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"
28 #include <sysrepo/values.h>
29 #include <libnetconf2/netconf.h>
31 #include "core/framework.h"
32 #include "core/context.h"
33 #include "core/session.h"
34 #include "core/datastore/populate.h"
36 #include "core/faults/faults.h"
38 #include "features/ves_pnf_registration/ves_pnf_registration.h"
39 #include "features/ves_heartbeat/ves_heartbeat.h"
40 #include "features/ves_file_ready/ves_file_ready.h"
41 #include "features/manual_notification/manual_notification.h"
42 #include "features/netconf_call_home/netconf_call_home.h"
43 #include "features/web_cut_through/web_cut_through.h"
45 #define IETF_NETCONF_MONITORING_MODULE "ietf-netconf-monitoring"
46 #define IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH "/ietf-netconf-monitoring:netconf-state/schemas"
48 #define NC_NOTIFICATIONS_MODULE "nc-notifications"
49 #define NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH "/nc-notifications:netconf/streams"
51 #define NTS_NETWORK_FUNCTION_MODULE "nts-network-function"
52 #define NTS_NETWORK_FUNCTION_SCHEMA_XPATH "/nts-network-function:simulation/network-function"
54 #define POPULATE_RPC_SCHEMA_XPATH "/nts-network-function:datastore-random-populate"
55 #define FEATURE_CONTROL_SCHEMA_XPATH "/nts-network-function:feature-control"
56 #define FAULTS_CLEAR_SCHEMA_XPATH "/nts-network-function:clear-fault-counters"
57 #define FAULTS_LIST_SCHEMA_XPATH "/nts-network-function:simulation/network-function/fault-generation"
58 #define FAULTS_COUNT_LIST_SCHEMA_XPATH "/nts-network-function:simulation/network-function/fault-generation/fault-count"
59 #define FAULTS_NC_ENABLED_SCHEMA_XPATH "/nts-network-function:simulation/network-function/netconf/faults-enabled"
60 #define FAULTS_VES_ENABLED_SCHEMA_XPATH "/nts-network-function:simulation/network-function/ves/faults-enabled"
62 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);
63 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);
65 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);
66 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);
67 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);
68 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);
69 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);
71 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);
73 static int faults_update_config(sr_session_ctx_t *session); //not protected by lock
74 static void *faults_thread_routine(void *arg);
76 static pthread_mutex_t nf_function_control_lock;
77 static char *nf_function_control_string = 0;
79 static pthread_t faults_thread;
80 static pthread_mutex_t faults_lock;
82 static pthread_mutex_t network_function_change_lock;
83 static char *function_type_default = 0;
84 static char *function_type_val = 0;
85 static char *mount_point_addressing_method_default = 0;
86 static char *mount_point_addressing_method_val = 0;
88 int network_function_run(void) {
91 log_message(1, LOG_COLOR_BOLD_YELLOW"\nrunning as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET);
93 if(pthread_mutex_init(&nf_function_control_lock, NULL) != 0) {
94 log_error("mutex init has failed");
95 return NTS_ERR_FAILED;
98 //ietf-netconf-monitoring schemas populate with modules and submodules (overwrite default Netopeer2 behaviour)
99 int 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);
100 if(rc != SR_ERR_OK) {
101 log_error("error from sr_oper_get_items_subscribe: %s", sr_strerror(rc));
105 //nc-notifications overwrite
106 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);
107 if(rc != SR_ERR_OK) {
108 log_error("error from sr_oper_get_items_subscribe: %s", sr_strerror(rc));
113 rc = sr_rpc_subscribe(session_running, POPULATE_RPC_SCHEMA_XPATH, network_function_populate_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
114 if(rc != SR_ERR_OK) {
115 log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc));
116 return NTS_ERR_FAILED;
120 rc = sr_rpc_subscribe(session_running, FEATURE_CONTROL_SCHEMA_XPATH, network_function_feature_control_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
121 if(rc != SR_ERR_OK) {
122 log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc));
123 return NTS_ERR_FAILED;
127 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);
128 if(rc != SR_ERR_OK) {
129 log_error("could not subscribe to faults");
133 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);
134 if(rc != SR_ERR_OK) {
135 log_error("could not subscribe to oper faults: %s", sr_strerror(rc));
139 rc = sr_rpc_subscribe(session_running, FAULTS_CLEAR_SCHEMA_XPATH, network_function_faults_clear_cb, 0, 0, SR_SUBSCR_CTX_REUSE, &session_subscription);
140 if(rc != SR_ERR_OK) {
141 log_error("error from sr_rpc_subscribe: %s", sr_strerror(rc));
142 return NTS_ERR_FAILED;
145 //subscribe to any changes on the main
146 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, &session_subscription);
147 if(rc != SR_ERR_OK) {
148 log_error("could not subscribe to simulation changes");
149 return NTS_ERR_FAILED;
153 if(rc != NTS_ERR_OK) {
154 log_error("faults_init error", sr_strerror(rc));
155 return NTS_ERR_FAILED;
158 if(pthread_mutex_init(&faults_lock, NULL) != 0) {
159 log_error("mutex init has failed");
160 return NTS_ERR_FAILED;
163 if(pthread_create(&faults_thread, 0, faults_thread_routine, 0)) {
164 log_error("could not create thread for heartbeat");
165 return NTS_ERR_FAILED;
168 if(pthread_mutex_init(&network_function_change_lock, NULL) != 0) {
169 log_error("mutex init has failed");
170 return NTS_ERR_FAILED;
173 while(!framework_sigint) {
174 pthread_mutex_lock(&network_function_change_lock);
175 if(function_type_val) {
176 rc = sr_set_item_str(session_running, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/function-type", function_type_val, 0, 0);
177 if(rc != SR_ERR_OK) {
178 log_error("sr_set_item_str failed");
181 rc = sr_apply_changes(session_running, 0, 0);
182 if(rc != SR_ERR_OK) {
183 log_error("sr_apply_changes failed");
186 function_type_val = 0;
189 if(mount_point_addressing_method_val) {
190 rc = sr_set_item_str(session_running, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/mount-point-addressing-method", mount_point_addressing_method_val, 0, 0);
191 if(rc != SR_ERR_OK) {
192 log_error("sr_set_item_str failed");
195 rc = sr_apply_changes(session_running, 0, 0);
196 if(rc != SR_ERR_OK) {
197 log_error("sr_apply_changes failed");
200 mount_point_addressing_method_val = 0;
202 pthread_mutex_unlock(&network_function_change_lock);
204 pthread_mutex_lock(&nf_function_control_lock);
205 if(nf_function_control_string) {
206 if(strstr(nf_function_control_string, "ves-file-ready") != 0) {
207 // start feature for handling the fileReady VES message
208 rc = ves_file_ready_feature_start(session_running);
210 log_error("ves_file_ready_feature_start() failed");
214 if(strstr(nf_function_control_string, "ves-pnf-registration") != 0) {
215 // check if PNF registration is enabled and send PNF registration message if so
216 rc = ves_pnf_registration_feature_start(session_running);
218 log_error("ves_pnf_registration_feature_start() failed");
222 if(strstr(nf_function_control_string, "ves-heartbeat") != 0) {
223 // start feature for handling the heartbeat VES message
224 rc = ves_heartbeat_feature_start(session_running);
226 log_error("ves_heartbeat_feature_start() failed");
230 if(strstr(nf_function_control_string, "manual-notification-generation") != 0) {
231 // start feature for manual notification
232 rc = manual_notification_feature_start(session_running);
234 log_error("manual_notification_feature_start() failed");
238 if(strstr(nf_function_control_string, "netconf-call-home") != 0) {
239 // start feature for NETCONF Call Home
240 rc = netconf_call_home_feature_start(session_running);
242 log_error("netconf_call_home_feature_start() failed");
246 if(strstr(nf_function_control_string, "web-cut-through") != 0) {
247 // start feature for NETCONF Call Home
248 rc = web_cut_through_feature_start(session_running);
250 log_error("web_cut_through_feature_start() failed");
254 free(nf_function_control_string);
255 nf_function_control_string = 0;
257 pthread_mutex_unlock(&nf_function_control_lock);
267 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) {
268 struct lyd_node *root = 0;
269 root = lyd_new_path(*parent, session_context, IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH, 0, 0, 0);
271 struct lyd_node *list = 0;
272 const struct lys_module *mod = 0;
273 const struct lys_submodule *submod = 0;
276 // get all modules from context
277 while ((mod = ly_ctx_get_module_iter(session_context, &i))) {
278 list = lyd_new(root, NULL, "schema");
279 lyd_new_leaf(list, NULL, "identifier", mod->name);
280 lyd_new_leaf(list, NULL, "version", (mod->rev ? mod->rev[0].date : NULL));
281 lyd_new_leaf(list, NULL, "format", "yang");
282 lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
283 lyd_new_leaf(list, NULL, "location", "NETCONF");
285 // iterate all the submodules included by a module
286 for (int j = 0; j < mod->inc_size; j++) {
287 submod = mod->inc[j].submodule;
289 list = lyd_new(root, NULL, "schema");
290 lyd_new_leaf(list, NULL, "identifier", submod->name);
291 lyd_new_leaf(list, NULL, "version", (submod->rev ? submod->rev[0].date : NULL));
292 lyd_new_leaf(list, NULL, "format", "yang");
293 lyd_new_leaf(list, NULL, "namespace", lys_main_module(mod)->ns);
294 lyd_new_leaf(list, NULL, "location", "NETCONF");
301 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) {
302 struct lyd_node *root = lyd_new_path(0, session_context, NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH, 0, 0, 0);
305 struct lyd_node *stream = lyd_new_path(root, 0, "/nc-notifications:netconf/streams/stream[name='NETCONF']", NULL, 0, 0);
306 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.");
307 lyd_new_leaf(stream, stream->schema->module, "replaySupport", "true");
309 /* all other streams */
310 struct lyd_node *sr_data;
311 struct lyd_node *sr_mod;
312 /* go through all the sysrepo modules */
313 int rc = sr_get_module_info(session_connection, &sr_data);
314 if(rc != SR_ERR_OK) {
315 log_error("sr_get_module_info failed");
316 return SR_ERR_OPERATION_FAILED;
319 LY_TREE_FOR(sr_data->child, sr_mod) {
320 const char *mod_name = ((struct lyd_node_leaf_list *)sr_mod->child)->value_str;
321 const struct lys_module *mod = ly_ctx_get_module(session_context, mod_name, 0, 1);
322 int has_notifications = 0;
323 struct lys_node *data = mod->data;
325 if(data->nodetype == LYS_NOTIF) {
326 has_notifications = 1;
331 if(has_notifications) {
332 /* generate information about the stream/module */
333 stream = lyd_new(root->child, NULL, "stream");
334 lyd_new_leaf(stream, NULL, "name", mod_name);
335 lyd_new_leaf(stream, NULL, "description", "Stream with all notifications of a module.");
337 struct lyd_node *rep_sup = 0;
338 struct ly_set *set = lyd_find_path(sr_mod, "replay-support");
339 if(set && (set->number == 1)) {
340 rep_sup = set->set.d[0];
344 lyd_new_leaf(stream, NULL, "replaySupport", rep_sup ? "true" : "false");
347 nc_time2datetime(((struct lyd_node_leaf_list *)rep_sup)->value.uint64, NULL, buf);
348 lyd_new_leaf(stream, NULL, "replayLogCreationTime", buf);
353 lyd_free_withsiblings(sr_data);
359 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) {
363 rc = sr_new_values(*output_cnt, output);
364 if(SR_ERR_OK != rc) {
368 rc = sr_val_set_xpath(output[0], POPULATE_RPC_SCHEMA_XPATH"/status");
369 if(SR_ERR_OK != rc) {
373 rc = schema_populate();
374 if(rc != NTS_ERR_OK) {
375 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
378 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
384 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) {
386 int total_errors = 0;
389 rc = sr_new_values(*output_cnt, output);
390 if(SR_ERR_OK != rc) {
394 rc = sr_val_set_xpath(output[0], FEATURE_CONTROL_SCHEMA_XPATH"/status");
395 if(SR_ERR_OK != rc) {
399 if(total_errors != 0) {
400 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
403 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
406 pthread_mutex_lock(&nf_function_control_lock);
407 nf_function_control_string = strdup(input[0].data.bits_val);
408 pthread_mutex_unlock(&nf_function_control_lock);
413 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) {
417 rc = sr_new_values(*output_cnt, output);
418 if(SR_ERR_OK != rc) {
422 rc = sr_val_set_xpath(output[0], FAULTS_CLEAR_SCHEMA_XPATH"/status");
423 if(SR_ERR_OK != rc) {
427 pthread_mutex_lock(&faults_lock);
428 faults_counters_clear();
429 pthread_mutex_unlock(&faults_lock);
431 rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
435 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) {
438 if(event == SR_EV_DONE) {
439 pthread_mutex_lock(&faults_lock);
440 rc = faults_update_config(session);
441 pthread_mutex_unlock(&faults_lock);
442 if(rc != NTS_ERR_OK) {
443 log_error("faults_update_config failed");
444 return SR_ERR_VALIDATION_FAILED;
451 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) {
452 pthread_mutex_lock(&faults_lock);
453 fault_counters_t counters = faults_counters_get();
454 pthread_mutex_unlock(&faults_lock);
457 *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), FAULTS_COUNT_LIST_SCHEMA_XPATH, 0, 0, 0);
459 return SR_ERR_OPERATION_FAILED;
462 sprintf(value, "%d", counters.normal);
463 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/normal", value, 0, 0) == 0) {
464 return SR_ERR_OPERATION_FAILED;
467 sprintf(value, "%d", counters.warning);
468 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/warning", value, 0, 0) == 0) {
469 return SR_ERR_OPERATION_FAILED;
472 sprintf(value, "%d", counters.minor);
473 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/minor", value, 0, 0) == 0) {
474 return SR_ERR_OPERATION_FAILED;
477 sprintf(value, "%d", counters.major);
478 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/major", value, 0, 0) == 0) {
479 return SR_ERR_OPERATION_FAILED;
482 sprintf(value, "%d", counters.critical);
483 if(lyd_new_path(*parent, NULL, FAULTS_COUNT_LIST_SCHEMA_XPATH"/critical", value, 0, 0) == 0) {
484 return SR_ERR_OPERATION_FAILED;
490 static int faults_update_config(sr_session_ctx_t *session) {
494 int ret = NTS_ERR_OK;
497 struct lyd_node *data;
498 rc = sr_get_subtree(session, FAULTS_LIST_SCHEMA_XPATH, 0, &data);
499 if(rc != SR_ERR_OK) {
500 log_error("sr_get_subtree failed");
501 ret = NTS_ERR_FAILED;
504 faults_fault_list_clear();
505 faults_counters_clear();
506 if(data->child == 0) {
507 goto faults_update_config_free;
510 struct lyd_node *chd = 0;
511 LY_TREE_FOR(data->child, chd) {
512 if(strcmp(chd->schema->name, "fault-delay-list") == 0) {
513 struct lyd_node *delay_list_entry = 0;
514 LY_TREE_FOR(chd->child, delay_list_entry) {
515 if(strcmp(delay_list_entry->schema->name, "delay-period") == 0) {
516 rc = faults_fault_list_add(((const struct lyd_node_leaf_list *)delay_list_entry)->value.uint16);
517 if(rc != NTS_ERR_OK) {
518 log_error("faults_fault_list_add failed");
519 ret = NTS_ERR_FAILED;
520 goto faults_update_config_free;
528 faults_update_config_free:
534 static void *faults_thread_routine(void *arg) {
537 sr_session_ctx_t *current_session_running = 0;
538 rc = sr_session_start(session_connection, SR_DS_RUNNING, ¤t_session_running);
539 if (rc != SR_ERR_OK) {
540 log_error("sr_session_start failed");
544 sr_session_ctx_t *current_session_operational = 0;
545 rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, ¤t_session_operational);
546 if (rc != SR_ERR_OK) {
547 log_error("sr_session_start failed");
551 pthread_mutex_lock(&faults_lock);
552 rc = faults_update_config(current_session_running);
553 if(rc != NTS_ERR_OK) {
554 log_error("faults_update_config failed");
557 pthread_mutex_unlock(&faults_lock);
559 while(!framework_sigint) {
560 pthread_mutex_lock(&faults_lock);
561 if(faults_fault_list_not_empty()) {
562 uint16_t new_delay = faults_fault_list_get_next();
564 fault_details_t *fault = faults_generate_fault();
566 log_error("faults_generate_fault failed");
567 pthread_mutex_unlock(&faults_lock);
572 rc = faults_counters_increase(fault->severity);
573 if(rc != NTS_ERR_OK) {
574 log_error("faults_counters_increase failed");
576 pthread_mutex_unlock(&faults_lock);
579 bool nc_fault_enabled = false;
580 bool ves_fault_enabled = false;
582 rc = sr_get_item(current_session_running, FAULTS_NC_ENABLED_SCHEMA_XPATH, 0, &val);
583 if(rc == SR_ERR_OK) {
584 nc_fault_enabled = val->data.bool_val;
588 rc = sr_get_item(current_session_running, FAULTS_VES_ENABLED_SCHEMA_XPATH, 0, &val);
589 if(rc == SR_ERR_OK) {
590 ves_fault_enabled = val->data.bool_val;
594 if(nc_fault_enabled) {
595 struct lyd_node *notif = 0;
596 notif = lyd_parse_mem(session_context, fault->yang_notif_processed, LYD_XML, LYD_OPT_NOTIF, 0);
598 log_error("lyd_parse_mem failed");
602 rc = sr_event_notif_send_tree(current_session_running, notif);
604 if(rc != SR_ERR_OK) {
605 log_error("sr_event_notif_send_tree failed");
610 if(ves_fault_enabled) {
611 rc = faults_ves_message_send(current_session_running, fault->condition, fault->object, fault->severity, fault->date_time, fault->specific_problem);
612 if(rc != NTS_ERR_OK) {
613 log_error("faults_ves_message_send failed");
620 pthread_mutex_unlock(&faults_lock);
625 sr_session_stop(current_session_running);
626 sr_session_stop(current_session_operational);
631 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) {
632 sr_change_iter_t *it = 0;
634 sr_change_oper_t oper;
635 sr_val_t *old_value = 0;
636 sr_val_t *new_value = 0;
638 static bool function_type_set = false;
639 static bool mount_point_addressing_method_set = false;
641 if(event == SR_EV_DONE) {
642 rc = sr_get_changes_iter(session, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"//.", &it);
643 if(rc != SR_ERR_OK) {
644 log_error("sr_get_changes_iter failed");
645 return SR_ERR_VALIDATION_FAILED;
648 while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
650 if(new_value->xpath && (strcmp(new_value->xpath, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/function-type") == 0)) {
651 if(function_type_set == false) {
652 function_type_set = true;
653 function_type_default = strdup(new_value->data.string_val);
656 //prevent changing function_type
657 if(strcmp(new_value->data.string_val, function_type_default) != 0) {
658 pthread_mutex_lock(&network_function_change_lock);
659 function_type_val = function_type_default;
660 pthread_mutex_unlock(&network_function_change_lock);
665 if(new_value->xpath && (strcmp(new_value->xpath, NTS_NETWORK_FUNCTION_SCHEMA_XPATH"/mount-point-addressing-method") == 0)) {
666 if(mount_point_addressing_method_set == false) {
667 mount_point_addressing_method_set = true;
668 mount_point_addressing_method_default = strdup(new_value->data.string_val);
671 //prevent changing mount_point_addressing_method
672 if(strcmp(new_value->data.string_val, mount_point_addressing_method_default) != 0) {
673 pthread_mutex_lock(&network_function_change_lock);
674 mount_point_addressing_method_val = mount_point_addressing_method_default;
675 pthread_mutex_unlock(&network_function_change_lock);
680 sr_free_val(old_value);
681 sr_free_val(new_value);
684 sr_free_change_iter(it);