aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/openconfig
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/openconfig')
-rw-r--r--src/plugins/openconfig/openconfig_interfaces.c646
-rw-r--r--src/plugins/openconfig/openconfig_interfaces.cpp309
-rw-r--r--src/plugins/openconfig/openconfig_local_routing.c548
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);
-