diff options
Diffstat (limited to 'src/plugins/openconfig')
-rw-r--r-- | src/plugins/openconfig/openconfig_interfaces.c | 646 | ||||
-rw-r--r-- | src/plugins/openconfig/openconfig_interfaces.cpp | 309 | ||||
-rw-r--r-- | src/plugins/openconfig/openconfig_local_routing.c | 548 |
3 files changed, 309 insertions, 1194 deletions
diff --git a/src/plugins/openconfig/openconfig_interfaces.c b/src/plugins/openconfig/openconfig_interfaces.c deleted file mode 100644 index 67b9a3c..0000000 --- a/src/plugins/openconfig/openconfig_interfaces.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright (c) 2018 PANTHEON.tech. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <string.h> - -#include <scvpp/comm.h> -#include <scvpp/interface.h> -#include <scvpp/ip.h> - -#include <sc_plugins.h> - -// XPATH: /openconfig-interfaces:interfaces/interface[name='%s']/config/ -static int openconfig_interfaces_interfaces_interface_config_cb( - sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event, - void *private_ctx) -{ - UNUSED(private_ctx); - sr_change_iter_t *it = NULL; - sr_change_oper_t oper; - sr_xpath_ctx_t state = {0}; - sr_val_t *old = NULL; - sr_val_t *new = NULL; - char *tmp = NULL; - char interface_name[XPATH_SIZE] = {0}; - int rc = 0; - - SRP_LOG_INF("In %s", __FUNCTION__); - SRP_LOG_INF("XPATH %s", xpath); - - ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); - - if (event == SR_EV_APPLY) - return SR_ERR_OK; - - if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) { - sr_free_change_iter(it); - return SR_ERR_OK; - } - - foreach_change (ds, it, oper, old, new) { - - SRP_LOG_DBG("xpath: %s", new->xpath); - - tmp = sr_xpath_key_value(new->xpath, "interface", "name", &state); - if (!tmp) { - sr_set_error(ds, "XPATH interface name NOT found", new->xpath); - return SR_ERR_INVAL_ARG; - } - strncpy(interface_name, tmp, XPATH_SIZE); - sr_xpath_recover(&state); - - switch (oper) { - case SR_OP_CREATED: - case SR_OP_MODIFIED: - if (sr_xpath_node_name_eq(new->xpath, "name")) { - //TODO: LEAF: name, type: string - } else if(sr_xpath_node_name_eq(new->xpath, "type")) { - //TODO: LEAF: type, type: identityref - } else if(sr_xpath_node_name_eq(new->xpath, "mtu")) { - //TODO: LEAF: mtu, type: uint16 - } else if(sr_xpath_node_name_eq(new->xpath, - "loopback-mode")) { - //TODO: LEAF: loopback-mode, type: boolean - } else if(sr_xpath_node_name_eq(new->xpath, - "description")) { - //TODO: LEAF: description, type: string - } else if(sr_xpath_node_name_eq(new->xpath, "enabled")) { - rc = interface_enable(interface_name, - new->data.bool_val); - } else if(sr_xpath_node_name_eq(new->xpath, - "oc-vlan:tpid")) { - //TODO: LEAF: oc-vlan:tpid, type: identityref - } - break; - - case SR_OP_MOVED: - break; - - case SR_OP_DELETED: - if (sr_xpath_node_name_eq(old->xpath, "name")) { - //TODO: LEAF: name, type: string - } else if(sr_xpath_node_name_eq(old->xpath, "type")) { - //TODO: LEAF: type, type: identityref - } else if(sr_xpath_node_name_eq(old->xpath, "mtu")) { - //TODO: LEAF: mtu, type: uint16 - } else if(sr_xpath_node_name_eq(old->xpath, - "loopback-mode")) { - //TODO: LEAF: loopback-mode, type: boolean - } else if(sr_xpath_node_name_eq(old->xpath, - "description")) { - //TODO: LEAF: description, type: string - } else if(sr_xpath_node_name_eq(old->xpath, "enabled")) { - rc = interface_enable(interface_name, false); - } else if(sr_xpath_node_name_eq(old->xpath, - "oc-vlan:tpid")) { - //TODO: LEAF: oc-vlan:tpid, type: identityref - } - break; - } - - if (0 != rc) { - sr_xpath_recover(&state); - - sr_free_val(old); - sr_free_val(new); - - sr_free_change_iter(it); - - return SR_ERR_OPERATION_FAILED; - } - - sr_xpath_recover(&state); - - sr_free_val(old); - sr_free_val(new); - } - - sr_free_change_iter(it); - return SR_ERR_OK; -} - -//XPATH : /openconfig-interfaces:interfaces/interface/state -static int -openconfig_interfaces_interfaces_interface_state_cb( - const char *xpath, sr_val_t **values, - size_t *values_cnt, uint64_t request_id, const char *original_xpath, - void *private_ctx) -{ - UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); - sw_interface_dump_t reply = {0}; - sr_val_t *vals = NULL; - sr_xpath_ctx_t state = {0}; - char interface_name[VPP_INTFC_NAME_LEN] = {0}; - char xpath_root[XPATH_SIZE]; - int vc = 10; - char *tmp; - int rc; - - SRP_LOG_INF("In %s", __FUNCTION__); - - ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); - - tmp = sr_xpath_key_value((char*) xpath, "interface", "name", &state); - if (!tmp) { - SRP_LOG_ERR_MSG("XPATH interface name not found"); - return SR_ERR_INVAL_ARG; - } - strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN); - sr_xpath_recover(&state); - - snprintf(xpath_root, XPATH_SIZE, - "/openconfig-interfaces:interfaces/interface[name='%s']/state", - interface_name); - - //dump interface interface_name - rc = interface_dump_iface(&reply, interface_name); - if (rc == -SCVPP_NOT_FOUND) { - SRP_LOG_ERR_MSG("interface not found"); - return SR_ERR_NOT_FOUND; - } - - rc = sr_new_values(vc, &vals); - if (SR_ERR_OK != rc) - return rc; - - sr_val_build_xpath(&vals[0], "%s/name", xpath_root); - sr_val_set_str_data(&vals[0], SR_STRING_T, (char *)reply.interface_name); - - sr_val_build_xpath(&vals[1], "%s/type", xpath_root); - sr_val_set_str_data(&vals[1], SR_IDENTITYREF_T, "ianaift:ethernetCsmacd"); - - sr_val_build_xpath(&vals[2], "%s/mtu", xpath_root); - vals[2].type = SR_UINT16_T; - vals[2].data.uint16_val = reply.link_mtu; - - sr_val_build_xpath(&vals[3], "%s/loopback-mode", xpath_root); - vals[3].type = SR_BOOL_T; - if (strncmp((char*)reply.interface_name, "loop", 4) == 0) - vals[3].data.bool_val = 1; - else - vals[3].data.bool_val = 0; - - sr_val_build_xpath(&vals[4], "%s/description", xpath_root); - sr_val_set_str_data(&vals[4], SR_STRING_T, NOT_AVAL); - - sr_val_build_xpath(&vals[5], "%s/enabled", xpath_root); - vals[5].type = SR_BOOL_T; - vals[5].data.bool_val = reply.admin_up_down; - - sr_val_build_xpath(&vals[6], "%s/ifindex", xpath_root); - vals[6].type = SR_UINT32_T; - vals[6].data.uint32_val = reply.sw_if_index; - - sr_val_build_xpath(&vals[7], "%s/admin-status", xpath_root); - sr_val_set_str_data(&vals[7], SR_ENUM_T, - reply.admin_up_down ? "UP" : "DOWN"); - - sr_val_build_xpath(&vals[8], "%s/oper-status", xpath_root); - sr_val_set_str_data(&vals[8], SR_ENUM_T, - reply.link_up_down ? "UP" : "DOWN"); - - //TODO: Openconfig required this value - // sr_val_build_xpath(&vals[9], "%s/last-change", xpath_root); - // sr_val_set_str_data(&vals[9], YANG INPUT TYPE: oc-types:timeticks64); - - sr_val_build_xpath(&vals[9], "%s/logical", xpath_root); - vals[9].type = SR_BOOL_T; - vals[9].data.bool_val = true; //for now, we assume all are logical - - *values = vals; - *values_cnt = vc; - - return SR_ERR_OK; -} - -//TODO: for some arcane reason, this doesn't work -static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb( - const char *xpath, sr_val_t **values, size_t *values_cnt, - uint64_t request_id, const char *original_xpath, void *private_ctx) -{ - UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); - char xpath_root[XPATH_SIZE] = {0}; - sr_xpath_ctx_t state = {0}; - sr_val_t *vals = NULL; - char interface_name[VPP_INTFC_NAME_LEN] = {0}; - char subinterface_index[XPATH_SIZE] = {0}; - char address_ip[XPATH_SIZE] = {0}; - u8 prefix_len; - char *tmp = NULL; - int rc, cnt = 0; - - ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); - - SRP_LOG_INF("In %s", __FUNCTION__); - - /* Get XPATH parameters name, index and ip */ - - tmp = sr_xpath_key_value((char*)xpath, "interface", "name", &state); - if (!tmp) { - SRP_LOG_ERR_MSG("XPATH interface name not found"); - return SR_ERR_INVAL_ARG; - } - strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN); - sr_xpath_recover(&state); - - tmp = sr_xpath_key_value((char*)xpath, "subinterface", "index", &state); - if (NULL == tmp) { - SRP_LOG_ERR_MSG("XPATH subinterface index not found."); - return SR_ERR_INVAL_ARG; - } - strncpy(subinterface_index, tmp, XPATH_SIZE); - sr_xpath_recover(&state); - - tmp = sr_xpath_key_value((char*)xpath, "address", "ip", &state); - if (NULL == tmp) { - SRP_LOG_ERR_MSG("XPATH address ip not found."); - return SR_ERR_INVAL_ARG; - } - strncpy(address_ip, tmp, XPATH_SIZE); - sr_xpath_recover(&state); - - snprintf(xpath_root, XPATH_SIZE, "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address[ip='%s']/openconfig-if-ip:state", - interface_name, subinterface_index, address_ip); - - rc = ipv46_address_dump(interface_name, address_ip, &prefix_len, false); - if (!rc) { - SRP_LOG_ERR_MSG("ipv46_address_dump failed"); - return SR_ERR_INVAL_ARG; - } - - /* Build answer to state XPATH */ - - rc = sr_new_values(3, &vals); - if (SR_ERR_OK != rc) - return rc; - - sr_val_build_xpath(&vals[cnt], "%s/openconfig-if-ip:ip", xpath_root); - sr_val_set_str_data(&vals[cnt], SR_STRING_T, address_ip); - cnt++; - - sr_val_build_xpath(&vals[cnt], "%s/openconfig-if-ip:prefix-length", xpath_root); - vals[cnt].type = SR_UINT8_T; - vals[cnt].data.uint8_val = prefix_len; - cnt++; - - sr_val_build_xpath(&vals[cnt], "%s/openconfig-if-ip:origin", xpath_root); - sr_val_set_str_data(&vals[cnt], SR_ENUM_T, "STATIC"); - cnt++; - - sr_xpath_recover(&state); - *values = vals; - *values_cnt = cnt; - - return SR_ERR_OK; -} - -/* TODO move to common functions between all plugins */ -static bool -is_subinterface(const char* subif_name, const char* base_name, - const u32 subif_index) -{ - assert(subif_name && base_name); - - const char* dot = strchr(subif_name, '.'); - - if (NULL == dot && 0 == subif_index) - return true; //subif_index == 0 can pass as a "real" interface - - if (dot > subif_name && 0 == strncmp(subif_name, base_name, - dot - subif_name)) { - char * eptr = NULL; - u32 si = strtoul(dot + 1, &eptr, 10); - - if ('\0' == *eptr && subif_index == si) - return true; - } - - return false; -} - -// openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state -static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb( - const char *xpath, sr_val_t **values, size_t *values_cnt, - uint64_t request_id, const char *original_xpath, void *private_ctx) -{ - UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); - sw_interface_dump_t reply = {0}; - char xpath_root[XPATH_SIZE]; - sr_xpath_ctx_t state = {0}; - char *tmp = NULL; - char interface_name[VPP_INTFC_NAME_LEN] = {0}; - char subinterface_index[XPATH_SIZE] = {0}; - u32 sub_id; - sr_val_t *vals = NULL; - int vc = 6; - int val_idx = 0; - int rc; - - ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); - - SRP_LOG_INF("In %s", __FUNCTION__); - - tmp = sr_xpath_key_value((char*)xpath, "interface", "name", &state); - if (!tmp) { - SRP_LOG_ERR_MSG("XPATH interface name not found"); - return SR_ERR_INVAL_ARG; - } - strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN); - sr_xpath_recover(&state); - - tmp = sr_xpath_key_value((char*)xpath, "subinterface", "index", &state); - if (!tmp) { - SRP_LOG_ERR_MSG("subinterface index not found"); - return SR_ERR_INVAL_ARG; - } - strncpy(subinterface_index, tmp, XPATH_SIZE); - sr_xpath_recover(&state); - - snprintf(xpath_root, XPATH_SIZE, - "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state", - interface_name, subinterface_index); - - rc = interface_dump_iface(&reply, interface_name); - if (rc == -SCVPP_NOT_FOUND) { - SRP_LOG_ERR_MSG("interface not found"); - return SR_ERR_NOT_FOUND; - } - - /* Check that requested subinterface index matches reply subid */ - sub_id = atoi(subinterface_index); - if (sub_id != reply.sub_id) { - SRP_LOG_ERR_MSG("subinterface index not found."); - return SR_ERR_NOT_FOUND; - } - - /* Check that interface is a sub interface */ - if (!is_subinterface((char*)reply.interface_name, interface_name, sub_id)) { - SRP_LOG_ERR("%s not a subinterface", interface_name); - return SR_ERR_OPERATION_FAILED; - } - - rc = sr_new_values(vc, &vals); - if (SR_ERR_OK != rc) - return rc; - - sr_val_build_xpath(&vals[val_idx], "%s/index", xpath_root); - vals[val_idx].type = SR_UINT32_T; - vals[val_idx++].data.uint32_val = sub_id; - - sr_val_build_xpath(&vals[val_idx], "%s/description", xpath_root); - sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, NOT_AVAL); - - sr_val_build_xpath(&vals[val_idx], "%s/enabled", xpath_root); - vals[val_idx].type = SR_BOOL_T; - vals[val_idx++].data.bool_val = reply.admin_up_down; - - //TODO: Openconfig required this value - // sr_val_build_xpath(&vals[val_idx], "%s/name", xpath_root); - // sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, YANG INPUT TYPE: string); - - // sr_val_build_xpath(&vals[val_idx], "%s/ifindex", interface_name, sub_id); - // vals[val_idx].type = SR_UINT32_T; - // vals[val_idx++].data.uint32_val = YANG INPUT TYPE: uint32; - - sr_val_build_xpath(&vals[val_idx], "%s/admin-status", xpath_root); - sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T, - reply.admin_up_down ? "UP" : "DOWN"); - - sr_val_build_xpath(&vals[val_idx], "%s/oper-status", xpath_root); - sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T, reply.admin_up_down ? "UP" : "DOWN"); - - //TODO: Openconfig required this value - // sr_val_build_xpath(&vals[val_idx], "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state/last-change", interface_name, sub_id); - // sr_val_set_str_data(&vals[val_idx++], YANG INPUT TYPE: oc-types:timeticks64); - - sr_val_build_xpath(&vals[val_idx], "%s/logical", xpath_root); - vals[val_idx].type = SR_BOOL_T; - vals[val_idx++].data.bool_val = true; //for now, we assume all are logical - - sr_xpath_recover(&state); - - *values = vals; - *values_cnt = vc; - - return SR_ERR_OK; -} - -// openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/oc-ip:ipv4/oc-ip:addresses/oc-ip:address[ip='%s']/oc-ip:config/ -static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb( - sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event, - void *private_ctx) -{ - UNUSED(private_ctx); - sr_change_iter_t *it = NULL; - sr_change_oper_t oper; - sr_xpath_ctx_t state = {0}; - sr_val_t *old = NULL; - sr_val_t *new = NULL; - char *tmp = NULL; - char interface_name[VPP_INTFC_NAME_LEN] = {0}; - char subinterface_index[XPATH_SIZE] = {0}; - char address_ip[XPATH_SIZE] = {0}; - char old_address_ip[XPATH_SIZE] = {0}; - u8 prefix_len = 0; - u8 old_prefix_len = 0; - int rc = 0; - bool ip_set = false, prefix_len_set = false; - bool old_ip_set = false, old_prefix_len_set = false; - - ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); - - // if we receive event SR_EV_APPLY - config has changed - - if (event == SR_EV_APPLY) - return SR_ERR_OK; - - if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) { - sr_free_change_iter(it); - return SR_ERR_OK; - } - - foreach_change (ds, it, oper, old, new) { - - SRP_LOG_DBG("xpath: %s", new->xpath); - - tmp = sr_xpath_key_value(new->xpath, "interface", "name", &state); - if (!tmp) { - sr_set_error(ds, "XPATH interface name NOT found", new->xpath); - return SR_ERR_INVAL_ARG; - } - strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN); - sr_xpath_recover(&state); - - tmp = sr_xpath_key_value(new->xpath, "subinterface", "index", &state); - if (!tmp) { - sr_set_error(ds, "XPATH subinterface index NOT found", new->xpath); - return SR_ERR_INVAL_ARG; - } - strncpy(subinterface_index, tmp, XPATH_SIZE); - sr_xpath_recover(&state); - - switch (oper) { - case SR_OP_CREATED: - if (sr_xpath_node_name_eq(new->xpath, "ip")) { - ip_set = true; - strncpy(address_ip, new->data.string_val, XPATH_SIZE); - } else if (sr_xpath_node_name_eq(new->xpath, - "prefix-length")) { - prefix_len_set = true; - prefix_len = new->data.uint8_val; - } - - if (ip_set && prefix_len_set) //add ipv4 - rc = ipv46_config_add_remove(interface_name, address_ip, - prefix_len, false , true); - - break; - - case SR_OP_MODIFIED: - if (sr_xpath_node_name_eq(old->xpath, "ip")) { - old_ip_set = true; - strncpy(old_address_ip, old->data.string_val, - XPATH_SIZE); - } else if (sr_xpath_node_name_eq(old->xpath, - " prefix-length")) { - old_prefix_len_set = true; - old_prefix_len = old->data.uint8_val; - } - - if (sr_xpath_node_name_eq(new->xpath, "ip")) { - ip_set = true; - strncpy(address_ip, new->data.string_val, XPATH_SIZE); - } else if (sr_xpath_node_name_eq(new->xpath, - "prefix-length")) { - prefix_len_set = true; - prefix_len = new->data.uint8_val; - } - - if (old_ip_set && old_prefix_len_set) { - //remove ipv4 - rc = ipv46_config_add_remove(interface_name, old_address_ip, - old_prefix_len, false, false); - if (0 != rc) { - break; - } - } - - if (ip_set && prefix_len_set) { - //add ipv4 - rc = ipv46_config_add_remove(interface_name, address_ip, - prefix_len, false, true); - } - break; - - case SR_OP_MOVED: - break; - - case SR_OP_DELETED: - if (sr_xpath_node_name_eq(old->xpath, "ip")) { - old_ip_set = true; - strncpy(old_address_ip, old->data.string_val, - XPATH_SIZE); - } else if (sr_xpath_node_name_eq(old->xpath, - "prefix-length")) { - old_prefix_len_set = true; - old_prefix_len = old->data.uint8_val; - } - - if (old_ip_set && old_prefix_len_set) { - //remove ipv4 - rc = ipv46_config_add_remove(interface_name, old_address_ip, - old_prefix_len, false, false); - } - break; - } - - if (0 != rc) { - sr_xpath_recover(&state); - - sr_free_val(old); - sr_free_val(new); - - sr_free_change_iter(it); - - return SR_ERR_OPERATION_FAILED; - } - - sr_xpath_recover(&state); - - sr_free_val(old); - sr_free_val(new); - } - - sr_free_change_iter(it); - return SR_ERR_OK; -} - -int -openconfig_interface_init(sc_plugin_main_t *pm) -{ - int rc = SR_ERR_OK; - SRP_LOG_DBG_MSG("Initializing openconfig-interfaces plugin."); - - rc = sr_subtree_change_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/config", - openconfig_interfaces_interfaces_interface_config_cb, NULL, 98, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/state", - openconfig_interfaces_interfaces_interface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state", - openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_subtree_change_subscribe(pm->session, - "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address/openconfig-if-ip:config", - openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb, - NULL, 100, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_dp_get_items_subscribe(pm->session, - "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address/openconfig-if-ip:state", - openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb, - NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - SRP_LOG_DBG_MSG("openconfig-interfaces plugin initialized successfully."); - return SR_ERR_OK; - -error: - SRP_LOG_ERR("Error by initialization of openconfig-interfaces plugin. Error : %d", rc); - return rc; -} - -void -openconfig_interface_exit(__attribute__((unused)) sc_plugin_main_t *pm) -{ -} - -SC_INIT_FUNCTION(openconfig_interface_init); -SC_EXIT_FUNCTION(openconfig_interface_exit); diff --git a/src/plugins/openconfig/openconfig_interfaces.cpp b/src/plugins/openconfig/openconfig_interfaces.cpp new file mode 100644 index 0000000..40de71c --- /dev/null +++ b/src/plugins/openconfig/openconfig_interfaces.cpp @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2018 PANTHEON.tech. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <assert.h> +#include <string.h> + +#include <vom/interface.hpp> +#include <vom/om.hpp> + +#include <vpp-oper/interface.hpp> + +#include <sc_plugins.h> + +using VOM::interface; +using VOM::OM; +using VOM::HW; +using VOM::rc_t; + +using type_t = VOM::interface::type_t; +using admin_state_t = VOM::interface::admin_state_t; + +class interface_builder { + public: + interface_builder() {} + + shared_ptr<VOM::interface> build() { + if (m_name.empty() || m_type.empty()) + return nullptr; + return make_shared<interface>(m_name, type_t::from_string(m_type), + admin_state_t::from_int(m_state)); + } + + /* Getters */ + string name() { + return m_name; + } + + /* Setters */ + interface_builder& set_name(string n) { + m_name = n; + return *this; + } + + interface_builder& set_type(string t) { + if (t == "iana-if-type:ethernetCsmacd") + m_type = "ETHERNET"; + return *this; + } + + interface_builder& set_state(bool enable) { + m_state = enable; + return *this; + } + + std::string to_string() { + std::ostringstream os; + os << m_name << "," << m_type << "," << m_state; + return os.str(); + } + + private: + string m_name; + string m_type; + bool m_state; +}; + + +// XPATH: /openconfig-interfaces:interfaces/interface[name='%s']/config/ +static int +oc_interfaces_config_cb(sr_session_ctx_t *ds, const char *xpath, + sr_notif_event_t event, void *private_ctx) +{ + UNUSED(private_ctx); + interface_builder builder; + shared_ptr<VOM::interface> intf; + string intf_name; + sr_change_iter_t *it = nullptr; + sr_xpath_ctx_t state; + sr_val_t *ol = nullptr; + sr_val_t *ne = nullptr; + sr_change_oper_t oper; + bool create, remove, modify; + int rc; + + SRP_LOG_INF("In %s", __FUNCTION__); + + ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); + + if (event != SR_EV_VERIFY) + return SR_ERR_OK; + + if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) { + sr_free_change_iter(it); + return SR_ERR_OK; + } + + foreach_change (ds, it, oper, ol, ne) { + + intf_name = sr_xpath_key_value(ne->xpath, "interface", "name", &state); + if (intf_name.empty()) { + sr_set_error(ds, "XPATH interface name NOT found", ne->xpath); + return SR_ERR_INVAL_ARG; + } + sr_xpath_recover(&state); + + switch (oper) { + case SR_OP_CREATED: + if (sr_xpath_node_name_eq(ne->xpath, "name")) { + builder.set_name(ne->data.string_val); + create = true; + } else if(sr_xpath_node_name_eq(ne->xpath, "type")) { + builder.set_type(ne->data.string_val); + } else if(sr_xpath_node_name_eq(ne->xpath, "enabled")) { + builder.set_state(ne->data.bool_val); + } + break; + + case SR_OP_MODIFIED: + if (sr_xpath_node_name_eq(ne->xpath, "enabled")) { + string n = sr_xpath_key_value(ne->xpath, "interface", + "name", &state); + intf = interface::find(n); + if (!intf) { + rc = SR_ERR_OPERATION_FAILED; + goto nothing_todo; + } + intf->set(admin_state_t::from_int(ne->data.bool_val)); + modify = true; + } + break; + + case SR_OP_DELETED: + if (sr_xpath_node_name_eq(ol->xpath, "name")) { + builder.set_name(ol->data.string_val); + remove = true; + } + break; + + default: + rc = SR_ERR_UNSUPPORTED; + goto nothing_todo; + } + + sr_xpath_recover(&state); + + sr_free_val(ol); + sr_free_val(ne); + } + + if (create) { + SRP_LOG_INF("creating interface '%s'", builder.name().c_str()); + intf = builder.build(); + if (nullptr == intf) { + SRP_LOG_ERR_MSG("Interface does not exist"); + rc = SR_ERR_INVAL_ARG; + goto nothing_todo; + } + } + + if (create || modify) { + if ( OM::write(intf->key(), *intf) != rc_t::OK ) { + SRP_LOG_ERR("Fail writing changes to VPP for: %s", + builder.to_string().c_str()); + rc = SR_ERR_OPERATION_FAILED; + goto nothing_todo; + } + } else if (remove) { + SRP_LOG_INF("deleting interface '%s'", builder.name().c_str()); + OM::remove(builder.name()); + } + + sr_free_change_iter(it); + return SR_ERR_OK; + +nothing_todo: + sr_free_val(ol); + sr_free_val(ne); + sr_free_change_iter(it); + return rc; +} + +//XPATH : /openconfig-interfaces:interfaces/interface/state +static int +oc_interfaces_state_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, + uint64_t request_id, const char *original_xpath, + void *private_ctx) +{ + UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); + vapi_payload_sw_interface_details reply; + shared_ptr<interface_dump> dump; + string intf_name; + sr_val_t *vals = nullptr; + sr_xpath_ctx_t state; + char xpath_root[XPATH_SIZE]; + int vc = 7; + int cnt = 0; + int rc; + + SRP_LOG_INF("In %s", __FUNCTION__); + + ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); + + intf_name = sr_xpath_key_value((char*) xpath, "interface", "name", &state); + if (intf_name.empty()) { + SRP_LOG_ERR_MSG("XPATH interface name not found"); + return SR_ERR_INVAL_ARG; + } + sr_xpath_recover(&state); + + snprintf(xpath_root, XPATH_SIZE, + "/openconfig-interfaces:interfaces/interface[name='%s']/state", + intf_name.c_str()); + + rc = sr_new_values(vc, &vals); + if (SR_ERR_OK != rc) + return rc; + + dump = make_shared<interface_dump>(intf_name); //dump only specific intf + HW::enqueue(dump); + HW::write(); + + reply = dump->begin()->get_payload(); + + sr_val_build_xpath(&vals[cnt], "%s/name", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_STRING_T, (char *)reply.interface_name); + cnt++; + + //TODO revisit types after V3PO has been implemented + sr_val_build_xpath(&vals[cnt], "%s/type", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_IDENTITYREF_T, "ianaift:ethernetCsmacd"); + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/mtu", xpath_root); + vals[cnt].type = SR_UINT16_T; + vals[cnt].data.uint16_val = reply.link_mtu; + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/enabled", xpath_root); + vals[cnt].type = SR_BOOL_T; + vals[cnt].data.bool_val = reply.admin_up_down; + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/ifindex", xpath_root); + vals[cnt].type = SR_UINT32_T; + vals[cnt].data.uint32_val = reply.sw_if_index; + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/admin-status", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_ENUM_T, + reply.admin_up_down ? "UP" : "DOWN"); + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/oper-status", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_ENUM_T, + reply.link_up_down ? "UP" : "DOWN"); + cnt++; + + *values = vals; + *values_cnt = cnt; + + return SR_ERR_OK; +} + +int +openconfig_interface_init(sc_plugin_main_t *pm) +{ + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Initializing openconfig-interfaces plugin."); + + rc = sr_subtree_change_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/config", + oc_interfaces_config_cb, nullptr, 98, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/state", + oc_interfaces_state_cb, nullptr, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + SRP_LOG_DBG_MSG("openconfig-interfaces plugin initialized successfully."); + return SR_ERR_OK; + +error: + SRP_LOG_ERR("Error by initialization of openconfig-interfaces plugin. Error : %d", rc); + return rc; +} + +void +openconfig_interface_exit(__attribute__((unused)) sc_plugin_main_t *pm) +{ +} + +SC_INIT_FUNCTION(openconfig_interface_init); +SC_EXIT_FUNCTION(openconfig_interface_exit); diff --git a/src/plugins/openconfig/openconfig_local_routing.c b/src/plugins/openconfig/openconfig_local_routing.c deleted file mode 100644 index 2d16da0..0000000 --- a/src/plugins/openconfig/openconfig_local_routing.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * Copyright (c) 2018 PANTHEON.tech. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <string.h> - -#include <scvpp/comm.h> -#include <scvpp/interface.h> -#include <scvpp/ip.h> - -#include <sc_plugins.h> - -#define HOP_INDEX_SIZE 10 //number of digit in max 32 bit integer - -static inline int -_set_route (const char *prefix, const char *nhop, bool is_add, - const char *iface) -{ - int table = 0; //FIB table ID - int mask; - int rc; - - // Put prefix length in mask and prefix IP in prefix - mask = ip_prefix_split(prefix); - if (mask < 1) { - SRP_LOG_ERR("Prefix length can not be %d", mask); - return SR_ERR_INVAL_ARG; - } - - rc = ipv46_config_add_del_route(prefix, mask, nhop, is_add, table, iface); - if (rc != SCVPP_OK) { - SRP_LOG_ERR("Add/delete route failed for %s %s", prefix, iface); - return SR_ERR_INVAL_ARG; - } - - SRP_LOG_INF("Add/delete route Success for %s %s", prefix, iface); - - return SR_ERR_OK; -} - -#define STR(string) #string - -#define ROOT "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/%s" - -static inline char * _get_ds_elem(sr_session_ctx_t *sess, const char *prefix, - const char *index, const char *sub) -{ - char xpath[XPATH_SIZE] = {0}; - sr_val_t *value = NULL; - int rc; - - snprintf(xpath, XPATH_SIZE, ROOT, prefix, index, sub); - - rc = sr_get_item(sess, xpath, &value); - if (SR_ERR_OK != rc) { - SRP_LOG_DBG("XPATH %s not set", xpath); - return NULL; - } - - return value->data.string_val; -} - -/* @brief add/del route to FIB table 0. - * If you add/delete an entry to FIB, prefix is mandatory and next hop can be: - * - interface only - * - next hop IP - * - both interface and next hop IP - */ -static int set_route(sr_session_ctx_t *sess, const char *index, - const char *interface /* NULLABLE*/, - const char *next_hop /* NULLABLE*/, - const char *prefix, bool is_add) -{ - const char *iface = NULL; - const char *nhop = NULL; - - ARG_CHECK3(SR_ERR_INVAL_ARG, sess, index, prefix); - - if (!interface && !next_hop) - return SR_ERR_INVAL_ARG; - - if (!interface) //fetch interface in datastore, can return NULL - iface = _get_ds_elem(sess, prefix, index, "interface-ref/config/interface"); - else //use interface provided - iface = interface; - - if (!next_hop) //fetch next-hop in datastore , can return NULL - nhop = _get_ds_elem(sess, prefix, index, "config/next-hop"); - else //use next hop IP provided - nhop = next_hop; - - return _set_route(prefix, nhop, is_add, iface); -} - -/* @brief Callback used to add prefix entry for XPATH: - * /openconfig-local-routing:local-routes/static-routes/static/config - */ -static int -oc_prefix_config_cb(sr_session_ctx_t *ds, const char *xpath, - sr_notif_event_t event, void *private_ctx) -{ - UNUSED(ds); UNUSED(xpath); UNUSED(event); UNUSED(private_ctx); - - SRP_LOG_INF("In %s", __FUNCTION__); - - return SR_ERR_OK; -} - -// XPATH: /openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/config/ -static int oc_next_hop_config_cb(sr_session_ctx_t *ds, const char *xpath, - sr_notif_event_t event, void *private_ctx) -{ - char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0}; - char next_hop[VPP_IP4_ADDRESS_STRING_LEN] = {0}; //IP of next router - char index[HOP_INDEX_SIZE]; //next hop index - bool index_set = false, next_hop_set = false; - sr_change_iter_t *it; - sr_change_oper_t oper; - sr_val_t *old, *new, *tmp; - sr_xpath_ctx_t state = {0}; - int rc = SR_ERR_OK; - UNUSED(private_ctx); - - ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); - - SRP_LOG_INF("In %s", __FUNCTION__); - - if (event == SR_EV_APPLY) //SR_EV_VERIFY already applied the changes - return SR_ERR_OK; - - rc = sr_get_changes_iter(ds, (char *)xpath, &it); - if (rc != SR_ERR_OK) { - sr_free_change_iter(it); - return rc; - } - - foreach_change(ds, it, oper, old, new) { - - rc = get_xpath_key(prefix, new->xpath, "static", "prefix", - VPP_IP4_PREFIX_STRING_LEN, &state); - if (rc != 0) - goto error; - - switch (oper) { - case SR_OP_MODIFIED: - case SR_OP_CREATED: - tmp = new; - break; - case SR_OP_DELETED: - tmp = old; - break; - default: - SRP_LOG_WRN_MSG("Operation not supported"); - break; - } - - if (sr_xpath_node_name_eq(tmp->xpath, "config")) { - SRP_LOG_DBG("xpath: %s", tmp->xpath); - } else if (sr_xpath_node_name_eq(tmp->xpath, "index")) { - strncpy(index, tmp->data.string_val, HOP_INDEX_SIZE); - index_set = true; - } else if(sr_xpath_node_name_eq(tmp->xpath, "next-hop")) { - strncpy(next_hop, tmp->data.string_val, VPP_IP4_ADDRESS_STRING_LEN); - next_hop_set = true; - } else if(sr_xpath_node_name_eq(tmp->xpath, "recurse")) { - //SYSREPO BUG: Just catch it, sysrepo thinks it is mandatory... - } else { //metric, recurse - SRP_LOG_ERR("Unsupported field %s", tmp->xpath); - return SR_ERR_UNSUPPORTED; - } - - if (index_set && next_hop_set) { - if (oper == SR_OP_CREATED) { - rc = set_route(ds, index, NULL, next_hop, prefix, true); - } else if (oper == SR_OP_MODIFIED) { - rc = set_route(ds, index, NULL, next_hop, prefix, false); - rc |= set_route(ds, index, NULL, next_hop, prefix, true); - } else if (oper == SR_OP_DELETED) { - rc = set_route(ds, index, NULL, next_hop, prefix, false); - } - - if (rc != 0) { - SRP_LOG_ERR_MSG("setting route failed"); - goto error; - } - index_set = false; next_hop_set = false; - } - - sr_free_val(old); - sr_free_val(new); - sr_xpath_recover(&state); - } - - sr_free_change_iter(it); - return rc; - -error: - sr_free_val(old); - sr_free_val(new); - sr_xpath_recover(&state); - sr_free_change_iter(it); - return rc; -} - -// XPATH: /openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/interface-ref/config/ -static int -oc_next_hop_interface_config_cb(sr_session_ctx_t *ds, const char *xpath, - sr_notif_event_t event, void *private_ctx) -{ - char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0}; - char interface[VPP_INTFC_NAME_LEN] = {0}; - char index[HOP_INDEX_SIZE] = {0}; - sr_change_iter_t *it = NULL; - sr_change_oper_t oper; - sr_val_t *old, *new, *tmp; - sr_xpath_ctx_t state = {0}; - bool interface_set = false; - int rc = SR_ERR_OK; - UNUSED(private_ctx); - - SRP_LOG_INF("In %s", __FUNCTION__); - - if (event == SR_EV_APPLY) - return SR_ERR_OK; - - rc = sr_get_changes_iter(ds, (char *)xpath, &it); - if (rc != SR_ERR_OK) { - sr_free_change_iter(it); - return rc; - } - - foreach_change(ds, it, oper, old, new) { - - SRP_LOG_DBG("xpath: %s", new->xpath); - - rc = get_xpath_key(prefix, new->xpath, "static", "prefix", - VPP_IP4_PREFIX_STRING_LEN, &state); - - rc |= get_xpath_key(index, new->xpath, "next-hop", "index", - HOP_INDEX_SIZE, &state); - if (rc) - goto error; - - switch (oper) { - case SR_OP_MODIFIED: - case SR_OP_CREATED: - tmp = new; - break; - case SR_OP_DELETED: - tmp = old; - break; - default: - SRP_LOG_WRN_MSG("Operation not supported"); - break; - } - - if (sr_xpath_node_name_eq(tmp->xpath, "config")) { - SRP_LOG_DBG("xpath: %s", tmp->xpath); - } else if (sr_xpath_node_name_eq(tmp->xpath, "interface")) { - strncpy(interface, tmp->data.string_val, VPP_INTFC_NAME_LEN); - interface_set = true; - } else { //metric, recurse - SRP_LOG_ERR("Unsupported field %s", tmp->xpath); - return SR_ERR_UNSUPPORTED; - } - - if (oper == SR_OP_CREATED && interface_set) { - rc = set_route(ds, index, interface, NULL, prefix, true); - interface_set = false; - } else if (oper == SR_OP_MODIFIED && interface_set) { - rc = set_route(ds, index, interface, NULL, prefix, false); - rc |= set_route(ds, index, interface, NULL, prefix, true); - interface_set = false; - } else if (oper == SR_OP_DELETED && interface_set) { - rc = set_route(ds, index, interface, NULL, prefix, false); - interface_set = false; - } - - if (rc != 0) { - SRP_LOG_ERR_MSG("setting route failed"); - goto error; - } - - sr_free_val(old); - sr_free_val(new); - sr_xpath_recover(&state); - } - - sr_free_change_iter(it); - return SR_ERR_OK; - -error: - sr_free_val(old); - sr_free_val(new); - sr_xpath_recover(&state); - sr_free_change_iter(it); - return rc; -} - -// XPATH: /openconfig-local-routing:local-routes/static-routes/static/state -static int oc_prefix_state_cb( - const char *xpath, sr_val_t **values, size_t *values_cnt, - uint64_t request_id, const char *original_xpath, void *private_ctx) -{ - UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); - char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0}; - sr_xpath_ctx_t state = {0}; - sr_val_t *vals = NULL; - fib_dump_t *reply = NULL; - int vc = 1; - int rc = 0; - - ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); - - SRP_LOG_INF("In %s", __FUNCTION__); - - rc = get_xpath_key(prefix, (char *)xpath, "static", "prefix", - VPP_IP4_PREFIX_STRING_LEN, &state); - if (rc != 0) - return SR_ERR_INVAL_ARG; - - rc = ipv4_fib_dump_prefix(prefix, &reply); - if (rc == -SCVPP_NOT_FOUND) { - SRP_LOG_ERR("Prefix %s not found in VPP FIB", prefix); - return SR_ERR_NOT_FOUND; - } - - /* Allocation for number of elements dumped by ipv4_fib_dump_all */ - rc = sr_new_values(vc, &vals); - if (SR_ERR_OK != rc) - return rc; - - sr_val_build_xpath(&vals[0], "%s/prefix", xpath); - sr_val_set_str_data(&vals[0], SR_STRING_T, prefix); - - sr_xpath_recover(&state); - - free(reply); - *values = vals; - *values_cnt = vc; - - return SR_ERR_OK; -} - -// XPATH /openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state -static int -oc_next_hop_state_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, - uint64_t request_id, const char *original_xpath, - void *private_ctx) -{ - UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); - char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0}; - char index[HOP_INDEX_SIZE]; - char next_hop[INET_ADDRSTRLEN] = {0}; - fib_dump_t *reply = NULL; - sr_xpath_ctx_t state = {0}; - sr_val_t *vals = NULL; - int vc = 3; - int rc = 0; - - ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); - - SRP_LOG_INF("In %s", __FUNCTION__); - - /* Get prefix and index key from XPATH */ - rc = get_xpath_key(prefix, (char *)xpath, "static", "prefix", - VPP_IP4_PREFIX_STRING_LEN, &state); - - rc |= get_xpath_key(index, (char*)xpath, "next-hop", "index", - HOP_INDEX_SIZE, &state); - - if (rc != 0) - return SR_ERR_INVAL_ARG; - - rc = ipv4_fib_dump_prefix(prefix, &reply); - if (rc != SCVPP_OK) { - SRP_LOG_ERR("Fail to dump prefix %s", prefix); - return SR_ERR_INVAL_ARG; - } - - rc = sr_new_values(vc, &vals); - if (SR_ERR_OK != rc) - return rc; - - // check next hop index equals next hop id - if (strtoul(index, NULL, 0) != reply->path[0].next_hop_id) { - SRP_LOG_ERR("next hop index is %d for prefix %s", - reply->path[0].next_hop_id, prefix); - SRP_LOG_ERR("before %s, stroul is %lu", index, strtoul(index, NULL, 0)); - return SR_ERR_INVAL_ARG; - } - - sr_val_build_xpath(&vals[0], "%s/index", xpath); - sr_val_set_str_data(&vals[0], SR_STRING_T, index); - - strncpy(next_hop, sc_ntoa(reply->path[0].next_hop), VPP_IP4_ADDRESS_LEN); - sr_val_build_xpath(&vals[1], "%s/next-hop", xpath); - sr_val_set_str_data(&vals[1], SR_STRING_T, (char *)reply->path[0].next_hop); - - sr_val_build_xpath(&vals[2], "%s/metric", xpath); - vals[2].type = SR_UINT32_T; - vals[2].data.uint32_val = reply->path[0].weight; - - free(reply); - sr_xpath_recover(&state); - *values = vals; - *values_cnt = vc; - - return SR_ERR_OK; -} - -// XPATH /openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state -static int -oc_next_hop_interface_state_cb(const char *xpath, sr_val_t **values, - size_t *values_cnt, uint64_t request_id, - const char *original_xpath, void *private_ctx) -{ - UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); - sr_xpath_ctx_t state = {0}; - char prefix[VPP_IP4_PREFIX_STRING_LEN] = {0}; - char interface[VPP_INTFC_NAME_LEN] = {0}; - char index[HOP_INDEX_SIZE]; //next hop index - fib_dump_t *reply = NULL; - sr_val_t *vals = NULL; - int vc = 1; - int rc = 0; - - //ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); - - SRP_LOG_INF("In %s", __FUNCTION__); - - ///* Get prefix key from XPATH */ - rc = get_xpath_key(prefix, (char*) xpath, "static", "prefix", - VPP_IP4_PREFIX_STRING_LEN, &state); - - rc |= get_xpath_key(index, (char *)xpath, "next-hop", "index", - HOP_INDEX_SIZE, &state); - - if (rc != 0) - return SR_ERR_INVAL_ARG; - - rc = ipv4_fib_dump_prefix(prefix, &reply); - if (rc != SCVPP_OK) { - SRP_LOG_ERR("Fail to dump prefix %s", prefix); - return SR_ERR_INVAL_ARG; - } - //TODO: check nhop? - - rc = sr_new_values(vc, &vals); - if (SR_ERR_OK != rc) - return rc; - - // check next hop index equals next hop id - if (strtoul(index, NULL, 0) != reply->path[0].next_hop_id) { - SRP_LOG_ERR("next hop index is %d for prefix %s", - reply->path[0].next_hop_id, prefix); - SRP_LOG_ERR("before %s, stroul is %lu", index, strtoul(index, NULL, 0)); - return SR_ERR_INVAL_ARG; - } - - rc = get_interface_name(interface, reply->path[0].sw_if_index); - if (rc != SCVPP_OK) { - SRP_LOG_ERR("No interface name for id %d", reply->path[0].sw_if_index); - return SR_ERR_INVAL_ARG; - } - - sr_val_build_xpath(&vals[0], "%s/interface", xpath); - sr_val_set_str_data(&vals[0], SR_STRING_T, interface); - - free(reply); - sr_xpath_recover(&state); - *values = vals; - *values_cnt = vc; - - return SR_ERR_OK; -} - -int -openconfig_local_routing_init(sc_plugin_main_t *pm) -{ - int rc = SR_ERR_OK; - SRP_LOG_DBG_MSG("Initializing openconfig-local-routing plugin."); - - rc = sr_subtree_change_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/config", - oc_prefix_config_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_subtree_change_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/config", - oc_next_hop_config_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_subtree_change_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/config", - oc_next_hop_interface_config_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/state", - oc_prefix_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state", - oc_next_hop_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state", - oc_next_hop_interface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); - if (SR_ERR_OK != rc) { - goto error; - } - - SRP_LOG_DBG_MSG("openconfig-local-routing plugin initialized successfully."); - return SR_ERR_OK; - -error: - SRP_LOG_ERR("Error by initialization of openconfig-local-routing plugin. Error : %d", rc); - return rc; -} - -void -openconfig_local_routing_exit(__attribute__((unused)) sc_plugin_main_t *pm) -{ -} - -SC_INIT_FUNCTION(openconfig_local_routing_init); -SC_EXIT_FUNCTION(openconfig_local_routing_exit); - |