description
"This module contains common yang definitions YANG definitions for the Network Topology Simulator.";
+ revision 2021-06-08 {
+ description
+ "Moved NTS_PROTOCOL_TYPE_BASE identities from nts-manager.";
+ reference
+ "O-RAN-SC SIM project";
+ }
revision 2021-03-26 {
description
"Added controller-protocol.";
"O-RAN-SC SIM project";
}
+ identity NTS_PROTOCOL_TYPE_BASE {
+ description
+ "Base identity for protocol.";
+ }
+
+ identity NTS_PROTOCOL_TYPE_NETCONF_SSH {
+ base NTS_PROTOCOL_TYPE_BASE;
+ description
+ "Identity for NETCONF SSH protocol.";
+ }
+
+ identity NTS_PROTOCOL_TYPE_NETCONF_TLS {
+ base NTS_PROTOCOL_TYPE_BASE;
+ description
+ "Identity for NETCONF TLS protocol.";
+ }
+
+ identity NTS_PROTOCOL_TYPE_FTP {
+ base NTS_PROTOCOL_TYPE_BASE;
+ description
+ "Identity for FTP protocol.";
+ }
+
+ identity NTS_PROTOCOL_TYPE_SFTP {
+ base NTS_PROTOCOL_TYPE_BASE;
+ description
+ "Identity for SFTP protocol.";
+ }
+
+ identity NTS_PROTOCOL_TYPE_HTTP {
+ base NTS_PROTOCOL_TYPE_BASE;
+ description
+ "Identity for HTTP protocol.";
+ }
+
+ identity NTS_PROTOCOL_TYPE_HTTPS {
+ base NTS_PROTOCOL_TYPE_BASE;
+ description
+ "Identity for HTTPS protocol.";
+ }
+
feature faults-status {
description
"This means that the server supports reporting back the number of faults that were generated";
"The protocol used for communication with the SDN Controller.";
}
leaf controller-ip {
- type inet:ip-address;
+ type inet:host;
description
"The IP address of the SDN Controller.";
}
"The protocol (HTTP / HTTPS) to be used to address the VES Collector.";
}
leaf ves-endpoint-ip {
- type inet:ip-address;
+ type inet:host;
description
"The IP address of the VES Collector.";
}
namespace "urn:o-ran-sc:params:xml:ns:yang:nts:network:function";
prefix ntsnf;
+ import ietf-inet-types {
+ prefix inet;
+ }
import nts-common {
prefix ntsc;
}
description
"This module contains YANG definitions for the Network Topology Simulator - Network Functions";
+ revision 2021-06-18 {
+ description
+ "Added test-list for NETCONF hardware delay emulation.";
+ reference
+ "O-RAN-SC SIM project";
+ }
+ revision 2021-06-14 {
+ description
+ "Added total loss network emulation RPC and NETCONF write-delay emulation.";
+ reference
+ "O-RAN-SC SIM project";
+ }
+ revision 2021-06-08 {
+ description
+ "Added more info and NETCONF latency emulation.";
+ reference
+ "O-RAN-SC SIM project";
+ }
revision 2021-05-17 {
description
"Added support for network emulation.";
}
}
+ rpc emulate-total-loss {
+ description
+ "Operation to emulate 100% loss in network packets. Operation will resume after specified timeout.";
+ input {
+ leaf timeout {
+ type uint32;
+ units "miliseconds (ms)";
+ description
+ "Period after which loss will stop being 100%.";
+ }
+ }
+ output {
+ uses ntsc:rpc-status-g;
+ }
+ }
+
container info {
config false;
description
description
"A bit-wise list with currently started features.";
}
+ leaf ssh-connections {
+ type uint8;
+ config false;
+ description
+ "The number of SSH Endpoints the network function instance exposes.";
+ }
+ leaf tls-connections {
+ type uint8;
+ config false;
+ description
+ "The number of TLS Endpoints the network function instance exposes.";
+ }
+ leaf hostname {
+ type string;
+ description
+ "Current network function hostname.";
+ }
+ list docker-ports {
+ key "port";
+ description
+ "The ports which are exposed inside the docker container implementing this network function instance.";
+ leaf port {
+ type inet:port-number;
+ description
+ "Port number.";
+ }
+ leaf protocol {
+ type identityref {
+ base ntsc:NTS_PROTOCOL_TYPE_BASE;
+ }
+ description
+ "Protocol attached to current port.";
+ }
+ }
}
container simulation {
description
"Delay packets based on packet size.";
}
}
+ container hardware-emulation {
+ description
+ "Container which encompasses the details of hardware emulation.";
+ container netconf-delay {
+ description
+ "Emulates delay on an operational leaf.";
+ leaf delay {
+ type uint32;
+ units "miliseconds (ms)";
+ default "0";
+ description
+ "Delay time to be set for get operation on test leaf.";
+ }
+ leaf get-test {
+ type uint32;
+ units "miliseconds (ms)";
+ config false;
+ description
+ "Read to test. Value represents emulated delay.";
+ }
+ leaf edit-test {
+ type uint32;
+ units "miliseconds (ms)";
+ description
+ "Writing non-null value will emulate a write-delay.";
+ }
+ list get-test-list {
+ config false;
+ description
+ "Read to test. Returned values are saved from edit-test-list.";
+ leaf value {
+ type string;
+ description
+ "Values from edit-test-list.";
+ }
+ }
+ list edit-test-list {
+ key "value";
+ description
+ "Write to test.";
+ leaf value {
+ type string;
+ description
+ "Unique values for testing.";
+ }
+ }
+ }
+ }
container sdn-controller {
description
"Groups details about the SDN Controller.";
---
-tag: 1.3.4
\ No newline at end of file
+tag: 1.3.5
\ No newline at end of file
---
-tag: 1.3.4
\ No newline at end of file
+tag: 1.3.5
\ No newline at end of file
description
"This module contains YANG definitions for the Network Topology Simulator - Manager.";
+ revision 2021-06-08 {
+ description
+ "Moved NTS_PROTOCOL_TYPE_BASE identities to nts-common.";
+ reference
+ "O-RAN-SC SIM project";
+ }
revision 2021-03-26 {
description
"Added NTS_PROTOCOL_TYPE_BASE identities and changed instance/networking container; also added multi-base port support.";
"O-RAN-SC SIM project";
}
- identity NTS_PROTOCOL_TYPE_BASE {
- description
- "Base identity for protocol.";
- }
-
- identity NTS_PROTOCOL_TYPE_NETCONF_SSH {
- base NTS_PROTOCOL_TYPE_BASE;
- description
- "Identity for NETCONF SSH protocol.";
- }
-
- identity NTS_PROTOCOL_TYPE_NETCONF_TLS {
- base NTS_PROTOCOL_TYPE_BASE;
- description
- "Identity for NETCONF TLS protocol.";
- }
-
- identity NTS_PROTOCOL_TYPE_FTP {
- base NTS_PROTOCOL_TYPE_BASE;
- description
- "Identity for FTP protocol.";
- }
-
- identity NTS_PROTOCOL_TYPE_SFTP {
- base NTS_PROTOCOL_TYPE_BASE;
- description
- "Identity for SFTP protocol.";
- }
-
- identity NTS_PROTOCOL_TYPE_HTTP {
- base NTS_PROTOCOL_TYPE_BASE;
- description
- "Identity for HTTP protocol.";
- }
-
- identity NTS_PROTOCOL_TYPE_HTTPS {
- base NTS_PROTOCOL_TYPE_BASE;
- description
- "Identity for HTTPS protocol.";
- }
-
typedef percent {
type decimal64 {
fraction-digits 2;
}
leaf protocol {
type identityref {
- base NTS_PROTOCOL_TYPE_BASE;
+ base ntsc:NTS_PROTOCOL_TYPE_BASE;
}
description
"Protocol attached to current port.";
}
leaf protocol {
type identityref {
- base NTS_PROTOCOL_TYPE_BASE;
+ base ntsc:NTS_PROTOCOL_TYPE_BASE;
}
description
"Protocol attached to current port.";
---
-tag: 1.3.4
\ No newline at end of file
+tag: 1.3.5
\ No newline at end of file
---
-tag: 1.3.4
\ No newline at end of file
+tag: 1.3.5
\ No newline at end of file
---
-tag: 1.3.4
\ No newline at end of file
+tag: 1.3.5
\ No newline at end of file
---
-tag: 1.3.4
\ No newline at end of file
+tag: 1.3.5
\ No newline at end of file
#include "core/xpath.h"
#include "core/framework.h"
+#include <sysrepo.h>
+#include <sysrepo/values.h>
+
static int app_common_populate_info(void);
+
static int app_common_populate_network_emulation_info(void);
-static int app_common_populate_network_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
+static int app_common_network_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
+
+static int app_common_hardware_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data);
+static int app_common_hardware_emulation_netconf_delay_oper_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
+
+static int app_common_emulate_total_loss_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data);
+
+static uint32_t netconf_delay = 0;
int app_common_init(void) {
assert_session();
return NTS_ERR_FAILED;
}
- rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_NETWORK_EMULATION_SCHEMA_XPATH, app_common_populate_network_emulation_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription);
+ rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_NETWORK_EMULATION_SCHEMA_XPATH, app_common_network_emulation_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription);
+ if(rc != SR_ERR_OK) {
+ log_error("could not subscribe to network emulation\n");
+ return NTS_ERR_FAILED;
+ }
+
+
+ rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH, app_common_hardware_emulation_change_cb, NULL, 2, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription);
if(rc != SR_ERR_OK) {
- log_error("could not subscribe to faults");
+ log_error("could not subscribe to hardware emulation changes\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_HE_NETCONF_DELAY_SCHEMA_XPATH, app_common_hardware_emulation_netconf_delay_oper_cb, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_OPER_MERGE, &session_subscription);
+ if(rc != SR_ERR_OK) {
+ log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
+ return 0;
+ }
+
+ rc = sr_rpc_subscribe(session_running, NTS_NF_RPC_EMULATE_TOTAL_LOSS_SCHEMA_XPATH, app_common_emulate_total_loss_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
+ if(rc != SR_ERR_OK) {
+ log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
return NTS_ERR_FAILED;
}
static int app_common_populate_info(void) {
int rc;
+ char aux[9];
+
+ struct lys_module *module = (struct lys_module *)ly_ctx_get_module(session_context, NTS_NETWORK_FUNCTION_MODULE, 0, 0);
+ if(module == 0) {
+ log_error("could not get module %s from context\n", NTS_NETWORK_FUNCTION_MODULE);
+ return NTS_ERR_FAILED;
+ }
+
+ struct lyd_node *info = lyd_new(0, module, "info");
+ if(info == 0) {
+ log_error("lyd_new failed\n");
+ return NTS_ERR_FAILED;
+ }
+ struct lyd_node *node;
if (framework_environment.nts.build_time && strlen(framework_environment.nts.build_time) > 0) {
- rc = sr_set_item_str(session_operational, NTS_NF_INFO_SCHEMA_XPATH"/build-time", framework_environment.nts.build_time, 0, 0);
- if(rc != SR_ERR_OK) {
- log_error("sr_set_item_str failed\n");
+ node = lyd_new_leaf(info, module, "build-time", framework_environment.nts.build_time);
+ if(node == 0) {
+ log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
}
- rc = sr_set_item_str(session_operational, NTS_NF_INFO_SCHEMA_XPATH"/version", framework_environment.nts.version, 0, 0);
+ node = lyd_new_leaf(info, module, "version", framework_environment.nts.version);
+ if(node == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ sprintf(aux, "%d", framework_environment.settings.ssh_connections);
+ node = lyd_new_leaf(info, module, "ssh-connections", aux);
+ if(node == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ sprintf(aux, "%d", framework_environment.settings.tls_connections);
+ node = lyd_new_leaf(info, module, "tls-connections", aux);
+ if(node == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ node = lyd_new_leaf(info, module, "hostname", framework_environment.settings.hostname);
+ if(node == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ //netconf ssh ports
+ for(int k = 0; k < framework_environment.settings.ssh_connections; k++) {
+ char value[128];
+
+ struct lyd_node *ports = lyd_new(info, module, "docker-ports");
+ if(ports == 0) {
+ log_error("lyd_new failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ sprintf(value, "%d", STANDARD_NETCONF_PORT + k);
+ if(lyd_new_leaf(ports, module, "port", value) == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ if(lyd_new_leaf(ports, module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+ }
+
+ //netconf tls ports
+ for(int k = 0; k < framework_environment.settings.tls_connections; k++) {
+ char value[128];
+
+ struct lyd_node *ports = lyd_new(info, module, "docker-ports");
+ if(ports == 0) {
+ log_error("lyd_new failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ sprintf(value, "%d", STANDARD_NETCONF_PORT + framework_environment.settings.ssh_connections + k);
+ if(lyd_new_leaf(ports, module, "port", value) == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ if(lyd_new_leaf(ports, module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+ }
+
+ //ftp ports
+ for(int k = 0; k < framework_environment.settings.ftp_connections; k++) {
+ char value[128];
+
+ struct lyd_node *ports = lyd_new(info, module, "docker-ports");
+ if(ports == 0) {
+ log_error("lyd_new failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ sprintf(value, "%d", STANDARD_FTP_PORT + k);
+ if(lyd_new_leaf(ports, module, "port", value) == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ if(lyd_new_leaf(ports, module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_FTP") == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+ }
+
+ //sftp ports
+ for(int k = 0; k < framework_environment.settings.sftp_connections; k++) {
+ char value[128];
+
+ struct lyd_node *ports = lyd_new(info, module, "docker-ports");
+ if(ports == 0) {
+ log_error("lyd_new failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ sprintf(value, "%d", STANDARD_SFTP_PORT + k);
+ if(lyd_new_leaf(ports, module, "port", value) == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ if(lyd_new_leaf(ports, module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_SFTP") == 0) {
+ log_error("lyd_new_leaf failed\n");
+ return NTS_ERR_FAILED;
+ }
+ }
+
+ rc = sr_edit_batch(session_operational, info, "merge");
if(rc != SR_ERR_OK) {
- log_error("sr_set_item_str failed\n");
+ log_error("sr_edit_batch failed: %s\n", sr_strerror(rc));
return NTS_ERR_FAILED;
}
return NTS_ERR_OK;
}
-static int app_common_populate_network_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
+static int app_common_network_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
if(event == SR_EV_UPDATE) {
sr_change_iter_t *it = 0;
return SR_ERR_OK;
}
+
+static int app_common_hardware_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
+ bool delay = false;
+
+ if(event == SR_EV_UPDATE) {
+ sr_change_iter_t *it = 0;
+ int rc = SR_ERR_OK;
+ sr_change_oper_t oper;
+ sr_val_t *old_value = 0;
+ sr_val_t *new_value = 0;
+
+ rc = sr_get_changes_iter(session, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH"//.", &it);
+ if(rc != SR_ERR_OK) {
+ log_error("sr_get_changes_iter failed\n");
+ return SR_ERR_VALIDATION_FAILED;
+ }
+
+ while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
+ if(new_value->xpath && (strstr(new_value->xpath, "/netconf-delay/edit-test-list"))) {
+ delay = true;
+ }
+ else if(new_value->xpath && (strstr(new_value->xpath, "/netconf-delay/edit-test"))) {
+ rc = sr_set_item_str(session, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH"/netconf-delay/edit-test", "0", 0, 0);
+ if(rc != SR_ERR_OK) {
+ log_error("sr_set_item failed\n");
+ return SR_ERR_VALIDATION_FAILED;
+ }
+
+ delay = true;
+ }
+
+ sr_free_val(old_value);
+ sr_free_val(new_value);
+ }
+
+ if(delay) {
+ delay = false;
+
+ int32_t sec = netconf_delay / 1000;
+ uint32_t usec = (netconf_delay % 1000) * 1000;
+
+ usleep(usec);
+ if(sec > 0) {
+ sleep(sec);
+ }
+ }
+
+ sr_free_change_iter(it);
+ }
+
+ if(event == SR_EV_DONE) {
+ sr_val_t *values = NULL;
+ size_t count = 0;
+
+ int rc = sr_get_items(session, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH"//.", 0, 0, &values, &count);
+ if (rc != SR_ERR_OK) {
+ log_error("sr_get_items failed\n");
+ return rc;
+ }
+
+ for(size_t i = 0; i < count; i++) {
+ if(strstr(values[i].xpath, "/netconf-delay/delay")) {
+ netconf_delay = values[i].data.uint32_val;
+ }
+ }
+
+ sr_free_values(values, count);
+ }
+
+ return SR_ERR_OK;
+}
+
+static int app_common_hardware_emulation_netconf_delay_oper_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+
+ char aux[9];
+ sprintf(aux, "%d", netconf_delay);
+ struct lyd_node *container = lyd_new_path(0, session_context, NTS_NF_HE_NETCONF_DELAY_SCHEMA_XPATH, 0, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(container == 0) {
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ //get test leaf
+ lyd_new_leaf(container, container->schema->module, "get-test", aux);
+
+ //get test list
+ sr_val_t *values = NULL;
+ size_t count = 0;
+ int rc = sr_get_items(session_running, NTS_NF_HE_NETCONF_DELAY_SCHEMA_XPATH"/edit-test-list/*", 0, 0, &values, &count);
+ if (rc != SR_ERR_OK) {
+ log_error("sr_get_items failed\n");
+ return rc;
+ }
+ for(size_t i = 0; i < count; i++) {
+ struct lyd_node *listitem = lyd_new(container, container->schema->module, "get-test-list");
+ if(listitem) {
+ lyd_new_leaf(listitem, container->schema->module, "value", values[i].data.string_val);
+ }
+ }
+
+ sr_free_values(values, count);
+
+
+
+ uint32_t sec = netconf_delay / 1000;
+ uint32_t usec = (netconf_delay % 1000) * 1000;
+
+ usleep(usec);
+ if(sec > 0) {
+ sleep(sec);
+ }
+
+ *parent = container;
+ return SR_ERR_OK;
+}
+
+static int app_common_emulate_total_loss_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+ int rc;
+
+ *output_cnt = 1;
+ rc = sr_new_values(*output_cnt, output);
+ if(SR_ERR_OK != rc) {
+ return rc;
+ }
+
+ rc = sr_val_set_xpath(output[0], NTS_NF_RPC_EMULATE_TOTAL_LOSS_SCHEMA_XPATH"/status");
+ if(SR_ERR_OK != rc) {
+ return rc;
+ }
+
+ sr_val_t *values = NULL;
+ size_t count = 0;
+
+ rc = sr_get_items(session, NTS_NF_NETWORK_EMULATION_SCHEMA_XPATH"//.", 0, 0, &values, &count);
+ if (rc != SR_ERR_OK) {
+ log_error("sr_get_items failed\n");
+ return rc;
+ }
+
+ network_emultation_settings_t s;
+ for(size_t i = 0; i < count; i++) {
+ if(strstr(values[i].xpath, "/limit")) {
+ s.limit = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/time")) {
+ s.delay.time = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/jitter")) {
+ s.delay.jitter = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/correlation")) {
+ s.delay.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/distribution")) {
+ s.delay.distribution = strdup(values[i].data.string_val);
+ }
+ else if(strstr(values[i].xpath, "/loss")) {
+ s.loss = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/corruption/percentage")) {
+ s.corruption.percentage = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/corruption/correlation")) {
+ s.corruption.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/duplication/percentage")) {
+ s.duplication.percentage = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/duplication/correlation")) {
+ s.duplication.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/reordering/percentage")) {
+ s.reordering.percentage = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/reordering/correlation")) {
+ s.reordering.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/rate")) {
+ s.rate = values[i].data.uint16_val;
+ }
+ }
+
+ uint16_t old_loss = s.loss;
+ s.loss = 100; //100 percent loss
+
+ sr_free_values(values, count);
+ if(network_emulation_update(&s) != NTS_ERR_OK) {
+ log_error("network_emulation_update() failed\n");
+ free(s.delay.distribution);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ int delay = input->data.uint32_val;
+ int32_t sec = delay / 1000;
+ uint32_t usec = (delay % 1000) * 1000;
+
+ usleep(usec);
+ if(sec > 0) {
+ sleep(sec);
+ }
+
+ s.loss = old_loss;
+ if(network_emulation_update(&s) != NTS_ERR_OK) {
+ log_error("network_emulation_update() failed\n");
+ free(s.delay.distribution);
+ return SR_ERR_OPERATION_FAILED;
+ }
+ free(s.delay.distribution);
+
+ rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+ return rc;
+}
char *leaf_path = strdup(strstr(new_value->xpath, "']/") + 3);
if(strcmp(leaf_path, "started-instances") == 0) {
new_oper->started_instances = new_value->data.uint16_val;
- rc = sr_set_item(session, old_value->xpath, old_value, 0);
- if(rc != SR_ERR_OK) {
- log_error("sr_set_item failed\n");
- return SR_ERR_VALIDATION_FAILED;
- }
+ // checkAL sysrepo v1.4.140 workaround
+ // rc = sr_set_item(session, old_value->xpath, old_value, 0);
+ // if(rc != SR_ERR_OK) {
+ // log_error("sr_set_item failed\n");
+ // return SR_ERR_VALIDATION_FAILED;
+ // }
}
else if(strcmp(leaf_path, "mounted-instances") == 0) {
new_oper->mounted_instances = new_value->data.uint16_val;
- rc = sr_set_item(session, old_value->xpath, old_value, 0);
- if(rc != SR_ERR_OK) {
- log_error("sr_set_item failed\n");
- return SR_ERR_VALIDATION_FAILED;
- }
+ // checkAL sysrepo v1.4.140 workaround
+ // rc = sr_set_item(session, old_value->xpath, old_value, 0);
+ // if(rc != SR_ERR_OK) {
+ // log_error("sr_set_item failed\n");
+ // return SR_ERR_VALIDATION_FAILED;
+ // }
}
else if(strcmp(leaf_path, "docker-instance-name") == 0) {
new_oper->docker_instance_name = strdup(nv);
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_NETCONF_SSH") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_NETCONF_TLS") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_FTP") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_FTP") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_FTP") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_FTP") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_SFTP") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_SFTP") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
return NTS_ERR_FAILED;
}
- if(lyd_new_leaf(ports, ports->schema->module, "protocol", "NTS_PROTOCOL_TYPE_SFTP") == 0) {
+ if(lyd_new_leaf(ports, ports->schema->module, "protocol", "nts-common:NTS_PROTOCOL_TYPE_SFTP") == 0) {
log_error("lyd_new_leaf failed\n");
return NTS_ERR_FAILED;
}
}
//ietf-netconf-monitoring schemas populate with modules and submodules (overwrite default Netopeer2 behaviour)
- rc = sr_oper_get_items_subscribe(session_running, IETF_NETCONF_MONITORING_MODULE, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, netconf_monitoring_state_schemas_cb, 0, SR_SUBSCR_DEFAULT, &session_subscription);
+ rc = sr_oper_get_items_subscribe(session_running, IETF_NETCONF_MONITORING_MODULE, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, netconf_monitoring_state_schemas_cb, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
if(rc != SR_ERR_OK) {
log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
return 0;
}
//nc-notifications overwrite
- rc = sr_oper_get_items_subscribe(session_running, NC_NOTIFICATIONS_MODULE, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, notifications_streams_cb, 0, SR_SUBSCR_DEFAULT, &session_subscription);
+ rc = sr_oper_get_items_subscribe(session_running, NC_NOTIFICATIONS_MODULE, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, notifications_streams_cb, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
if(rc != SR_ERR_OK) {
log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
return 0;
#include "core/framework.h"
#define GEN_KEY_SCRIPT "/home/netconf/.ssh/generate-ssh-keys.sh"
-#define KS_CERT_NAME "melacon_server_cert"
#define SERVER_PRIVATE_KEY_PATH "/home/netconf/.ssh/melacon.server.key"
#define SERVER_PUBLIC_KEY_PATH "/home/netconf/.ssh/melacon.server.key.pub.pem"
-#define SERVER_CERT_PATH "/home/netconf/.ssh/melacon.server.crt"
#define CA_CERT_PATH "/home/netconf/.ssh/ca.pem"
static int nc_config_netconf_port = STANDARD_NETCONF_PORT;
return NTS_ERR_FAILED;
}
- if (ssh_connections > 0) {
- rc = create_ssh_listen_endpoints(netconf_node, ssh_connections);
- if(rc != NTS_ERR_OK) {
- log_error("could not create %d SSH Listen endpoints on the NETCONF Server\n", ssh_connections);
- return NTS_ERR_FAILED;
- }
+ rc = create_ssh_listen_endpoints(netconf_node, ssh_connections);
+ if(rc != NTS_ERR_OK) {
+ log_error("could not create %d SSH Listen endpoints on the NETCONF Server\n", ssh_connections);
+ return NTS_ERR_FAILED;
}
// create the TLS endpoints in ietf-netconf-server
#define NTS_NF_VES_HEARTBEAT_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves/heartbeat-period"
#define NTS_NF_VES_PNF_REGISTRATION_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves/pnf-registration"
#define NTS_NF_NETWORK_EMULATION_SCHEMA_XPATH "/nts-network-function:simulation/network-emulation"
+#define NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH "/nts-network-function:simulation/hardware-emulation"
+#define NTS_NF_HE_NETCONF_DELAY_SCHEMA_XPATH "/nts-network-function:simulation/hardware-emulation/netconf-delay"
#define NTS_NF_VES_ENDPOINT_CONFIG_XPATH "/nts-network-function:simulation/ves-endpoint"
#define NTS_NF_SDN_CONTROLLER_CONFIG_XPATH "/nts-network-function:simulation/sdn-controller"
#define NTS_NF_RPC_FAULTS_CLEAR_SCHEMA_XPATH "/nts-network-function:clear-fault-counters"
#define NTS_NF_RPC_MANUAL_NOTIF_SCHEMA_XPATH "/nts-network-function:invoke-notification"
#define NTS_NF_RPC_FILE_READY_SCHEMA_XPATH "/nts-network-function:invoke-ves-pm-file-ready"
-#define NTS_NF_RPC_SET_NETWORK_LATENCY_SCHEMA_XPATH "/nts-network-function:set-network-latency"
+#define NTS_NF_RPC_EMULATE_TOTAL_LOSS_SCHEMA_XPATH "/nts-network-function:emulate-total-loss"
#define IETF_KEYSTORE_MODULE "ietf-keystore"
#define IETF_KEYSTORE_SCHEMA_XPATH "/ietf-keystore:keystore"
#define IETF_NETCONF_SERVER_CH_SSH_TCP_CLIENT_SCHEMA_XPATH "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/tcp-client-parameters"
#define IETF_NETCONF_SERVER_CH_SSH_SERVER_PARAMS_SCEHMA_XPATH "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-ssh']/ssh/ssh-server-parameters"
#define IETF_NETCONF_SERVER_CH_CONN_PERSISTENT_SCHEMA_XPATH "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/connection-type/persistent"
+#define IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-tls']/tls/tcp-client-parameters"
+#define IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH "/ietf-netconf-server:netconf-server/call-home/netconf-client[name='default-client']/endpoints/endpoint[name='callhome-tls']/tls/tls-server-parameters"
+
#define IETF_NETCONF_SERVER_SSH_TCP_SERVER_PARAM_SCHEMA_XPATH "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/tcp-server-parameters"
#define IETF_NETCONF_SERVER_SSH_SERVER_PARAM_SCHEMA_XPATH "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/ssh/ssh-server-parameters"
#define IETF_NETCONF_SERVER_TLS_TCP_SERVER_PARAM_SCHEMA_XPATH "/ietf-netconf-server:netconf-server/listen/endpoint[name='%s']/tls/tcp-server-parameters"
#include "core/framework.h"
#include "core/xpath.h"
-#define NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\",\"odl-netconf-callhome-server:ssh-host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf!\"]}}]}"
+#define NETCONF_SSH_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\", \"odl-netconf-callhome-server:ssh-client-params\": {\"odl-netconf-callhome-server:host-key\":\"%s\",\"odl-netconf-callhome-server:credentials\":{\"odl-netconf-callhome-server:username\":\"netconf\",\"odl-netconf-callhome-server:passwords\":[\"netconf!\"]}}}]}"
+#define NETCONF_TLS_CALLHOME_CURL_SEND_PAYLOAD_FORMAT "{\"odl-netconf-callhome-server:device\":[{\"odl-netconf-callhome-server:unique-id\":\"%s\", \"odl-netconf-callhome-server:tls-client-params\": {\"odl-netconf-callhome-server:certificate-id\":\"%s\",\"odl-netconf-callhome-server:key-id\":\"%s\"}}]}"
+#define NETCONF_TRUSTED_CERTIFICATE_CURL_SEND_PAYLOAD_FORMAT "{\"input\":{\"trusted-certificate\":[{\"name\":\"%s\",\"certificate\":\"%s\"}]}}"
static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node);
static int create_tls_callhome_endpoint(sr_session_ctx_t *current_session, struct lyd_node *netconf_node);
-static int send_odl_callhome_configuration(sr_session_ctx_t *current_session);
+static int send_odl_add_trusted_certificate(sr_session_ctx_t *current_session);
+static int send_odl_callhome_configuration(sr_session_ctx_t *current_session, bool is_tls);
static int netconf_call_home_status = 0;
return NTS_ERR_FAILED;
}
- rc = create_ssh_callhome_endpoint(current_session, netconf_node);
- if(rc != NTS_ERR_OK) {
- log_error("could not create SSH CallHome endpoint on the NETCONF Server\n");
+ controller_details_t *controller = controller_details_get(current_session);
+ if(controller == 0) {
+ log_error("controller_details_get failed\n");
return NTS_ERR_FAILED;
}
- rc = create_tls_callhome_endpoint(current_session, netconf_node);
- if(rc != NTS_ERR_OK) {
- log_error("could not create TLS CallHome endpoint on the NETCONF Server\n");
- return NTS_ERR_FAILED;
+ if (controller->nc_callhome_port == 4335) {
+ // port is CallHome via TLS
+ rc = create_tls_callhome_endpoint(current_session, netconf_node);
+ if(rc != NTS_ERR_OK) {
+ log_error("could not create TLS CallHome endpoint on the NETCONF Server\n");
+ controller_details_free(controller);
+ return NTS_ERR_FAILED;
+ }
+ }
+ else {
+ // port is CallHome via SSH
+ rc = create_ssh_callhome_endpoint(current_session, netconf_node);
+ if(rc != NTS_ERR_OK) {
+ log_error("could not create SSH CallHome endpoint on the NETCONF Server\n");
+ controller_details_free(controller);
+ return NTS_ERR_FAILED;
+ }
}
+ controller_details_free(controller);
rc = sr_edit_batch(current_session, netconf_node, "merge");
if(rc != SR_ERR_OK) {
return NTS_ERR_FAILED;
}
-
struct lyd_node *rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_SSH_TCP_CLIENT_SCHEMA_XPATH"/keepalives/idle-time", "1", 0, LYD_PATH_OPT_NOPARENTRET);
if(rcl == 0) {
log_error("could not created yang path\n");
return NTS_ERR_FAILED;
}
- int rc = send_odl_callhome_configuration(current_session);
+ int rc = send_odl_callhome_configuration(current_session, false);
if(rc != NTS_ERR_OK) {
log_add_verbose(2, "could not send ODL Call Home configuration.\n");
}
assert(current_session);
assert(netconf_node);
- // checkAS future usage, TLS endpoint yet supported in ODL
+ controller_details_t *controller = controller_details_get(current_session);
+ if(controller == 0) {
+ log_error("controller_details_get failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ char *controller_ip = strdup(controller->ip);
+ uint16_t controller_callhome_port = controller->nc_callhome_port;
+ controller_details_free(controller);
+
+ if(controller_ip == 0) {
+ log_error("strdup failed\n");
+ return NTS_ERR_FAILED;
+ }
+ struct lyd_node *rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/keepalives/idle-time", "1", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/keepalives/max-probes", "10", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/keepalives/probe-interval", "5", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/remote-address", controller_ip, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ free(controller_ip);
+ return NTS_ERR_FAILED;
+ }
+ free(controller_ip);
+
+ char port[20];
+ sprintf(port, "%d", controller_callhome_port);
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_TCP_CLIENT_SCHEMA_XPATH"/remote-port", port, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/server-identity/keystore-reference/asymmetric-key", KS_KEY_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/server-identity/keystore-reference/certificate", KS_CERT_NAME, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/required", "", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/ca-certs", "cacerts", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/client-certs", "clientcerts", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/fingerprint", "02:E9:38:1F:F6:8B:62:DE:0A:0B:C5:03:81:A8:03:49:A0:00:7F:8B:F3", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, session_context, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/map-type", "ietf-x509-cert-to-name:specified", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_TLS_SERVER_PARAMS_SCEHMA_XPATH"/client-authentication/cert-maps/cert-to-name[id='1']/name", "netconf", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ rcl = lyd_new_path(netconf_node, 0, IETF_NETCONF_SERVER_CH_CONN_PERSISTENT_SCHEMA_XPATH, "", 0, LYD_PATH_OPT_NOPARENTRET);
+ if(rcl == 0) {
+ log_error("could not created yang path\n");
+ return NTS_ERR_FAILED;
+ }
+
+ int rc = send_odl_callhome_configuration(current_session, true);
+ if(rc != NTS_ERR_OK) {
+ log_add_verbose(2, "could not send ODL Call Home configuration.\n");
+ }
+
return NTS_ERR_OK;
}
-static int send_odl_callhome_configuration(sr_session_ctx_t *current_session) {
+static int send_odl_add_trusted_certificate(sr_session_ctx_t *current_session) {
assert(current_session);
- char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
- if(public_ssh_key == 0) {
- log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH);
+ char *server_cert = read_key(SERVER_CERT_PATH);
+ if(server_cert == 0) {
+ log_error("could not read the serevr certificate from file %s\n", SERVER_CERT_PATH);
return NTS_ERR_FAILED;
}
- char *ssh_key_string;
- ssh_key_string = strtok(public_ssh_key, " ");
- ssh_key_string = strtok(NULL, " ");
- ssh_key_string[strlen(ssh_key_string) - 1] = 0; // trim the newline character
+ char *odl_trusted_certificate_payload = 0;
+ asprintf(&odl_trusted_certificate_payload, NETCONF_TRUSTED_CERTIFICATE_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, server_cert);
+ if(odl_trusted_certificate_payload == 0) {
+ log_error("bad asprintf\n");
+ return NTS_ERR_FAILED;
+ }
+ free(server_cert);
+
+ controller_details_t *controller = controller_details_get(current_session);
+ if(controller == 0) {
+ log_error("controller_details_get failed\n");
+ return NTS_ERR_FAILED;
+ }
+
+ char *url = 0;
+ asprintf(&url, "%s/rests/operations/netconf-keystore:add-trusted-certificate", controller->base_url);
+ if(url == 0) {
+ log_error("bad asprintf\n");
+ controller_details_free(controller);
+ return NTS_ERR_FAILED;
+ }
+
+ int rc = http_request(url, controller->username, controller->password, "POST", odl_trusted_certificate_payload, 0, 0);
+ if(rc != NTS_ERR_OK) {
+ log_error("http_request failed\n");
+ }
+
+ free(url);
+ controller_details_free(controller);
+ free(odl_trusted_certificate_payload);
+
+ return rc;
+}
+
+static int send_odl_callhome_configuration(sr_session_ctx_t *current_session, bool is_tls) {
+ assert(current_session);
- // checkAS we have hardcoded here the username and password of the NETCONF Server
char *odl_callhome_payload = 0;
- asprintf(&odl_callhome_payload, NETCONF_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, ssh_key_string);
- free(public_ssh_key);
+ if (!is_tls) {
+ char *public_ssh_key = read_key(SERVER_PUBLIC_SSH_KEY_PATH);
+ if(public_ssh_key == 0) {
+ log_error("could not read the public ssh key from file %s\n", SERVER_PUBLIC_SSH_KEY_PATH);
+ return NTS_ERR_FAILED;
+ }
+
+ char *ssh_key_string;
+ ssh_key_string = strtok(public_ssh_key, " ");
+ ssh_key_string = strtok(NULL, " ");
+ ssh_key_string[strlen(ssh_key_string) - 1] = 0; // trim the newline character
+
+ // checkAS we have hardcoded here the username and password of the NETCONF Server
+ asprintf(&odl_callhome_payload, NETCONF_SSH_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, ssh_key_string);
+ free(public_ssh_key);
+ }
+ else {
+ int ret = send_odl_add_trusted_certificate(current_session);
+ if (ret != NTS_ERR_OK) {
+ log_error("Could not send trusted certificate to ODL.");
+ return NTS_ERR_FAILED;
+ }
+ // checkAS we have hardcoded here the private key of ODL
+ asprintf(&odl_callhome_payload, NETCONF_TLS_CALLHOME_CURL_SEND_PAYLOAD_FORMAT, framework_environment.settings.hostname, framework_environment.settings.hostname, "ODL_private_key_0");
+ }
+
if(odl_callhome_payload == 0) {
log_error("bad asprintf\n");
return NTS_ERR_FAILED;
#include "utils/nts_utils.h"
#include <stdio.h>
#include <assert.h>
+#include <pthread.h>
#include "core/session.h"
#include "core/framework.h"
#include "core/xpath.h"
static int ves_pnf_sequence_number = 0;
-
+static pthread_t ves_pnf_registration_thread;
+static void* ves_pnf_registration_thread_routine(void *arg);
static int ves_pnf_registration_send(sr_session_ctx_t *current_session, const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, nts_mount_point_addressing_method_t mp, bool is_tls);
static cJSON* ves_create_pnf_registration_fields(const char *nf_ip_v4_address, const char *nf_ip_v6_address, int nf_port, bool is_tls);
sr_val_t *value = 0;
int rc = NTS_ERR_OK;
bool pnf_registration_enabled = false;
- rc = sr_get_item(current_session, NTS_NF_VES_PNF_REGISTRATION_SCHEMA_XPATH, 0, &value);
- if(rc == SR_ERR_OK) {
- pnf_registration_enabled = value->data.bool_val;
- sr_free_val(value);
- }
- else if(rc != SR_ERR_NOT_FOUND) {
- log_error("sr_get_item failed\n");
- return NTS_ERR_FAILED;
+ if(strlen(framework_environment.nts.nf_standalone_start_features)) {
+ pnf_registration_enabled = true;
}
else {
- // if value is not set yet, feature enable means we want to start pnf-registration
- if(strlen(framework_environment.nts.nf_standalone_start_features)) {
- pnf_registration_enabled = true;
+ rc = sr_get_item(current_session, NTS_NF_VES_PNF_REGISTRATION_SCHEMA_XPATH, 0, &value);
+ if(rc == SR_ERR_OK) {
+ pnf_registration_enabled = value->data.bool_val;
+ sr_free_val(value);
+ }
+ else if(rc != SR_ERR_NOT_FOUND) {
+ log_error("sr_get_item failed\n");
+ return NTS_ERR_FAILED;
}
}
return NTS_ERR_OK;
}
+ if(pthread_create(&ves_pnf_registration_thread, 0, ves_pnf_registration_thread_routine, current_session)) {
+ log_error("could not create thread for heartbeat\n");
+ return NTS_ERR_FAILED;
+ }
+
+ return NTS_ERR_OK;
+}
+
+static void* ves_pnf_registration_thread_routine(void *arg) {
+ sr_session_ctx_t *current_session = arg;
+
int ssh_base_port = 0;
int tls_base_port = 0;
char nf_ip_v4_address[128];
nts_mount_point_addressing_method_t mp = nts_mount_point_addressing_method_get(current_session);
if(mp == UNKNOWN_MAPPING) {
log_error("mount-point-addressing-method failed\n");
- return NTS_ERR_FAILED;
+ return (void*)NTS_ERR_FAILED;
}
else if(mp == DOCKER_MAPPING) {
if (framework_environment.settings.ip_v4 != 0) {
tls_base_port = framework_environment.host.tls_base_port;
}
+ uint32_t total_regs = 0;
+ struct regs_s {
+ bool sent;
+ uint16_t port;
+ bool is_tls;
+ } *regs;
+
+ regs = (struct regs_s *)malloc(sizeof(struct regs_s) * (1 + framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections));
+ if(regs == 0) {
+ log_error("malloc failed\n");
+ return (void*)NTS_ERR_FAILED;
+ }
+
+
if((framework_environment.settings.ssh_connections + framework_environment.settings.tls_connections) > 1) {
for(int port = ssh_base_port; port < ssh_base_port + framework_environment.settings.ssh_connections; port++) {
- int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, false);
- if(rc != NTS_ERR_OK) {
- log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s and port=%d and protocol SSH\n", nf_ip_v4_address, nf_ip_v6_address, port);
- }
+ regs[total_regs].sent = false;
+ regs[total_regs].port = port;
+ regs[total_regs].is_tls = false;
+ total_regs++;
}
for(int port = tls_base_port; port < tls_base_port + framework_environment.settings.tls_connections; port++) {
- int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, true);
- if(rc != NTS_ERR_OK) {
- log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s and port=%d and protocol TLS\n", nf_ip_v4_address, nf_ip_v6_address, port);
- }
+ regs[total_regs].sent = false;
+ regs[total_regs].port = port;
+ regs[total_regs].is_tls = true;
+ total_regs++;
}
}
else {
bool tls;
- int port;
if(framework_environment.settings.tls_connections == 0) {
tls = false;
- port = ssh_base_port;
}
else {
tls = true;
- port = tls_base_port;
}
- int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, 0, mp, tls);
- if(rc != NTS_ERR_OK) {
- log_error("could not send pnfRegistration message for IPv4=%s and IPv6=%s\n", nf_ip_v4_address, nf_ip_v6_address, port);
+ regs[total_regs].sent = false;
+ regs[total_regs].port = 0;
+ regs[total_regs].is_tls = tls;
+ total_regs++;
+ }
+
+ uint32_t remaining = total_regs;
+ while(remaining) {
+ for(int i = 0; i < total_regs; i++) {
+ if(regs[i].sent == false) {
+ uint16_t port = regs[i].port;
+ bool is_tls = regs[i].is_tls;
+ int rc = ves_pnf_registration_send(current_session, nf_ip_v4_address, nf_ip_v6_address, port, mp, is_tls);
+ if(rc == NTS_ERR_OK) {
+ remaining--;
+ regs[i].sent = true;
+ }
+ else {
+ log_error("pnfRegistration failed for ipv4=%s ipv6=%s port=%d is_tls=%d\n", nf_ip_v4_address, nf_ip_v6_address, port, is_tls);
+ }
+ }
+ }
+ if(remaining) {
+ log_error("pnfRegistration could not register all ports; retrying in 5 seconds...\n");
+ sleep(5);
}
}
-
- log_add_verbose(2, "PNF registration enabled\n");
+ free(regs);
+ log_add_verbose(2, "PNF registration finished\n");
ves_pnf_registration_status = 1;
return NTS_ERR_OK;
#define STANDARD_SFTP_PORT 22
#define KS_KEY_NAME "melacon_server_key"
+#define KS_CERT_NAME "melacon_server_cert"
#define SERVER_PUBLIC_SSH_KEY_PATH "/home/netconf/.ssh/melacon.server.key.pub"
+#define SERVER_CERT_PATH "/home/netconf/.ssh/melacon.server.crt"
//filesystem functions
bool dir_exists(const char *path);