1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "network_function.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "utils/nts_utils.h"
29 #include <sysrepo/values.h>
30 #include <libnetconf2/netconf.h>
32 #include "core/framework.h"
33 #include "core/context.h"
34 #include "core/session.h"
35 #include "core/datastore/populate.h"
37 #include "core/faults/faults.h"
39 #include "features/ves_pnf_registration/ves_pnf_registration.h"
40 #include "features/ves_heartbeat/ves_heartbeat.h"
41 #include "features/ves_file_ready/ves_file_ready.h"
42 #include "features/manual_notification/manual_notification.h"
43 #include "features/netconf_call_home/netconf_call_home.h"
44 #include "features/web_cut_through/web_cut_through.h"
46 #include "app_common.h"
48 #define NF_FUNCTION_CONTROL_BUFFER_LENGTH 32
50 #define IETF_NETCONF_MONITORING_MODULE "ietf-netconf-monitoring"
51 #define IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH "/ietf-netconf-monitoring:netconf-state/schemas"
53 #define NC_NOTIFICATIONS_MODULE "nc-notifications"
54 #define NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH "/nc-notifications:netconf/streams"
56 #define NTS_NETWORK_FUNCTION_MODULE "nts-network-function"
57 #define NTS_NETWORK_FUNCTION_SCHEMA_XPATH "/nts-network-function:simulation/network-function"
59 #define POPULATE_RPC_SCHEMA_XPATH "/nts-network-function:datastore-populate"
60 #define FEATURE_CONTROL_SCHEMA_XPATH "/nts-network-function:feature-control"
61 #define FAULTS_CLEAR_SCHEMA_XPATH "/nts-network-function:clear-fault-counters"
62 #define FAULTS_LIST_SCHEMA_XPATH "/nts-network-function:simulation/network-function/fault-generation"
63 #define FAULTS_COUNT_LIST_SCHEMA_XPATH "/nts-network-function:simulation/network-function/fault-generation/fault-count"
64 #define FAULTS_NC_ENABLED_SCHEMA_XPATH "/nts-network-function:simulation/network-function/netconf/faults-enabled"
65 #define FAULTS_VES_ENABLED_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves/faults-enabled"
67 #define STARTED_FEATURES_LIST_SCHEMA_XPATH "/nts-network-function:info/started-features"
69 static int netconf_monitoring_state_schemas_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
70 static int notifications_streams_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data);
72 static int network_function_populate_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);
73 static int network_function_feature_control_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);
74 static int network_function_faults_clear_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);
75 static int network_function_faults_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);
76 static int network_function_faults_count_get_items_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);
78 static int network_function_started_features_get_items_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);
80 static int network_function_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);
82 static int faults_update_config(sr_session_ctx_t *session); //not protected by lock
83 static void *faults_thread_routine(void *arg);
85 static pthread_mutex_t nf_function_control_lock;
86 static char *nf_function_control_buffer[NF_FUNCTION_CONTROL_BUFFER_LENGTH];
87 static int nf_function_control_buffer_in;
88 static int nf_function_control_buffer_out;
90 static pthread_t faults_thread;
91 static pthread_mutex_t faults_lock;
93 int network_function_run(void) {
96 nf_function_control_buffer_in = 0;
97 nf_function_control_buffer_out = 0;
99 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"running as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET);
101 int rc = app_common_init();
102 if(rc != NTS_ERR_OK) {
103 log_error("app_common_init failed\n");
104 return NTS_ERR_FAILED;
107 if(strlen(framework_environment.nts.nf_standalone_start_features)) {
108 rc = nts_utils_populate_info(session_running, framework_environment.nts.function_type);
109 if(rc != NTS_ERR_OK) {
110 log_error("nts_utils_populate_info failed\n");
111 return NTS_ERR_FAILED;
115 if(pthread_mutex_init(&nf_function_control_lock, NULL) != 0) {
116 log_error("mutex init has failed\n");
117 return NTS_ERR_FAILED;
120 //ietf-netconf-monitoring schemas populate with modules and submodules (overwrite default Netopeer2 behaviour)
121 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);
122 if(rc != SR_ERR_OK) {
123 log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
127 //nc-notifications overwrite
128 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);
129 if(rc != SR_ERR_OK) {
130 log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
135 rc = sr_rpc_subscribe(session_running, POPULATE_RPC_SCHEMA_XPATH, network_function_populate_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
136 if(rc != SR_ERR_OK) {
137 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
138 return NTS_ERR_FAILED;
142 rc = sr_rpc_subscribe(session_running, FEATURE_CONTROL_SCHEMA_XPATH, network_function_feature_control_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
143 if(rc != SR_ERR_OK) {
144 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
145 return NTS_ERR_FAILED;
149 rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, FAULTS_LIST_SCHEMA_XPATH, network_function_faults_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
150 if(rc != SR_ERR_OK) {
151 log_error("could not subscribe to faults");
155 rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, FAULTS_COUNT_LIST_SCHEMA_XPATH, network_function_faults_count_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription);
156 if(rc != SR_ERR_OK) {
157 log_error("could not subscribe to oper faults: %s\n", sr_strerror(rc));
161 rc = sr_rpc_subscribe(session_running, FAULTS_CLEAR_SCHEMA_XPATH, network_function_faults_clear_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
162 if(rc != SR_ERR_OK) {
163 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
164 return NTS_ERR_FAILED;
167 rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, STARTED_FEATURES_LIST_SCHEMA_XPATH, network_function_started_features_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription);
168 if(rc != SR_ERR_OK) {
169 log_error("could not subscribe to oper started-features: %s\n", sr_strerror(rc));
174 //subscribe to any changes on the main
175 rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NETWORK_FUNCTION_SCHEMA_XPATH, network_function_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription);
176 if(rc != SR_ERR_OK) {
177 log_error("could not subscribe to simulation changes\n");
178 return NTS_ERR_FAILED;
182 if(rc != NTS_ERR_OK) {
183 log_error("faults_init error\n", sr_strerror(rc));
184 return NTS_ERR_FAILED;
187 if(pthread_mutex_init(&faults_lock, NULL) != 0) {
188 log_error("mutex init has failed\n");
189 return NTS_ERR_FAILED;
192 if(pthread_create(&faults_thread, 0, faults_thread_routine, 0)) {
193 log_error("could not create thread for heartbeat\n");
194 return NTS_ERR_FAILED;
197 //check standalone mode
198 if(strlen(framework_environment.nts.nf_standalone_start_features)) {
199 char *start_features = 0;
201 asprintf(&start_features, "1 %s", framework_environment.nts.nf_standalone_start_features);
202 nf_function_control_buffer[nf_function_control_buffer_in] = start_features;
203 nf_function_control_buffer_in++;
204 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
205 nf_function_control_buffer_in = 0;
208 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"running in NETWORK FUNCTION STANDALONE mode!\n"LOG_COLOR_RESET);
209 log_add_verbose(1, "Currently enabled features are: %s\n", framework_environment.nts.nf_standalone_start_features);
210 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Docker IP:"LOG_COLOR_RESET" %s\n", framework_environment.settings.ip_v6_enabled ? framework_environment.settings.ip_v6 : framework_environment.settings.ip_v4);
211 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Docker ports"LOG_COLOR_RESET": ");
212 if(framework_environment.settings.ssh_connections) {
213 log_add(1, "NETCONF SSH: %d (%d)", STANDARD_NETCONF_PORT, framework_environment.settings.ssh_connections);
216 log_add(1, "NETCONF SSH: disabled");
218 if(framework_environment.settings.tls_connections) {
219 log_add(1, " | NETCONF TLS: %d (%d)", STANDARD_NETCONF_PORT + framework_environment.settings.ssh_connections, framework_environment.settings.tls_connections);
222 log_add(1, " | NETCONF TLS: disabled");
224 if(framework_environment.settings.ftp_connections) {
225 log_add(1, " | FTP: %d (%d)", STANDARD_FTP_PORT, framework_environment.settings.ftp_connections);
228 log_add(1, " | FTP: disabled");
230 if(framework_environment.settings.sftp_connections) {
231 log_add(1, " | SFTP: %d (%d)", STANDARD_SFTP_PORT, framework_environment.settings.sftp_connections);
234 log_add(1, " | SFTP: disabled");
239 while(!framework_sigint) {
240 pthread_mutex_lock(&nf_function_control_lock);
241 while(nf_function_control_buffer_in != nf_function_control_buffer_out) {
242 //get current function control string
243 char *nf_function_control_string = nf_function_control_buffer[nf_function_control_buffer_out];
244 nf_function_control_buffer_out++;
245 if(nf_function_control_buffer_out >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
246 nf_function_control_buffer_out = 0;
249 if(strstr(nf_function_control_string, "datastore-populate") != 0) {
250 rc = datastore_populate(3);
251 if(rc != NTS_ERR_OK) {
252 log_error("datastore_populate() failed\n");
256 if(strstr(nf_function_control_string, "ves-file-ready") != 0) {
257 if(nf_function_control_string[0] == '1') {
258 // start feature for handling the fileReady VES message
259 rc = ves_file_ready_feature_start(session_running);
261 log_error("ves_file_ready_feature_start() failed\n");
264 else if(nf_function_control_string[0] == '0') {
265 // stop feature for handling the fileReady VES message
266 rc = ves_file_ready_feature_stop();
268 log_error("ves_file_ready_feature_stop() failed\n");
273 if(strstr(nf_function_control_string, "ves-pnf-registration") != 0) {
274 if(nf_function_control_string[0] == '1') {
275 // check if PNF registration is enabled and send PNF registration message if so
276 rc = ves_pnf_registration_feature_start(session_running);
278 log_error("ves_pnf_registration_feature_start() failed\n");
283 if(strstr(nf_function_control_string, "ves-heartbeat") != 0) {
284 if(nf_function_control_string[0] == '1') {
285 // start feature for handling the heartbeat VES message
286 rc = ves_heartbeat_feature_start(session_running);
288 log_error("ves_heartbeat_feature_start() failed\n");
291 else if(nf_function_control_string[0] == '0') {
292 // stop feature for handling the heartbeat VES message
293 rc = ves_heartbeat_feature_stop();
295 log_error("ves_heartbeat_feature_stop() failed\n");
300 if(strstr(nf_function_control_string, "manual-notification-generation") != 0) {
301 if(nf_function_control_string[0] == '1') {
302 // start feature for manual notification
303 rc = manual_notification_feature_start(session_running);
305 log_error("manual_notification_feature_start() failed\n");
308 else if(nf_function_control_string[0] == '0') {
309 // stop feature for manual notification
310 rc = manual_notification_feature_stop();
312 log_error("manual_notification_feature_stop() failed\n");
317 if(strstr(nf_function_control_string, "netconf-call-home") != 0) {
318 if(nf_function_control_string[0] == '1') {
319 // start feature for NETCONF Call Home
320 rc = netconf_call_home_feature_start(session_running);
322 log_error("netconf_call_home_feature_start() failed\n");
327 if(strstr(nf_function_control_string, "web-cut-through") != 0) {
328 if(nf_function_control_string[0] == '1') {
329 // start feature for web cut-through
330 rc = web_cut_through_feature_start(session_running);
332 log_error("web_cut_through_feature_start() failed\n");
335 else if(nf_function_control_string[0] == '0') {
336 // stop feature for web cut-through
337 rc = web_cut_through_feature_stop(session_running);
339 log_error("web_cut_through_feature_stop() failed\n");
344 free(nf_function_control_string);
345 nf_function_control_string = 0;
347 pthread_mutex_unlock(&nf_function_control_lock);
357 static int netconf_monitoring_state_schemas_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
358 struct lyd_node *root = 0;
359 root = lyd_new_path(*parent, session_context, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, 0, 0, 0);
361 struct lyd_node *list = 0;
362 const struct lys_module *mod = 0;
363 const struct lys_submodule *submod = 0;
366 // get all modules from context
367 while ((mod = ly_ctx_get_module_iter(session_context, &i))) {
368 // we skip the internal sysrepo modules
369 if (!strcmp("sysrepo", mod->name) || !strcmp("sysrepo-monitoring", mod->name) || !strcmp("sysrepo-plugind", mod->name)) {
373 list = lyd_new(root, NULL, "schema");
374 lyd_new_leaf(list, NULL, "identifier", mod->name);
375 lyd_new_leaf(list, NULL, "version", (mod->rev ? mod->rev[0].date : NULL));
376 lyd_new_leaf(list, NULL, "format", "yang");
377 lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
378 lyd_new_leaf(list, NULL, "location", "NETCONF");
380 // iterate all the submodules included by a module
381 for (int j = 0; j < mod->inc_size; j++) {
382 submod = mod->inc[j].submodule;
384 list = lyd_new(root, NULL, "schema");
385 lyd_new_leaf(list, NULL, "identifier", submod->name);
386 lyd_new_leaf(list, NULL, "version", (submod->rev ? submod->rev[0].date : NULL));
387 lyd_new_leaf(list, NULL, "format", "yang");
388 lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
389 lyd_new_leaf(list, NULL, "location", "NETCONF");
396 static int notifications_streams_cb(sr_session_ctx_t *session, const char *module_name, const char *path, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
397 struct lyd_node *root = lyd_new_path(0, session_context, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, 0, 0, 0);
400 struct lyd_node *stream = lyd_new_path(root, 0, "/nc-notifications:netconf/streams/stream[name='NETCONF']", NULL, 0, 0);
401 lyd_new_leaf(stream, stream->schema->module, "description", "Default NETCONF stream containing notifications from all the modules. Replays only notifications for modules that support replay.");
402 lyd_new_leaf(stream, stream->schema->module, "replaySupport", "true");
404 /* all other streams */
405 struct lyd_node *sr_data;
406 struct lyd_node *sr_mod;
407 /* go through all the sysrepo modules */
408 int rc = sr_get_module_info(session_connection, &sr_data);
409 if(rc != SR_ERR_OK) {
410 log_error("sr_get_module_info failed\n");
411 return SR_ERR_OPERATION_FAILED;
414 LY_TREE_FOR(sr_data->child, sr_mod) {
415 const char *mod_name = ((struct lyd_node_leaf_list *)sr_mod->child)->value_str;
416 const struct lys_module *mod = ly_ctx_get_module(session_context, mod_name, 0, 1);
417 int has_notifications = 0;
418 struct lys_node *data = mod->data;
420 if(data->nodetype == LYS_NOTIF) {
421 has_notifications = 1;
426 if(has_notifications) {
427 /* generate information about the stream/module */
428 stream = lyd_new(root->child, NULL, "stream");
429 lyd_new_leaf(stream, NULL, "name", mod_name);
430 lyd_new_leaf(stream, NULL, "description", "Stream with all notifications of a module.");
432 struct lyd_node *rep_sup = 0;
433 struct ly_set *set = lyd_find_path(sr_mod, "replay-support");
434 if(set && (set->number == 1)) {
435 rep_sup = set->set.d[0];
439 lyd_new_leaf(stream, NULL, "replaySupport", rep_sup ? "true" : "false");
442 nc_time2datetime(((struct lyd_node_leaf_list *)rep_sup)->value.uint64, NULL, buf);
443 lyd_new_leaf(stream, NULL, "replayLogCreationTime", buf);
448 lyd_free_withsiblings(sr_data);
454 static int network_function_populate_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) {
458 rc = sr_new_values(*output_cnt, output);
459 if(SR_ERR_OK != rc) {
463 rc = sr_val_set_xpath(output[0], POPULATE_RPC_SCHEMA_XPATH"/status");
464 if(SR_ERR_OK != rc) {
468 pthread_mutex_lock(&nf_function_control_lock);
469 nf_function_control_buffer[nf_function_control_buffer_in] = strdup("datastore-populate");
470 nf_function_control_buffer_in++;
471 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
472 nf_function_control_buffer_in = 0;
474 pthread_mutex_unlock(&nf_function_control_lock);
476 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
480 static int network_function_feature_control_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) {
482 int total_errors = 0;
484 char start_features[16][64];
485 int start_features_cnt = 0;
487 char stop_features[16][64];
488 int stop_features_cnt = 0;
490 char *start_input = 0;
491 char *stop_input = 0;
493 for(int i = 0; i < input_cnt; i++) {
494 if(input[i].data.bits_val == 0) {
498 char *val = strdup(input[i].data.bits_val);
500 if(strstr(input[i].xpath, "start")) {
501 start_input = input[i].data.bits_val;
503 const char *tok = " ";
504 char *token = strtok(val, tok);
506 strcpy(start_features[start_features_cnt++], token);
507 token = strtok(0, tok);
511 if(strstr(input[i].xpath, "stop")) {
512 stop_input = input[i].data.bits_val;
514 const char *tok = " ";
515 char *token = strtok(val, tok);
517 strcpy(stop_features[stop_features_cnt++], token);
518 token = strtok(0, tok);
525 for(int i = 0; i < start_features_cnt; i++) {
526 for(int j = 0; j < stop_features_cnt; j++) {
527 if(strcmp(start_features[i], stop_features[j]) == 0) {
534 rc = sr_new_values(*output_cnt, output);
535 if(SR_ERR_OK != rc) {
539 rc = sr_val_set_xpath(output[0], FEATURE_CONTROL_SCHEMA_XPATH"/status");
540 if(SR_ERR_OK != rc) {
544 if(total_errors != 0) {
545 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
548 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
550 pthread_mutex_lock(&nf_function_control_lock);
551 if(start_features_cnt) {
552 asprintf(&nf_function_control_buffer[nf_function_control_buffer_in], "1 %s", start_input);
553 nf_function_control_buffer_in++;
554 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
555 nf_function_control_buffer_in = 0;
559 if(stop_features_cnt) {
560 asprintf(&nf_function_control_buffer[nf_function_control_buffer_in], "0 %s", stop_input);
561 nf_function_control_buffer_in++;
562 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
563 nf_function_control_buffer_in = 0;
566 pthread_mutex_unlock(&nf_function_control_lock);
574 static int network_function_faults_clear_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) {
578 rc = sr_new_values(*output_cnt, output);
579 if(SR_ERR_OK != rc) {
583 rc = sr_val_set_xpath(output[0], FAULTS_CLEAR_SCHEMA_XPATH"/status");
584 if(SR_ERR_OK != rc) {
588 pthread_mutex_lock(&faults_lock);
589 faults_counters_clear();
590 pthread_mutex_unlock(&faults_lock);
592 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
596 static int network_function_faults_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) {
599 if(event == SR_EV_DONE) {
600 pthread_mutex_lock(&faults_lock);
601 rc = faults_update_config(session);
602 pthread_mutex_unlock(&faults_lock);
603 if(rc != NTS_ERR_OK) {
604 log_error("faults_update_config failed\n");
605 return SR_ERR_VALIDATION_FAILED;
612 static int network_function_faults_count_get_items_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) {
613 pthread_mutex_lock(&faults_lock);
614 fault_counters_t counters = faults_counters_get();
615 pthread_mutex_unlock(&faults_lock);
618 *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), FAULTS_COUNT_LIST_SCHEMA_XPATH, 0, 0, 0);
620 log_error("lyd_new_path failed\n");
621 return SR_ERR_OPERATION_FAILED;
624 sprintf(value, "%d", counters.normal);
625 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/normal", value, 0, 0) == 0) {
626 log_error("lyd_new_path failed\n");
627 return SR_ERR_OPERATION_FAILED;
630 sprintf(value, "%d", counters.warning);
631 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/warning", value, 0, 0) == 0) {
632 log_error("lyd_new_path failed\n");
633 return SR_ERR_OPERATION_FAILED;
636 sprintf(value, "%d", counters.minor);
637 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/minor", value, 0, 0) == 0) {
638 log_error("lyd_new_path failed\n");
639 return SR_ERR_OPERATION_FAILED;
642 sprintf(value, "%d", counters.major);
643 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/major", value, 0, 0) == 0) {
644 log_error("lyd_new_path failed\n");
645 return SR_ERR_OPERATION_FAILED;
648 sprintf(value, "%d", counters.critical);
649 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/critical", value, 0, 0) == 0) {
650 log_error("lyd_new_path failed\n");
651 return SR_ERR_OPERATION_FAILED;
657 static int network_function_started_features_get_items_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) {
661 if(ves_file_ready_feature_get_status()) {
662 strcat(value, "ves-file-ready ");
665 if(ves_pnf_registration_feature_get_status()) {
666 strcat(value, "ves-pnf-registration ");
669 if(ves_heartbeat_feature_get_status()) {
670 strcat(value, "ves-heartbeat ");
673 if(manual_notification_feature_get_status()) {
674 strcat(value, "manual-notification-generation ");
677 if(netconf_call_home_feature_get_status()) {
678 strcat(value, "netconf-call-home ");
681 if(web_cut_through_feature_get_status()) {
682 strcat(value, "web-cut-through ");
686 value[strlen(value) - 1] = 0;
689 *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), STARTED_FEATURES_LIST_SCHEMA_XPATH, value, 0, 0);
691 log_error("lyd_new_path failed\n");
692 return SR_ERR_OPERATION_FAILED;
698 static int faults_update_config(sr_session_ctx_t *session) {
702 int ret = NTS_ERR_OK;
705 struct lyd_node *data;
706 rc = sr_get_subtree(session, FAULTS_LIST_SCHEMA_XPATH, 0, &data);
707 if(rc != SR_ERR_OK) {
708 log_error("sr_get_subtree failed\n");
709 return NTS_ERR_FAILED;
712 faults_fault_list_clear();
713 faults_counters_clear();
718 if(data->child == 0) {
719 goto faults_update_config_free;
722 struct lyd_node *chd = 0;
723 LY_TREE_FOR(data->child, chd) {
724 if(strcmp(chd->schema->name, "fault-delay-list") == 0) {
725 struct lyd_node *delay_list_entry = 0;
726 LY_TREE_FOR(chd->child, delay_list_entry) {
727 if(strcmp(delay_list_entry->schema->name, "delay-period") == 0) {
728 rc = faults_fault_list_add(((const struct lyd_node_leaf_list *)delay_list_entry)->value.uint16);
729 if(rc != NTS_ERR_OK) {
730 log_error("faults_fault_list_add failed\n");
731 ret = NTS_ERR_FAILED;
732 goto faults_update_config_free;
740 faults_update_config_free:
746 static void *faults_thread_routine(void *arg) {
749 sr_session_ctx_t *current_session_running = 0;
750 rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session_running);
751 if (rc != SR_ERR_OK) {
752 log_error("sr_session_start failed\n");
756 sr_session_ctx_t *current_session_operational = 0;
757 rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, ¤t_session_operational);
758 if (rc != SR_ERR_OK) {
759 log_error("sr_session_start failed\n");
763 pthread_mutex_lock(&faults_lock);
764 rc = faults_update_config(current_session_running);
765 if(rc != NTS_ERR_OK) {
766 log_error("faults_update_config failed\n");
769 pthread_mutex_unlock(&faults_lock);
771 while(!framework_sigint) {
772 pthread_mutex_lock(&faults_lock);
773 if(faults_fault_list_not_empty()) {
774 uint16_t new_delay = faults_fault_list_get_next();
776 fault_details_t *fault = faults_generate_fault();
778 log_error("faults_generate_fault failed\n");
779 pthread_mutex_unlock(&faults_lock);
784 rc = faults_counters_increase(fault->severity);
785 if(rc != NTS_ERR_OK) {
786 log_error("faults_counters_increase failed\n");
788 pthread_mutex_unlock(&faults_lock);
791 bool nc_fault_enabled = false;
792 bool ves_fault_enabled = false;
794 rc = sr_get_item(current_session_running, FAULTS_NC_ENABLED_SCHEMA_XPATH, 0, &val);
795 if(rc == SR_ERR_OK) {
796 nc_fault_enabled = val->data.bool_val;
800 rc = sr_get_item(current_session_running, FAULTS_VES_ENABLED_SCHEMA_XPATH, 0, &val);
801 if(rc == SR_ERR_OK) {
802 ves_fault_enabled = val->data.bool_val;
806 if(nc_fault_enabled) {
807 struct lyd_node *notif = 0;
808 log_add_verbose(1, "[faults] notification is '%s'\n", fault->yang_notif_processed);
809 notif = lyd_parse_mem(session_context, fault->yang_notif_processed, LYD_XML, LYD_OPT_NOTIF, 0);
811 log_error("lyd_parse_mem failed\n");
815 rc = sr_event_notif_send_tree(current_session_running, notif);
817 if(rc != SR_ERR_OK) {
818 log_error("sr_event_notif_send_tree failed\n");
823 if(ves_fault_enabled) {
824 rc = faults_ves_message_send(current_session_running, fault->condition, fault->object, fault->severity, fault->date_time, fault->specific_problem);
825 if(rc != NTS_ERR_OK) {
826 log_error("faults_ves_message_send failed\n");
830 log_add_verbose(1, "[faults] delaying %d sec\n", new_delay);
834 pthread_mutex_unlock(&faults_lock);
839 sr_session_stop(current_session_running);
840 sr_session_stop(current_session_operational);
845 static int network_function_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) {
846 sr_change_iter_t *it = 0;
848 sr_change_oper_t oper;
849 sr_val_t *old_value = 0;
850 sr_val_t *new_value = 0;
852 if(event == SR_EV_UPDATE) {
853 rc = sr_get_changes_iter(session, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"//.", &it);
854 if(rc != SR_ERR_OK) {
855 log_error("sr_get_changes_iter failed\n");
856 return SR_ERR_VALIDATION_FAILED;
859 while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
861 if(new_value->xpath && (strcmp(new_value->xpath, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/function-type") == 0)) {
862 if(old_value && !old_value->dflt) {
863 rc = sr_set_item(session, old_value->xpath, old_value, 0);
864 if(rc != SR_ERR_OK) {
865 log_error("sr_set_item failed\n");
866 return SR_ERR_VALIDATION_FAILED;
871 if(new_value->xpath && (strcmp(new_value->xpath, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/mount-point-addressing-method") == 0)) {
872 if(old_value && !old_value->dflt) {
873 rc = sr_set_item(session, old_value->xpath, old_value, 0);
874 if(rc != SR_ERR_OK) {
875 log_error("sr_set_item failed\n");
876 return SR_ERR_VALIDATION_FAILED;
881 sr_free_val(old_value);
882 sr_free_val(new_value);
885 sr_free_change_iter(it);