From fd9a6164f9cff51682fcebe77f53d99b8d882bc7 Mon Sep 17 00:00:00 2001 From: Alex Stancu Date: Tue, 5 Oct 2021 17:22:44 +0300 Subject: [PATCH] Add NETCONF CallHome via TLS feature. Issue-ID: SIM-80 Change-Id: I6ed024760eb430146fb2e94b244ab7c6241e75d4 Signed-off-by: Alex Stancu --- ntsimulator/deploy/base/yang/nts-common.yang | 51 ++- .../deploy/base/yang/nts-network-function.yang | 119 +++++++ ntsimulator/deploy/blank/container-tag.yaml | 2 +- ntsimulator/deploy/nts-manager/container-tag.yaml | 2 +- .../deploy/nts-manager/yang/nts-manager.yang | 51 +-- ntsimulator/deploy/o-ran-du/container-tag.yaml | 2 +- ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml | 2 +- ntsimulator/deploy/o-ran/container-tag.yaml | 2 +- ntsimulator/deploy/x-ran/container-tag.yaml | 2 +- ntsimulator/ntsim-ng/core/app/app_common.c | 387 ++++++++++++++++++++- ntsimulator/ntsim-ng/core/app/manager.c | 22 +- ntsimulator/ntsim-ng/core/app/manager_sysrepo.c | 16 +- ntsimulator/ntsim-ng/core/app/network_function.c | 4 +- ntsimulator/ntsim-ng/core/nc_config.c | 12 +- ntsimulator/ntsim-ng/core/xpath.h | 7 +- .../features/netconf_call_home/netconf_call_home.c | 226 ++++++++++-- .../ves_pnf_registration/ves_pnf_registration.c | 103 ++++-- ntsimulator/ntsim-ng/utils/sys_utils.h | 2 + 18 files changed, 871 insertions(+), 141 deletions(-) diff --git a/ntsimulator/deploy/base/yang/nts-common.yang b/ntsimulator/deploy/base/yang/nts-common.yang index 86d7b3e..960aea8 100644 --- a/ntsimulator/deploy/base/yang/nts-common.yang +++ b/ntsimulator/deploy/base/yang/nts-common.yang @@ -18,6 +18,12 @@ module nts-common { 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."; @@ -55,6 +61,47 @@ module nts-common { "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"; @@ -281,7 +328,7 @@ module nts-common { "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."; } @@ -326,7 +373,7 @@ module nts-common { "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."; } diff --git a/ntsimulator/deploy/base/yang/nts-network-function.yang b/ntsimulator/deploy/base/yang/nts-network-function.yang index 69c39fc..dbde984 100644 --- a/ntsimulator/deploy/base/yang/nts-network-function.yang +++ b/ntsimulator/deploy/base/yang/nts-network-function.yang @@ -3,6 +3,9 @@ module nts-network-function { 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; } @@ -21,6 +24,24 @@ module nts-network-function { 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."; @@ -153,6 +174,22 @@ module nts-network-function { } } + 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 @@ -172,6 +209,40 @@ module nts-network-function { 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 @@ -322,6 +393,54 @@ module nts-network-function { "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."; diff --git a/ntsimulator/deploy/blank/container-tag.yaml b/ntsimulator/deploy/blank/container-tag.yaml index edd6735..b21c92a 100644 --- a/ntsimulator/deploy/blank/container-tag.yaml +++ b/ntsimulator/deploy/blank/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.3.4 \ No newline at end of file +tag: 1.3.5 \ No newline at end of file diff --git a/ntsimulator/deploy/nts-manager/container-tag.yaml b/ntsimulator/deploy/nts-manager/container-tag.yaml index edd6735..b21c92a 100644 --- a/ntsimulator/deploy/nts-manager/container-tag.yaml +++ b/ntsimulator/deploy/nts-manager/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.3.4 \ No newline at end of file +tag: 1.3.5 \ No newline at end of file diff --git a/ntsimulator/deploy/nts-manager/yang/nts-manager.yang b/ntsimulator/deploy/nts-manager/yang/nts-manager.yang index 5f7bc14..0ecdd9f 100644 --- a/ntsimulator/deploy/nts-manager/yang/nts-manager.yang +++ b/ntsimulator/deploy/nts-manager/yang/nts-manager.yang @@ -21,6 +21,12 @@ module nts-manager { 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."; @@ -52,47 +58,6 @@ module nts-manager { "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; @@ -134,7 +99,7 @@ module nts-manager { } leaf protocol { type identityref { - base NTS_PROTOCOL_TYPE_BASE; + base ntsc:NTS_PROTOCOL_TYPE_BASE; } description "Protocol attached to current port."; @@ -156,7 +121,7 @@ module nts-manager { } leaf protocol { type identityref { - base NTS_PROTOCOL_TYPE_BASE; + base ntsc:NTS_PROTOCOL_TYPE_BASE; } description "Protocol attached to current port."; diff --git a/ntsimulator/deploy/o-ran-du/container-tag.yaml b/ntsimulator/deploy/o-ran-du/container-tag.yaml index edd6735..b21c92a 100644 --- a/ntsimulator/deploy/o-ran-du/container-tag.yaml +++ b/ntsimulator/deploy/o-ran-du/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.3.4 \ No newline at end of file +tag: 1.3.5 \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml b/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml index edd6735..b21c92a 100644 --- a/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml +++ b/ntsimulator/deploy/o-ran-ru-fh/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.3.4 \ No newline at end of file +tag: 1.3.5 \ No newline at end of file diff --git a/ntsimulator/deploy/o-ran/container-tag.yaml b/ntsimulator/deploy/o-ran/container-tag.yaml index edd6735..b21c92a 100644 --- a/ntsimulator/deploy/o-ran/container-tag.yaml +++ b/ntsimulator/deploy/o-ran/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.3.4 \ No newline at end of file +tag: 1.3.5 \ No newline at end of file diff --git a/ntsimulator/deploy/x-ran/container-tag.yaml b/ntsimulator/deploy/x-ran/container-tag.yaml index edd6735..b21c92a 100644 --- a/ntsimulator/deploy/x-ran/container-tag.yaml +++ b/ntsimulator/deploy/x-ran/container-tag.yaml @@ -1,2 +1,2 @@ --- -tag: 1.3.4 \ No newline at end of file +tag: 1.3.5 \ No newline at end of file diff --git a/ntsimulator/ntsim-ng/core/app/app_common.c b/ntsimulator/ntsim-ng/core/app/app_common.c index e74b655..c4b6c1a 100644 --- a/ntsimulator/ntsim-ng/core/app/app_common.c +++ b/ntsimulator/ntsim-ng/core/app/app_common.c @@ -28,9 +28,20 @@ #include "core/xpath.h" #include "core/framework.h" +#include +#include + 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(); @@ -49,9 +60,28 @@ int app_common_init(void) { 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; } @@ -60,18 +90,146 @@ int app_common_init(void) { 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; } @@ -174,7 +332,7 @@ static int app_common_populate_network_emulation_info(void) { 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; @@ -293,3 +451,214 @@ static int app_common_populate_network_emulation_change_cb(sr_session_ctx_t *ses 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; +} diff --git a/ntsimulator/ntsim-ng/core/app/manager.c b/ntsimulator/ntsim-ng/core/app/manager.c index f7ec705..179c7b6 100644 --- a/ntsimulator/ntsim-ng/core/app/manager.c +++ b/ntsimulator/ntsim-ng/core/app/manager.c @@ -203,19 +203,21 @@ static int manager_change_cb(sr_session_ctx_t *session, const char *module_name, 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); diff --git a/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c b/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c index d41ea56..b32f48c 100644 --- a/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c +++ b/ntsimulator/ntsim-ng/core/app/manager_sysrepo.c @@ -309,7 +309,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -327,7 +327,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -349,7 +349,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -367,7 +367,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -389,7 +389,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -407,7 +407,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -429,7 +429,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } @@ -447,7 +447,7 @@ int manager_sr_populate_networking(struct lyd_node *parent, const manager_networ 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; } diff --git a/ntsimulator/ntsim-ng/core/app/network_function.c b/ntsimulator/ntsim-ng/core/app/network_function.c index 2a5ff0f..d7909c4 100644 --- a/ntsimulator/ntsim-ng/core/app/network_function.c +++ b/ntsimulator/ntsim-ng/core/app/network_function.c @@ -99,14 +99,14 @@ int network_function_run(void) { } //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; diff --git a/ntsimulator/ntsim-ng/core/nc_config.c b/ntsimulator/ntsim-ng/core/nc_config.c index 7700595..963133b 100644 --- a/ntsimulator/ntsim-ng/core/nc_config.c +++ b/ntsimulator/ntsim-ng/core/nc_config.c @@ -33,10 +33,8 @@ #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; @@ -635,12 +633,10 @@ static int configure_endpoints_connections(sr_session_ctx_t *session) { 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 diff --git a/ntsimulator/ntsim-ng/core/xpath.h b/ntsimulator/ntsim-ng/core/xpath.h index 3c57770..cf65ebc 100644 --- a/ntsimulator/ntsim-ng/core/xpath.h +++ b/ntsimulator/ntsim-ng/core/xpath.h @@ -40,6 +40,8 @@ #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" @@ -48,7 +50,7 @@ #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" @@ -71,6 +73,9 @@ #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" diff --git a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c index a56e45b..59b2e58 100644 --- a/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c +++ b/ntsimulator/ntsim-ng/features/netconf_call_home/netconf_call_home.c @@ -30,11 +30,14 @@ #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; @@ -73,17 +76,31 @@ int netconf_call_home_feature_start(sr_session_ctx_t *current_session) { 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) { @@ -129,7 +146,6 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc 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"); @@ -202,7 +218,7 @@ static int create_ssh_callhome_endpoint(sr_session_ctx_t *current_session, struc 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"); } @@ -214,30 +230,194 @@ static int create_tls_callhome_endpoint(sr_session_ctx_t *current_session, struc 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; diff --git a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c index 71d62aa..691a64d 100644 --- a/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c +++ b/ntsimulator/ntsim-ng/features/ves_pnf_registration/ves_pnf_registration.c @@ -25,13 +25,15 @@ #include "utils/nts_utils.h" #include #include +#include #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); @@ -49,19 +51,18 @@ int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) { 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; } } @@ -70,6 +71,17 @@ int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) { 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]; @@ -81,7 +93,7 @@ int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) { 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) { @@ -106,40 +118,73 @@ int ves_pnf_registration_feature_start(sr_session_ctx_t *current_session) { 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; diff --git a/ntsimulator/ntsim-ng/utils/sys_utils.h b/ntsimulator/ntsim-ng/utils/sys_utils.h index f5c2cf2..eea514c 100644 --- a/ntsimulator/ntsim-ng/utils/sys_utils.h +++ b/ntsimulator/ntsim-ng/utils/sys_utils.h @@ -26,7 +26,9 @@ #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); -- 2.16.6