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/xpath.h"
36 #include "core/datastore/schema.h"
37 #include "core/datastore/populate.h"
39 #include "core/faults/faults.h"
41 #include "features/ves_pnf_registration/ves_pnf_registration.h"
42 #include "features/ves_heartbeat/ves_heartbeat.h"
43 #include "features/ves_file_ready/ves_file_ready.h"
44 #include "features/manual_notification/manual_notification.h"
45 #include "features/netconf_call_home/netconf_call_home.h"
46 #include "features/web_cut_through/web_cut_through.h"
47 #include "features/ves_o1_pnf_registration/ves_o1_pnf_registration.h"
49 #include "app_common.h"
50 #include "nf_oran_du.h"
51 #include "nf_oran_ru_supervision.h"
53 #define NF_FUNCTION_CONTROL_BUFFER_LENGTH 32
55 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);
56 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);
58 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);
59 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);
60 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);
61 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);
62 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);
63 static int network_function_info_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);
65 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);
67 static int faults_update_config(sr_session_ctx_t *session); //not protected by lock
68 static void *faults_thread_routine(void *arg);
70 static pthread_mutex_t nf_function_control_lock;
71 static char *nf_function_control_buffer[NF_FUNCTION_CONTROL_BUFFER_LENGTH];
72 static int nf_function_control_buffer_in;
73 static int nf_function_control_buffer_out;
75 static pthread_t faults_thread;
76 static pthread_mutex_t faults_lock;
78 int network_function_run(void) {
81 nf_function_control_buffer_in = 0;
82 nf_function_control_buffer_out = 0;
84 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"running as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET);
86 int rc = app_common_init();
87 if(rc != NTS_ERR_OK) {
88 log_error("app_common_init failed\n");
89 return NTS_ERR_FAILED;
92 if(strlen(framework_environment.nts.nf_standalone_start_features)) {
93 rc = nts_utils_populate_info(session_running, framework_environment.nts.function_type);
94 if(rc != NTS_ERR_OK) {
95 log_error("nts_utils_populate_info failed\n");
96 return NTS_ERR_FAILED;
100 if(pthread_mutex_init(&nf_function_control_lock, NULL) != 0) {
101 log_error("mutex init has failed\n");
102 return NTS_ERR_FAILED;
105 //ietf-netconf-monitoring schemas populate with modules and submodules (overwrite default Netopeer2 behaviour)
106 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);
107 if(rc != SR_ERR_OK) {
108 log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
112 //nc-notifications overwrite
113 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);
114 if(rc != SR_ERR_OK) {
115 log_error("error from sr_oper_get_items_subscribe: %s\n", sr_strerror(rc));
120 rc = sr_rpc_subscribe(session_running, NTS_NF_RPC_POPULATE_SCHEMA_XPATH, network_function_populate_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
121 if(rc != SR_ERR_OK) {
122 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
123 return NTS_ERR_FAILED;
127 rc = sr_rpc_subscribe(session_running, NTS_NF_RPC_FEATURE_CONTROL_SCHEMA_XPATH, network_function_feature_control_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
128 if(rc != SR_ERR_OK) {
129 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
130 return NTS_ERR_FAILED;
134 rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_FAULT_GENERATION_SCHEMA_XPATH, network_function_faults_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
135 if(rc != SR_ERR_OK) {
136 log_error("could not subscribe to faults");
137 return NTS_ERR_FAILED;
140 rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH, network_function_faults_count_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE, &session_subscription);
141 if(rc != SR_ERR_OK) {
142 log_error("could not subscribe to oper faults: %s\n", sr_strerror(rc));
143 return NTS_ERR_FAILED;
146 rc = sr_rpc_subscribe(session_running, NTS_NF_RPC_FAULTS_CLEAR_SCHEMA_XPATH, network_function_faults_clear_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
147 if(rc != SR_ERR_OK) {
148 log_error("error from sr_rpc_subscribe: %s\n", sr_strerror(rc));
149 return NTS_ERR_FAILED;
152 rc = sr_oper_get_items_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_INFO_SCHEMA_XPATH, network_function_info_get_items_cb, NULL, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_OPER_MERGE, &session_subscription);
153 if(rc != SR_ERR_OK) {
154 log_error("could not subscribe to oper started-features: %s\n", sr_strerror(rc));
155 return NTS_ERR_FAILED;
158 //subscribe to any changes on the main
159 rc = sr_module_change_subscribe(session_running, NTS_NETWORK_FUNCTION_MODULE, NTS_NF_NETWORK_FUNCTION_SCHEMA_XPATH, network_function_change_cb, NULL, 1, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_UPDATE, &session_subscription);
160 if(rc != SR_ERR_OK) {
161 log_error("could not subscribe to simulation changes: %s\n", sr_strerror(rc));
162 return NTS_ERR_FAILED;
166 if(rc != NTS_ERR_OK) {
167 log_error("faults_init error\n");
168 return NTS_ERR_FAILED;
171 if(pthread_mutex_init(&faults_lock, NULL) != 0) {
172 log_error("mutex init has failed\n");
173 return NTS_ERR_FAILED;
176 if(pthread_create(&faults_thread, 0, faults_thread_routine, 0)) {
177 log_error("could not create thread for heartbeat\n");
178 return NTS_ERR_FAILED;
181 //check standalone mode
182 if(strlen(framework_environment.nts.nf_standalone_start_features)) {
183 char *start_features = 0;
185 asprintf(&start_features, "1 %s", framework_environment.nts.nf_standalone_start_features);
186 nf_function_control_buffer[nf_function_control_buffer_in] = start_features;
187 nf_function_control_buffer_in++;
188 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
189 nf_function_control_buffer_in = 0;
192 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"running in NETWORK FUNCTION STANDALONE mode as a %s\n"LOG_COLOR_RESET, framework_environment.nts.function_type);
193 log_add_verbose(1, "Currently enabled features are: %s\n", framework_environment.nts.nf_standalone_start_features);
194 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);
195 log_add_verbose(1, LOG_COLOR_BOLD_YELLOW"Docker ports"LOG_COLOR_RESET": ");
196 if(framework_environment.settings.ssh_connections) {
197 log_add(1, "NETCONF SSH: %d (%d)", STANDARD_NETCONF_PORT, framework_environment.settings.ssh_connections);
200 log_add(1, "NETCONF SSH: disabled");
202 if(framework_environment.settings.tls_connections) {
203 log_add(1, " | NETCONF TLS: %d (%d)", STANDARD_NETCONF_PORT + framework_environment.settings.ssh_connections, framework_environment.settings.tls_connections);
206 log_add(1, " | NETCONF TLS: disabled");
208 if(framework_environment.settings.ftp_connections) {
209 log_add(1, " | FTP: %d (%d)", STANDARD_FTP_PORT, framework_environment.settings.ftp_connections);
212 log_add(1, " | FTP: disabled");
214 if(framework_environment.settings.sftp_connections) {
215 log_add(1, " | SFTP: %d (%d)", STANDARD_SFTP_PORT, framework_environment.settings.sftp_connections);
218 log_add(1, " | SFTP: disabled");
223 if(strcmp(framework_environment.nts.function_type, "NTS_FUNCTION_TYPE_O_RAN_O_DU") == 0) {
224 rc = nf_oran_du_init();
225 if(rc != NTS_ERR_OK) {
226 log_error("nf_oran_du_init failed\n");
227 return NTS_ERR_FAILED;
231 if(strcmp(framework_environment.nts.function_type, "NTS_FUNCTION_TYPE_O_RAN_O_RU_FH") == 0) {
232 log_add_verbose(1, "Initializing o-ran-supervision function...\n");
233 rc = nf_oran_ru_supervision_init();
234 if(rc != NTS_ERR_OK) {
235 log_error("nf_oran_ru_supervision_init failed, continuing...\n");
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_all();
251 if(rc != NTS_ERR_OK) {
252 log_error("datastore_populate_all() failed\n");
255 //subscribe to any changes so the operational is dynamic
258 int xpaths_count = datastore_schema_get_running_xpaths(&xpaths, &modules);
259 if(xpaths_count < 0) {
260 log_error("datastore_schema_get_running_xpaths failed\n");
261 return NTS_ERR_FAILED;
264 for(int i = 0; i < xpaths_count; i++) {
266 log_add_verbose(1, "subscribing to %s on module %s... ", xpaths[i], modules[i]);
267 rc = sr_module_change_subscribe(session_running, modules[i], xpaths[i], datastore_dynamic_operational_auto_callback, 0, 0, SR_SUBSCR_DONE_ONLY | SR_SUBSCR_CTX_REUSE, &session_subscription);
268 if(rc != SR_ERR_OK) {
269 log_error("sr_module_change_subscribe error\n");
272 log_add(1, "done\n");
282 if(strstr(nf_function_control_string, "ves-file-ready") != 0) {
283 if(nf_function_control_string[0] == '1') {
284 // start feature for handling the fileReady VES message
285 rc = ves_file_ready_feature_start(session_running);
287 log_error("ves_file_ready_feature_start() failed\n");
290 else if(nf_function_control_string[0] == '0') {
291 // stop feature for handling the fileReady VES message
292 rc = ves_file_ready_feature_stop();
294 log_error("ves_file_ready_feature_stop() failed\n");
299 if(strstr(nf_function_control_string, "ves-pnf-registration") != 0) {
300 if(nf_function_control_string[0] == '1') {
301 // check if PNF registration is enabled and send PNF registration message if so
302 rc = ves_pnf_registration_feature_start(session_running);
304 log_error("ves_pnf_registration_feature_start() failed\n");
309 if(strstr(nf_function_control_string, "ves-o1-pnf-registration") != 0) {
310 if(nf_function_control_string[0] == '1') {
311 // check if O1 PNF registration is enabled and send PNF registration message if so
312 rc = ves_o1_pnf_registration_feature_start(session_running);
314 log_error("ves_o1_pnf_registration_feature_start() failed\n");
319 if(strstr(nf_function_control_string, "ves-heartbeat") != 0) {
320 if(nf_function_control_string[0] == '1') {
321 // start feature for handling the heartbeat VES message
322 rc = ves_heartbeat_feature_start(session_running);
324 log_error("ves_heartbeat_feature_start() failed\n");
327 else if(nf_function_control_string[0] == '0') {
328 // stop feature for handling the heartbeat VES message
329 rc = ves_heartbeat_feature_stop();
331 log_error("ves_heartbeat_feature_stop() failed\n");
336 if(strstr(nf_function_control_string, "manual-notification-generation") != 0) {
337 if(nf_function_control_string[0] == '1') {
338 // start feature for manual notification
339 rc = manual_notification_feature_start(session_running);
341 log_error("manual_notification_feature_start() failed\n");
344 else if(nf_function_control_string[0] == '0') {
345 // stop feature for manual notification
346 rc = manual_notification_feature_stop();
348 log_error("manual_notification_feature_stop() failed\n");
353 if(strstr(nf_function_control_string, "netconf-call-home") != 0) {
354 if(nf_function_control_string[0] == '1') {
355 // start feature for NETCONF Call Home
356 rc = netconf_call_home_feature_start(session_running);
358 log_error("netconf_call_home_feature_start() failed\n");
363 if(strstr(nf_function_control_string, "web-cut-through") != 0) {
364 if(nf_function_control_string[0] == '1') {
365 // start feature for web cut-through
366 rc = web_cut_through_feature_start(session_running);
368 log_error("web_cut_through_feature_start() failed\n");
371 else if(nf_function_control_string[0] == '0') {
372 // stop feature for web cut-through
373 rc = web_cut_through_feature_stop(session_running);
375 log_error("web_cut_through_feature_stop() failed\n");
380 free(nf_function_control_string);
381 nf_function_control_string = 0;
383 pthread_mutex_unlock(&nf_function_control_lock);
394 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) {
395 struct lyd_node *root = 0;
396 root = lyd_new_path(*parent, session_context, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, 0, 0, 0);
398 struct lyd_node *list = 0;
399 const struct lys_module *mod = 0;
400 const struct lys_submodule *submod = 0;
403 // get all modules from context
404 while ((mod = ly_ctx_get_module_iter(session_context, &i))) {
405 // we skip the internal sysrepo modules
406 if (!strcmp("sysrepo", mod->name) || !strcmp("sysrepo-monitoring", mod->name) || !strcmp("sysrepo-plugind", mod->name)) {
410 list = lyd_new(root, NULL, "schema");
411 lyd_new_leaf(list, NULL, "identifier", mod->name);
412 lyd_new_leaf(list, NULL, "version", (mod->rev ? mod->rev[0].date : NULL));
413 lyd_new_leaf(list, NULL, "format", "yang");
414 lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
415 lyd_new_leaf(list, NULL, "location", "NETCONF");
417 // iterate all the submodules included by a module
418 for (int j = 0; j < mod->inc_size; j++) {
419 submod = mod->inc[j].submodule;
421 list = lyd_new(root, NULL, "schema");
422 lyd_new_leaf(list, NULL, "identifier", submod->name);
423 lyd_new_leaf(list, NULL, "version", (submod->rev ? submod->rev[0].date : NULL));
424 lyd_new_leaf(list, NULL, "format", "yang");
425 lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
426 lyd_new_leaf(list, NULL, "location", "NETCONF");
433 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) {
434 struct lyd_node *root = lyd_new_path(0, session_context, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, 0, 0, 0);
437 struct lyd_node *stream = lyd_new_path(root, 0, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH"/stream[name='NETCONF']", NULL, 0, 0);
438 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.");
439 lyd_new_leaf(stream, stream->schema->module, "replaySupport", "true");
441 /* all other streams */
442 struct lyd_node *sr_data;
443 struct lyd_node *sr_mod;
444 /* go through all the sysrepo modules */
445 int rc = sr_get_module_info(session_connection, &sr_data);
446 if(rc != SR_ERR_OK) {
447 log_error("sr_get_module_info failed\n");
448 return SR_ERR_OPERATION_FAILED;
451 LY_TREE_FOR(sr_data->child, sr_mod) {
452 const char *mod_name = ((struct lyd_node_leaf_list *)sr_mod->child)->value_str;
453 const struct lys_module *mod = ly_ctx_get_module(session_context, mod_name, 0, 1);
454 int has_notifications = 0;
455 struct lys_node *data = mod->data;
457 if(data->nodetype == LYS_NOTIF) {
458 has_notifications = 1;
463 if(has_notifications) {
464 /* generate information about the stream/module */
465 stream = lyd_new(root->child, NULL, "stream");
466 lyd_new_leaf(stream, NULL, "name", mod_name);
467 lyd_new_leaf(stream, NULL, "description", "Stream with all notifications of a module.");
469 struct lyd_node *rep_sup = 0;
470 struct ly_set *set = lyd_find_path(sr_mod, "replay-support");
471 if(set && (set->number == 1)) {
472 rep_sup = set->set.d[0];
476 lyd_new_leaf(stream, NULL, "replaySupport", rep_sup ? "true" : "false");
479 nc_time2datetime(((struct lyd_node_leaf_list *)rep_sup)->value.uint64, NULL, buf);
480 lyd_new_leaf(stream, NULL, "replayLogCreationTime", buf);
485 lyd_free_withsiblings(sr_data);
491 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) {
495 rc = sr_new_values(*output_cnt, output);
496 if(SR_ERR_OK != rc) {
500 rc = sr_val_set_xpath(output[0], NTS_NF_RPC_POPULATE_SCHEMA_XPATH"/status");
501 if(SR_ERR_OK != rc) {
505 pthread_mutex_lock(&nf_function_control_lock);
506 nf_function_control_buffer[nf_function_control_buffer_in] = strdup("datastore-populate");
507 nf_function_control_buffer_in++;
508 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
509 nf_function_control_buffer_in = 0;
511 pthread_mutex_unlock(&nf_function_control_lock);
513 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
517 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) {
519 int total_errors = 0;
521 char start_features[16][64];
522 int start_features_cnt = 0;
524 char stop_features[16][64];
525 int stop_features_cnt = 0;
527 char *start_input = 0;
528 char *stop_input = 0;
530 for(int i = 0; i < input_cnt; i++) {
531 if(input[i].data.bits_val == 0) {
535 char *val = strdup(input[i].data.bits_val);
537 if(strstr(input[i].xpath, "start")) {
538 start_input = input[i].data.bits_val;
540 const char *tok = " ";
541 char *token = strtok(val, tok);
543 strcpy(start_features[start_features_cnt++], token);
544 token = strtok(0, tok);
548 if(strstr(input[i].xpath, "stop")) {
549 stop_input = input[i].data.bits_val;
551 const char *tok = " ";
552 char *token = strtok(val, tok);
554 strcpy(stop_features[stop_features_cnt++], token);
555 token = strtok(0, tok);
562 for(int i = 0; i < start_features_cnt; i++) {
563 for(int j = 0; j < stop_features_cnt; j++) {
564 if(strcmp(start_features[i], stop_features[j]) == 0) {
571 rc = sr_new_values(*output_cnt, output);
572 if(SR_ERR_OK != rc) {
576 rc = sr_val_set_xpath(output[0], NTS_NF_RPC_FEATURE_CONTROL_SCHEMA_XPATH"/status");
577 if(SR_ERR_OK != rc) {
581 if(total_errors != 0) {
582 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
585 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
587 pthread_mutex_lock(&nf_function_control_lock);
588 if(start_features_cnt) {
589 asprintf(&nf_function_control_buffer[nf_function_control_buffer_in], "1 %s", start_input);
590 nf_function_control_buffer_in++;
591 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
592 nf_function_control_buffer_in = 0;
596 if(stop_features_cnt) {
597 asprintf(&nf_function_control_buffer[nf_function_control_buffer_in], "0 %s", stop_input);
598 nf_function_control_buffer_in++;
599 if(nf_function_control_buffer_in >= NF_FUNCTION_CONTROL_BUFFER_LENGTH) {
600 nf_function_control_buffer_in = 0;
603 pthread_mutex_unlock(&nf_function_control_lock);
611 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) {
615 rc = sr_new_values(*output_cnt, output);
616 if(SR_ERR_OK != rc) {
620 rc = sr_val_set_xpath(output[0], NTS_NF_RPC_FAULTS_CLEAR_SCHEMA_XPATH"/status");
621 if(SR_ERR_OK != rc) {
625 pthread_mutex_lock(&faults_lock);
626 faults_counters_clear();
627 pthread_mutex_unlock(&faults_lock);
629 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
633 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) {
636 if(event == SR_EV_DONE) {
637 pthread_mutex_lock(&faults_lock);
638 rc = faults_update_config(session);
639 pthread_mutex_unlock(&faults_lock);
640 if(rc != NTS_ERR_OK) {
641 log_error("faults_update_config failed\n");
642 return SR_ERR_VALIDATION_FAILED;
649 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) {
650 pthread_mutex_lock(&faults_lock);
651 fault_counters_t counters = faults_counters_get();
652 pthread_mutex_unlock(&faults_lock);
655 *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH, 0, 0, 0);
657 log_error("lyd_new_path failed\n");
658 return SR_ERR_OPERATION_FAILED;
661 sprintf(value, "%d", counters.normal);
662 if(lyd_new_path(*parent, NULL, NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH"/normal", value, 0, 0) == 0) {
663 log_error("lyd_new_path failed\n");
664 return SR_ERR_OPERATION_FAILED;
667 sprintf(value, "%d", counters.warning);
668 if(lyd_new_path(*parent, NULL, NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH"/warning", value, 0, 0) == 0) {
669 log_error("lyd_new_path failed\n");
670 return SR_ERR_OPERATION_FAILED;
673 sprintf(value, "%d", counters.minor);
674 if(lyd_new_path(*parent, NULL, NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH"/minor", value, 0, 0) == 0) {
675 log_error("lyd_new_path failed\n");
676 return SR_ERR_OPERATION_FAILED;
679 sprintf(value, "%d", counters.major);
680 if(lyd_new_path(*parent, NULL, NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH"/major", value, 0, 0) == 0) {
681 log_error("lyd_new_path failed\n");
682 return SR_ERR_OPERATION_FAILED;
685 sprintf(value, "%d", counters.critical);
686 if(lyd_new_path(*parent, NULL, NTS_NF_FAULT_COUNT_LIST_SCHEMA_XPATH"/critical", value, 0, 0) == 0) {
687 log_error("lyd_new_path failed\n");
688 return SR_ERR_OPERATION_FAILED;
694 static int network_function_info_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) {
695 char started_features[1024];
696 started_features[0] = 0;
698 if(ves_file_ready_feature_get_status()) {
699 strcat(started_features, "ves-file-ready ");
702 if(ves_pnf_registration_feature_get_status()) {
703 strcat(started_features, "ves-pnf-registration ");
706 if(ves_heartbeat_feature_get_status()) {
707 strcat(started_features, "ves-heartbeat ");
710 if(manual_notification_feature_get_status()) {
711 strcat(started_features, "manual-notification-generation ");
714 if(netconf_call_home_feature_get_status()) {
715 strcat(started_features, "netconf-call-home ");
718 if(web_cut_through_feature_get_status()) {
719 strcat(started_features, "web-cut-through ");
722 if(ves_o1_pnf_registration_feature_get_status()) {
723 strcat(started_features, "ves-o1-pnf-registration ");
726 if(strlen(started_features)) {
727 started_features[strlen(started_features) - 1] = 0;
730 *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), NTS_NF_INFO_SCHEMA_XPATH, 0, 0, 0);
732 log_error("lyd_new_path failed\n");
733 return SR_ERR_OPERATION_FAILED;
736 struct lyd_node *n = lyd_new_leaf(*parent, (*parent)->schema->module, "started-features", started_features);
738 log_error("lyd_new_leaf failed\n");
739 return SR_ERR_OPERATION_FAILED;
745 static int faults_update_config(sr_session_ctx_t *session) {
749 int ret = NTS_ERR_OK;
752 struct lyd_node *data;
753 rc = sr_get_subtree(session, NTS_NF_FAULT_GENERATION_SCHEMA_XPATH, 0, &data);
754 if(rc != SR_ERR_OK) {
755 log_error("sr_get_subtree failed\n");
756 return NTS_ERR_FAILED;
759 faults_fault_list_clear();
764 if(data->child == 0) {
765 goto faults_update_config_free;
768 struct lyd_node *chd = 0;
769 LY_TREE_FOR(data->child, chd) {
770 if(strcmp(chd->schema->name, "fault-delay-list") == 0) {
771 struct lyd_node *delay_list_entry = 0;
772 LY_TREE_FOR(chd->child, delay_list_entry) {
773 if(strcmp(delay_list_entry->schema->name, "delay-period") == 0) {
774 rc = faults_fault_list_add(((const struct lyd_node_leaf_list *)delay_list_entry)->value.uint16);
775 if(rc != NTS_ERR_OK) {
776 log_error("faults_fault_list_add failed\n");
777 ret = NTS_ERR_FAILED;
778 goto faults_update_config_free;
786 faults_update_config_free:
792 static void *faults_thread_routine(void *arg) {
795 sr_session_ctx_t *current_session_running = 0;
796 rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session_running);
797 if (rc != SR_ERR_OK) {
798 log_error("sr_session_start failed\n");
802 sr_session_ctx_t *current_session_operational = 0;
803 rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, ¤t_session_operational);
804 if (rc != SR_ERR_OK) {
805 log_error("sr_session_start failed\n");
809 pthread_mutex_lock(&faults_lock);
810 rc = faults_update_config(current_session_running);
811 if(rc != NTS_ERR_OK) {
812 log_error("faults_update_config failed\n");
815 pthread_mutex_unlock(&faults_lock);
817 while(!framework_sigint) {
818 pthread_mutex_lock(&faults_lock);
819 if(faults_fault_list_not_empty()) {
820 uint16_t new_delay = faults_fault_list_get_next();
822 fault_details_t *fault = faults_generate_fault();
824 log_error("faults_generate_fault failed\n");
825 pthread_mutex_unlock(&faults_lock);
830 rc = faults_counters_increase(fault->severity);
831 if(rc != NTS_ERR_OK) {
832 log_error("faults_counters_increase failed\n");
834 pthread_mutex_unlock(&faults_lock);
837 bool nc_fault_enabled = false;
838 bool ves_fault_enabled = false;
840 rc = sr_get_item(current_session_running, NTS_NF_NETCONF_FAULTS_ENABLED_SCHEMA_PATH, 0, &val);
841 if(rc == SR_ERR_OK) {
842 nc_fault_enabled = val->data.bool_val;
846 rc = sr_get_item(current_session_running, NTS_NF_VES_FAULTS_ENABLED_SCHEMA_XPATH, 0, &val);
847 if(rc == SR_ERR_OK) {
848 ves_fault_enabled = val->data.bool_val;
852 if(nc_fault_enabled) {
853 struct lyd_node *notif = 0;
854 log_add_verbose(1, "[faults] notification is '%s'\n", fault->yang_notif_processed);
855 notif = lyd_parse_mem(session_context, fault->yang_notif_processed, LYD_XML, LYD_OPT_NOTIF, 0);
857 log_error("lyd_parse_mem failed\n");
861 rc = sr_event_notif_send_tree(current_session_running, notif);
863 if(rc != SR_ERR_OK) {
864 log_error("sr_event_notif_send_tree failed\n");
869 if(ves_fault_enabled) {
870 rc = faults_ves_message_send(current_session_running, fault->condition, fault->object, fault->severity, fault->date_time, fault->specific_problem);
871 if(rc != NTS_ERR_OK) {
872 log_error("faults_ves_message_send failed\n");
876 log_add_verbose(1, "[faults] delaying %d sec\n", new_delay);
880 pthread_mutex_unlock(&faults_lock);
885 sr_session_stop(current_session_running);
886 sr_session_stop(current_session_operational);
891 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) {
892 sr_change_iter_t *it = 0;
894 sr_change_oper_t oper;
895 sr_val_t *old_value = 0;
896 sr_val_t *new_value = 0;
898 if(event == SR_EV_UPDATE) {
899 rc = sr_get_changes_iter(session, NTS_NF_NETWORK_FUNCTION_SCHEMA_XPATH"//.", &it);
900 if(rc != SR_ERR_OK) {
901 log_error("sr_get_changes_iter failed\n");
902 return SR_ERR_VALIDATION_FAILED;
905 while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
907 if(new_value->xpath && (strcmp(new_value->xpath, NTS_NF_NETWORK_FUNCTION_FTYPE_SCHEMA_XPATH) == 0)) {
908 if(old_value && !old_value->dflt) {
909 rc = sr_set_item(session, old_value->xpath, old_value, 0);
910 if(rc != SR_ERR_OK) {
911 log_error("sr_set_item failed\n");
912 return SR_ERR_VALIDATION_FAILED;
917 if(new_value->xpath && (strcmp(new_value->xpath, NTS_NF_NETWORK_FUNCTION_MPAM_SCHEMA_XPATH) == 0)) {
918 if(old_value && !old_value->dflt) {
919 rc = sr_set_item(session, old_value->xpath, old_value, 0);
920 if(rc != SR_ERR_OK) {
921 log_error("sr_set_item failed\n");
922 return SR_ERR_VALIDATION_FAILED;
927 sr_free_val(old_value);
928 sr_free_val(new_value);
931 sr_free_change_iter(it);