+
+static int app_common_hardware_emulation_change_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *private_data) {
+ bool delay = false;
+
+ if(event == SR_EV_UPDATE) {
+ sr_change_iter_t *it = 0;
+ int rc = SR_ERR_OK;
+ sr_change_oper_t oper;
+ sr_val_t *old_value = 0;
+ sr_val_t *new_value = 0;
+
+ rc = sr_get_changes_iter(session, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH"//.", &it);
+ if(rc != SR_ERR_OK) {
+ log_error("sr_get_changes_iter failed\n");
+ return SR_ERR_VALIDATION_FAILED;
+ }
+
+ while((rc = sr_get_change_next(session, it, &oper, &old_value, &new_value)) == SR_ERR_OK) {
+ if(new_value->xpath && (strstr(new_value->xpath, "/netconf-delay/edit-test-list"))) {
+ delay = true;
+ }
+ else if(new_value->xpath && (strstr(new_value->xpath, "/netconf-delay/edit-test"))) {
+ rc = sr_set_item_str(session, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH"/netconf-delay/edit-test", "0", 0, 0);
+ if(rc != SR_ERR_OK) {
+ log_error("sr_set_item failed\n");
+ return SR_ERR_VALIDATION_FAILED;
+ }
+
+ delay = true;
+ }
+
+ sr_free_val(old_value);
+ sr_free_val(new_value);
+ }
+
+ if(delay) {
+ delay = false;
+
+ int32_t sec = netconf_delay / 1000;
+ uint32_t usec = (netconf_delay % 1000) * 1000;
+
+ usleep(usec);
+ if(sec > 0) {
+ sleep(sec);
+ }
+ }
+
+ sr_free_change_iter(it);
+ }
+
+ if(event == SR_EV_DONE) {
+ sr_val_t *values = NULL;
+ size_t count = 0;
+
+ int rc = sr_get_items(session, NTS_NF_HARDWARE_EMULATION_SCHEMA_XPATH"//.", 0, 0, &values, &count);
+ if (rc != SR_ERR_OK) {
+ log_error("sr_get_items failed\n");
+ return rc;
+ }
+
+ for(size_t i = 0; i < count; i++) {
+ if(strstr(values[i].xpath, "/netconf-delay/delay")) {
+ netconf_delay = values[i].data.uint32_val;
+ }
+ }
+
+ sr_free_values(values, count);
+ }
+
+ return SR_ERR_OK;
+}
+
+static int app_common_hardware_emulation_netconf_delay_oper_cb(sr_session_ctx_t *session, const char *module_name, const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) {
+
+ char aux[9];
+ sprintf(aux, "%d", netconf_delay);
+ struct lyd_node *container = lyd_new_path(0, session_context, NTS_NF_HE_NETCONF_DELAY_SCHEMA_XPATH, 0, 0, LYD_PATH_OPT_NOPARENTRET);
+ if(container == 0) {
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ //get test leaf
+ lyd_new_leaf(container, container->schema->module, "get-test", aux);
+
+ //get test list
+ sr_val_t *values = NULL;
+ size_t count = 0;
+ int rc = sr_get_items(session_running, NTS_NF_HE_NETCONF_DELAY_SCHEMA_XPATH"/edit-test-list/*", 0, 0, &values, &count);
+ if (rc != SR_ERR_OK) {
+ log_error("sr_get_items failed\n");
+ return rc;
+ }
+ for(size_t i = 0; i < count; i++) {
+ struct lyd_node *listitem = lyd_new(container, container->schema->module, "get-test-list");
+ if(listitem) {
+ lyd_new_leaf(listitem, container->schema->module, "value", values[i].data.string_val);
+ }
+ }
+
+ sr_free_values(values, count);
+
+
+
+ uint32_t sec = netconf_delay / 1000;
+ uint32_t usec = (netconf_delay % 1000) * 1000;
+
+ usleep(usec);
+ if(sec > 0) {
+ sleep(sec);
+ }
+
+ *parent = container;
+ return SR_ERR_OK;
+}
+
+static int app_common_emulate_total_loss_cb(sr_session_ctx_t *session, const char *path, const sr_val_t *input, const size_t input_cnt, sr_event_t event, uint32_t request_id, sr_val_t **output, size_t *output_cnt, void *private_data) {
+ int rc;
+
+ *output_cnt = 1;
+ rc = sr_new_values(*output_cnt, output);
+ if(SR_ERR_OK != rc) {
+ return rc;
+ }
+
+ rc = sr_val_set_xpath(output[0], NTS_NF_RPC_EMULATE_TOTAL_LOSS_SCHEMA_XPATH"/status");
+ if(SR_ERR_OK != rc) {
+ return rc;
+ }
+
+ sr_val_t *values = NULL;
+ size_t count = 0;
+
+ rc = sr_get_items(session, NTS_NF_NETWORK_EMULATION_SCHEMA_XPATH"//.", 0, 0, &values, &count);
+ if (rc != SR_ERR_OK) {
+ log_error("sr_get_items failed\n");
+ return rc;
+ }
+
+ network_emultation_settings_t s;
+ for(size_t i = 0; i < count; i++) {
+ if(strstr(values[i].xpath, "/limit")) {
+ s.limit = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/time")) {
+ s.delay.time = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/jitter")) {
+ s.delay.jitter = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/correlation")) {
+ s.delay.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/delay/distribution")) {
+ s.delay.distribution = strdup(values[i].data.string_val);
+ }
+ else if(strstr(values[i].xpath, "/loss")) {
+ s.loss = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/corruption/percentage")) {
+ s.corruption.percentage = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/corruption/correlation")) {
+ s.corruption.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/duplication/percentage")) {
+ s.duplication.percentage = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/duplication/correlation")) {
+ s.duplication.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/reordering/percentage")) {
+ s.reordering.percentage = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/reordering/correlation")) {
+ s.reordering.correlation = values[i].data.uint16_val;
+ }
+ else if(strstr(values[i].xpath, "/rate")) {
+ s.rate = values[i].data.uint16_val;
+ }
+ }
+
+ uint16_t old_loss = s.loss;
+ s.loss = 100; //100 percent loss
+
+ sr_free_values(values, count);
+ if(network_emulation_update(&s) != NTS_ERR_OK) {
+ log_error("network_emulation_update() failed\n");
+ free(s.delay.distribution);
+ return SR_ERR_OPERATION_FAILED;
+ }
+
+ int delay = input->data.uint32_val;
+ int32_t sec = delay / 1000;
+ uint32_t usec = (delay % 1000) * 1000;
+
+ usleep(usec);
+ if(sec > 0) {
+ sleep(sec);
+ }
+
+ s.loss = old_loss;
+ if(network_emulation_update(&s) != NTS_ERR_OK) {
+ log_error("network_emulation_update() failed\n");
+ free(s.delay.distribution);
+ return SR_ERR_OPERATION_FAILED;
+ }
+ free(s.delay.distribution);
+
+ rc = sr_val_build_str_data(output[0], SR_ENUM_T, "%s", "SUCCESS");
+ return rc;
+}