5a66d18125879bb7a4447034a2eda29b12a582d3
[sim/o1-interface.git] / ntsimulator / ntsim-ng / core / app / network_function.c
1 /*************************************************************************
2 *
3 * Copyright 2020 highstreet technologies GmbH and others
4 *
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
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
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 ***************************************************************************/
17
18 #define _GNU_SOURCE
19
20 #include "network_function.h"
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include <stdio.h>
24 #include <pthread.h>
25 #include <assert.h>
26
27 #include <sysrepo.h>
28 #include <sysrepo/values.h>
29 #include <libnetconf2/netconf.h>
30
31 #include "core/framework.h"
32 #include "core/context.h"
33 #include "core/session.h"
34 #include "core/datastore/populate.h"
35
36 #include "core/faults/faults.h"
37
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"
44
45 #define IETF_NETCONF_MONITORING_MODULE                          "ietf-netconf-monitoring"
46 #define IETF_NETCONF_MONITORING_STATE_SCHEMAS_SCHEMA_XPATH      "/ietf-netconf-monitoring:netconf-state/schemas"
47
48 #define NC_NOTIFICATIONS_MODULE                                 "nc-notifications"
49 #define NC_NOTIFICATIONS_STREAMS_SCHEMA_XPATH                   "/nc-notifications:netconf/streams"
50
51 #define NTS_NETWORK_FUNCTION_MODULE                             "nts-network-function"
52 #define NTS_NETWORK_FUNCTION_SCHEMA_XPATH                       "/nts-network-function:simulation/network-function"
53
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"
61
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);
64
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);
70
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);
72
73 static int faults_update_config(sr_session_ctx_t *session);                 //not protected by lock
74 static void *faults_thread_routine(void *arg);
75
76 static pthread_mutex_t nf_function_control_lock;
77 static char *nf_function_control_string = 0;
78
79 static pthread_t faults_thread;
80 static pthread_mutex_t faults_lock;
81
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;
87
88 int network_function_run(void) {
89     assert_session();
90
91     log_message(1, LOG_COLOR_BOLD_YELLOW"\nrunning as NETWORK FUNCTION daemon...\n"LOG_COLOR_RESET);
92
93     if(pthread_mutex_init(&nf_function_control_lock, NULL) != 0) { 
94         log_error("mutex init has failed"); 
95         return NTS_ERR_FAILED; 
96     }
97
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));
102         return 0;
103     }
104
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));
109         return 0;
110     }
111
112     //populate
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;
117     }
118
119     //feature control
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;
124     }
125
126     //faults
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");
130         return 0;
131     }
132
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));
136         return 0;
137     }
138
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;
143     }
144
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;
150     }
151
152     rc = faults_init();
153     if(rc != NTS_ERR_OK) {
154         log_error("faults_init error", sr_strerror(rc));
155         return NTS_ERR_FAILED;
156     }
157
158     if(pthread_mutex_init(&faults_lock, NULL) != 0) { 
159         log_error("mutex init has failed"); 
160         return NTS_ERR_FAILED; 
161     }
162
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;
166     }
167
168     if(pthread_mutex_init(&network_function_change_lock, NULL) != 0) { 
169         log_error("mutex init has failed"); 
170         return NTS_ERR_FAILED; 
171     }
172
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");
179             }
180
181             rc = sr_apply_changes(session_running, 0, 0);
182             if(rc != SR_ERR_OK) {
183                 log_error("sr_apply_changes failed");
184             }
185
186             function_type_val = 0;
187         }
188
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");
193             }
194
195             rc = sr_apply_changes(session_running, 0, 0);
196             if(rc != SR_ERR_OK) {
197                 log_error("sr_apply_changes failed");
198             }
199
200             mount_point_addressing_method_val = 0;
201         }
202         pthread_mutex_unlock(&network_function_change_lock);
203
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);
209                 if(rc != 0) {
210                     log_error("ves_file_ready_feature_start() failed");
211                 }
212             }
213
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);
217                 if(rc != 0) {
218                     log_error("ves_pnf_registration_feature_start() failed");
219                 }
220             }
221
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);
225                 if(rc != 0) {
226                     log_error("ves_heartbeat_feature_start() failed");
227                 }
228             }
229
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);
233                 if(rc != 0) {
234                     log_error("manual_notification_feature_start() failed");
235                 }
236             }
237
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);
241                 if(rc != 0) {
242                     log_error("netconf_call_home_feature_start() failed");
243                 }
244             }
245
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);
249                 if(rc != 0) {
250                     log_error("web_cut_through_feature_start() failed");
251                 }
252             }
253
254             free(nf_function_control_string);
255             nf_function_control_string = 0;
256         }
257         pthread_mutex_unlock(&nf_function_control_lock);
258
259         sleep(1);
260     }
261
262     faults_free();
263
264     return NTS_ERR_OK;
265 }
266
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);
270
271     struct lyd_node *list = 0;
272     const struct lys_module *mod = 0;
273     const struct lys_submodule *submod = 0;
274     uint32_t i = 0;
275
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");
284
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;
288
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");
295         }
296     }
297
298     return SR_ERR_OK;
299 }
300
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);
303
304     /* generic stream */
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");
308     
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;
317     }
318
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;
324         while(data) {
325             if(data->nodetype == LYS_NOTIF) {
326                 has_notifications = 1;
327             }
328             data = data->next;
329         }
330
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.");
336
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];
341             }
342             ly_set_free(set);
343             
344             lyd_new_leaf(stream, NULL, "replaySupport", rep_sup ? "true" : "false");
345             if(rep_sup) {
346                 char buf[26];
347                 nc_time2datetime(((struct lyd_node_leaf_list *)rep_sup)->value.uint64, NULL, buf);
348                 lyd_new_leaf(stream, NULL, "replayLogCreationTime", buf);
349             }
350         }
351     }
352
353     lyd_free_withsiblings(sr_data);
354     *parent = root;
355
356     return SR_ERR_OK;
357 }
358
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) {
360     int rc;
361
362     *output_cnt = 1;
363     rc = sr_new_values(*output_cnt, output);
364     if(SR_ERR_OK != rc) {
365         return rc;
366     }
367
368     rc = sr_val_set_xpath(output[0], POPULATE_RPC_SCHEMA_XPATH"/status");
369     if(SR_ERR_OK != rc) {
370         return rc;
371     }
372
373     rc = schema_populate();
374     if(rc != NTS_ERR_OK) {
375         rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
376     }
377     else {
378         rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
379     }
380
381     return rc;
382 }
383
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) {
385     int rc;
386     int total_errors = 0;
387
388     *output_cnt = 1;
389     rc = sr_new_values(*output_cnt, output);
390     if(SR_ERR_OK != rc) {
391         return rc;
392     }
393
394     rc = sr_val_set_xpath(output[0], FEATURE_CONTROL_SCHEMA_XPATH"/status");
395     if(SR_ERR_OK != rc) {
396         return rc;
397     }
398
399     if(total_errors != 0) {
400         rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "ERROR");
401     }
402     else {
403         rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
404     }
405
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);
409
410     return rc;
411 }
412
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) {
414     int rc;
415
416     *output_cnt = 1;
417     rc = sr_new_values(*output_cnt, output);
418     if(SR_ERR_OK != rc) {
419         return rc;
420     }
421
422     rc = sr_val_set_xpath(output[0], FAULTS_CLEAR_SCHEMA_XPATH"/status");
423     if(SR_ERR_OK != rc) {
424         return rc;
425     }
426
427     pthread_mutex_lock(&faults_lock);
428     faults_counters_clear();
429     pthread_mutex_unlock(&faults_lock);
430
431     rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
432     return rc;
433 }
434
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) {
436     int rc = SR_ERR_OK;
437
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;
445         }
446     }
447
448     return SR_ERR_OK;
449 }
450
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);
455     char value[20];
456
457     *parent = lyd_new_path(NULL, sr_get_context(sr_session_get_connection(session)), FAULTS_COUNT_LIST_SCHEMA_XPATH, 0, 0, 0);
458     if(*parent == 0) {
459         return SR_ERR_OPERATION_FAILED;
460     }
461
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;
465     }
466
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;
470     }
471
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;
475     }
476
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;
480     }
481
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;
485     }
486
487     return SR_ERR_OK;
488 }
489
490 static int faults_update_config(sr_session_ctx_t *session) {
491     assert(session);
492     assert_session();
493
494     int ret = NTS_ERR_OK;
495     
496     int rc;
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;
502     }
503
504     faults_fault_list_clear();
505     faults_counters_clear();
506     if(data->child == 0) {
507         goto faults_update_config_free;
508     }
509
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;
521                     }
522                 }
523             }
524         }
525         
526     }
527     
528     faults_update_config_free:
529     lyd_free(data);
530
531     return ret;
532 }
533
534 static void *faults_thread_routine(void *arg) {
535     int rc = 0;
536
537     sr_session_ctx_t *current_session_running = 0;
538     rc = sr_session_start(session_connection, SR_DS_RUNNING, &current_session_running);
539     if (rc != SR_ERR_OK) {
540         log_error("sr_session_start failed");
541         return 0;
542     }
543
544     sr_session_ctx_t *current_session_operational = 0;
545     rc = sr_session_start(session_connection, SR_DS_OPERATIONAL, &current_session_operational);
546     if (rc != SR_ERR_OK) {
547         log_error("sr_session_start failed");
548         return 0;
549     }
550
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");
555         return 0;
556     }
557     pthread_mutex_unlock(&faults_lock);
558
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();
563
564             fault_details_t *fault = faults_generate_fault();
565             if(fault == 0) {
566                 log_error("faults_generate_fault failed");
567                 pthread_mutex_unlock(&faults_lock);
568                 sleep(1);
569                 continue;
570             }
571
572             rc = faults_counters_increase(fault->severity);
573             if(rc != NTS_ERR_OK) {
574                 log_error("faults_counters_increase failed");
575             }
576             pthread_mutex_unlock(&faults_lock);
577
578             sr_val_t *val = 0;
579             bool nc_fault_enabled = false;
580             bool ves_fault_enabled = false;
581
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;
585                 sr_free_val(val);
586             }
587
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;
591                 sr_free_val(val);
592             }
593
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);
597                 if(notif == 0) {
598                     log_error("lyd_parse_mem failed");
599                     goto fault_send_ves;
600                 }
601                 
602                 rc = sr_event_notif_send_tree(current_session_running, notif);
603                 lyd_free(notif);
604                 if(rc != SR_ERR_OK) {
605                     log_error("sr_event_notif_send_tree failed");
606                 }
607             }
608
609             fault_send_ves:
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");
614                 }
615             }
616
617             sleep(new_delay);
618         }
619         else {
620             pthread_mutex_unlock(&faults_lock);
621             sleep(1);
622         }
623     }
624
625     sr_session_stop(current_session_running);
626     sr_session_stop(current_session_operational);
627
628     return 0;
629 }
630
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;
633     int rc = SR_ERR_OK;
634     sr_change_oper_t oper;
635     sr_val_t *old_value = 0;
636     sr_val_t *new_value = 0;
637
638     static bool function_type_set = false;
639     static bool mount_point_addressing_method_set = false;
640
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;
646         }
647
648         while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
649             
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);
654                 }
655                 else {
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);
661                     }
662                 }
663             }
664
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);
669                 }
670                 else {
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);
676                     }
677                 }
678             }
679
680             sr_free_val(old_value);
681             sr_free_val(new_value);
682         }
683
684         sr_free_change_iter(it);
685     }
686
687     return SR_ERR_OK;
688 }