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.c759
-rw-r--r--src/plugins/openconfig/openconfig_interfaces.h26
-rw-r--r--src/plugins/openconfig/openconfig_local_routing.c888
-rw-r--r--src/plugins/openconfig/openconfig_local_routing.h25
4 files changed, 595 insertions, 1103 deletions
diff --git a/src/plugins/openconfig/openconfig_interfaces.c b/src/plugins/openconfig/openconfig_interfaces.c
index c72ad7f..7242c2b 100644
--- a/src/plugins/openconfig/openconfig_interfaces.c
+++ b/src/plugins/openconfig/openconfig_interfaces.c
@@ -17,119 +17,72 @@
#include <assert.h>
#include <string.h>
-#include "openconfig_interfaces.h"
-#include "../sys_util.h"
-
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+#include <scvpp/ip.h>
-#define XPATH_SIZE 2000
+#include "../sc_model.h"
+#include "../sys_util.h"
// XPATH: /openconfig-interfaces:interfaces/interface[name='%s']/config/
-int openconfig_interfaces_interfaces_interface_config_cb(
+static int openconfig_interfaces_interfaces_interface_config_cb(
sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+ void *private_ctx)
{
+ UNUSED(private_ctx);
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
+ 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_MSG("In openconfig_interfaces_interfaces_interface_config_cb");
+ SRP_LOG_INF("In %s", __FUNCTION__);
+ SRP_LOG_INF("XPATH %s", xpath);
ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
- // if we receive event SR_EV_APPLY - config has changed
-
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
-
- // apply configuration
- //
- //
- // in this type i guess we can call sr_get_item()
- // because we are subscribed to leaf we shouldn't
- // get more than one change in one callback
- // each chage represent change in a hierarchy of
- // xml document
- //
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY)
return SR_ERR_OK;
- }
-
- // first we get event VERIFY
- // then we get event APPLY
- // - we can return error from VERIFY event
- // - we can't return error from APPLY event
if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
sr_free_change_iter(it);
return SR_ERR_OK;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
+ foreach_change (ds, it, oper, old, new) {
- log_recv_oper(oper, "subtree_change_cb received");
+ SRP_LOG_DBG("xpath: %s", new->xpath);
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
-
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("interface_name NOT found.");
- continue;
+ 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:
- if (sr_xpath_node_name_eq(new_val->xpath, "name")) {
- //TODO: LEAF: name, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "type")) {
- //TODO: LEAF: type, type: identityref
- } else if(sr_xpath_node_name_eq(new_val->xpath, "mtu")) {
- //TODO: LEAF: mtu, type: uint16
- } else if(sr_xpath_node_name_eq(new_val->xpath,
- "loopback-mode")) {
- //TODO: LEAF: loopback-mode, type: boolean
- } else if(sr_xpath_node_name_eq(new_val->xpath,
- "description")) {
- //TODO: LEAF: description, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "enabled")) {
- rc = interface_enable(interface_name,
- new_val->data.bool_val);
- } else if(sr_xpath_node_name_eq(new_val->xpath,
- "oc-vlan:tpid")) {
- //TODO: LEAF: oc-vlan:tpid, type: identityref
- }
- break;
-
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(new_val->xpath, "name")) {
+ if (sr_xpath_node_name_eq(new->xpath, "name")) {
//TODO: LEAF: name, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "type")) {
+ } else if(sr_xpath_node_name_eq(new->xpath, "type")) {
//TODO: LEAF: type, type: identityref
- } else if(sr_xpath_node_name_eq(new_val->xpath, "mtu")) {
+ } else if(sr_xpath_node_name_eq(new->xpath, "mtu")) {
//TODO: LEAF: mtu, type: uint16
- } else if(sr_xpath_node_name_eq(new_val->xpath,
+ } 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_val->xpath,
+ } else if(sr_xpath_node_name_eq(new->xpath,
"description")) {
//TODO: LEAF: description, type: string
- } else if(sr_xpath_node_name_eq(new_val->xpath, "enabled")) {
+ } else if(sr_xpath_node_name_eq(new->xpath, "enabled")) {
rc = interface_enable(interface_name,
- new_val->data.bool_val);
- } else if(sr_xpath_node_name_eq(new_val->xpath,
+ new->data.bool_val);
+ } else if(sr_xpath_node_name_eq(new->xpath,
"oc-vlan:tpid")) {
//TODO: LEAF: oc-vlan:tpid, type: identityref
}
@@ -139,21 +92,21 @@ int openconfig_interfaces_interfaces_interface_config_cb(
break;
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "name")) {
+ if (sr_xpath_node_name_eq(old->xpath, "name")) {
//TODO: LEAF: name, type: string
- } else if(sr_xpath_node_name_eq(old_val->xpath, "type")) {
+ } else if(sr_xpath_node_name_eq(old->xpath, "type")) {
//TODO: LEAF: type, type: identityref
- } else if(sr_xpath_node_name_eq(old_val->xpath, "mtu")) {
+ } else if(sr_xpath_node_name_eq(old->xpath, "mtu")) {
//TODO: LEAF: mtu, type: uint16
- } else if(sr_xpath_node_name_eq(old_val->xpath,
+ } 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_val->xpath,
+ } else if(sr_xpath_node_name_eq(old->xpath,
"description")) {
//TODO: LEAF: description, type: string
- } else if(sr_xpath_node_name_eq(old_val->xpath, "enabled")) {
+ } else if(sr_xpath_node_name_eq(old->xpath, "enabled")) {
rc = interface_enable(interface_name, false);
- } else if(sr_xpath_node_name_eq(old_val->xpath,
+ } else if(sr_xpath_node_name_eq(old->xpath,
"oc-vlan:tpid")) {
//TODO: LEAF: oc-vlan:tpid, type: identityref
}
@@ -163,8 +116,8 @@ int openconfig_interfaces_interfaces_interface_config_cb(
if (0 != rc) {
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
sr_free_change_iter(it);
@@ -173,175 +126,190 @@ int openconfig_interfaces_interfaces_interface_config_cb(
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
}
sr_free_change_iter(it);
return SR_ERR_OK;
}
-// openconfig-interfaces
-int openconfig_interface_mod_cb(
- __attribute__((unused)) sr_session_ctx_t *session,
- __attribute__((unused)) const char *module_name,
- __attribute__((unused)) sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
-{
- SRP_LOG_INF_MSG("In openconfig_interface_mod_cb");
-
- return SR_ERR_OK;
-}
-
-typedef struct
+//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)
{
- bool is_subif;
- u32 subinterface_index;
- sw_interface_details_query_t sw_interface_details_query;
- sysr_values_ctx_t sysr_values_ctx;
-} sys_sw_interface_dump_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;
-#define NOT_AVAL "NA"
+ SRP_LOG_INF("In %s", __FUNCTION__);
+ ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
-static int sw_interface_dump_cb_inner(
- vapi_payload_sw_interface_details * reply,
- sys_sw_interface_dump_ctx * dctx)
-{
- sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0;
+ 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);
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, dctx);
+ snprintf(xpath_root, XPATH_SIZE,
+ "/openconfig-interfaces:interfaces/interface[name='%s']/state",
+ interface_name);
- vc = 10;
+ //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;
+ }
- /* convenient functions such as this can be found in sysrepo/values.h */
rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
+ if (SR_ERR_OK != rc)
return rc;
- }
-
- const char* interface_name = (const char*)dctx->sw_interface_details_query.sw_interface_details.interface_name;
- sr_val_build_xpath(&vals[0], "%s/name", dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T, interface_name);
+ 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", dctx->sysr_values_ctx.xpath_root);
+ 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", dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[2], "%s/mtu", xpath_root);
vals[2].type = SR_UINT16_T;
- vals[2].data.uint16_val = reply->link_mtu;
+ vals[2].data.uint16_val = reply.link_mtu;
- sr_val_build_xpath(&vals[3], "%s/loopback-mode",
- dctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[3], "%s/loopback-mode", xpath_root);
vals[3].type = SR_BOOL_T;
- vals[3].data.bool_val = (0 == strncmp(interface_name, "loop", 4)) ? 1 : 0;
+ 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",
- dctx->sysr_values_ctx.xpath_root);
+ 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",
- dctx->sysr_values_ctx.xpath_root);
+ 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;
+ vals[5].data.bool_val = reply.admin_up_down;
- sr_val_build_xpath(&vals[6], "%s/ifindex",
- dctx->sysr_values_ctx.xpath_root);
+ 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;
+ vals[6].data.uint32_val = reply.sw_if_index;
- sr_val_build_xpath(&vals[7], "%s/admin-status",
- dctx->sysr_values_ctx.xpath_root);
+ 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");
+ reply.admin_up_down ? "UP" : "DOWN");
- sr_val_build_xpath(&vals[8], "%s/oper-status",
- dctx->sysr_values_ctx.xpath_root);
+ 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");
+ reply.link_up_down ? "UP" : "DOWN");
//TODO: Openconfig required this value
- // sr_val_build_xpath(&vals[9], "%s/last-change", dctx->sysr_values_ctx.xpath_root);
+ // 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",
- dctx->sysr_values_ctx.xpath_root);
+ 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
+ vals[9].data.bool_val = true; //for now, we assume all are logical
- dctx->sysr_values_ctx.values = vals;
- dctx->sysr_values_ctx.values_cnt = vc;
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
-static int sw_subinterface_dump_cb_inner(
- vapi_payload_sw_interface_details *reply,
- sys_sw_interface_dump_ctx *dctx)
+//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;
- int rc = 0;
- int vc = 0, val_idx = 0;
+ 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_CHECK2(SR_ERR_INVAL_ARG, reply, dctx);
+ ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- vc = 6;
- /* convenient functions such as this can be found in sysrepo/values.h */
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
+ 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);
- sr_val_build_xpath(&vals[val_idx], "%s/index",
- dctx->sysr_values_ctx.xpath_root);
- vals[val_idx].type = SR_UINT32_T;
- vals[val_idx++].data.uint32_val = dctx->subinterface_index;
+ 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);
- sr_val_build_xpath(&vals[val_idx], "%s/description",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, NOT_AVAL);
+ 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);
- sr_val_build_xpath(&vals[val_idx], "%s/enabled",
- dctx->sysr_values_ctx.xpath_root);
- vals[val_idx].type = SR_BOOL_T;
- vals[val_idx++].data.bool_val = reply->admin_up_down;
+ 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);
- //TODO: Openconfig required this value
- // sr_val_build_xpath(&vals[val_idx], "%s/name", dctx->sysr_values_ctx.xpath_root);
- // sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, YANG INPUT TYPE: string);
+ 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;
+ }
- // sr_val_build_xpath(&vals[val_idx], "%s/ifindex", interface_name, subinterface_index);
- // vals[val_idx].type = SR_UINT32_T;
- // vals[val_idx++].data.uint32_val = YANG INPUT TYPE: uint32;
+ /* Build answer to state XPATH */
- sr_val_build_xpath(&vals[val_idx], "%s/admin-status",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T,
- reply->admin_up_down ? "UP" : "DOWN");
+ rc = sr_new_values(3, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- sr_val_build_xpath(&vals[val_idx], "%s/oper-status",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[val_idx++], SR_ENUM_T,
- reply->admin_up_down ? "UP" : "DOWN");
+ 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++;
- //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, subinterface_index);
- // sr_val_set_str_data(&vals[val_idx++], YANG INPUT TYPE: oc-types:timeticks64);
+ 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[val_idx], "%s/logical",
- dctx->sysr_values_ctx.xpath_root);
- vals[val_idx].type = SR_BOOL_T;
- vals[val_idx++].data.bool_val = true; //for now, we assume all are logical
+ 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++;
- dctx->sysr_values_ctx.values = vals;
- dctx->sysr_values_ctx.values_cnt = vc;
+ 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)
@@ -351,11 +319,10 @@ is_subinterface(const char* subif_name, const char* 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
+ return true; //subif_index == 0 can pass as a "real" interface
if (dot > subif_name && 0 == strncmp(subif_name, base_name,
- dot - subif_name))
- {
+ dot - subif_name)) {
char * eptr = NULL;
u32 si = strtoul(dot + 1, &eptr, 10);
@@ -366,289 +333,126 @@ is_subinterface(const char* subif_name, const char* base_name,
return false;
}
-static vapi_error_e
-sw_interface_dump_vapi_cb(struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_sw_interface_details * reply)
-{
- ARG_CHECK(VAPI_EINVAL, callback_ctx);
-
- if (is_last)
- {
- assert (NULL == reply);
- }
- else
- {
- assert (NULL != reply);
- sys_sw_interface_dump_ctx *dctx = callback_ctx;
-
- const char* const dctx_interface_name = (const char *)dctx->sw_interface_details_query.sw_interface_details.interface_name;
-
- SRP_LOG_DBG("interface_name: '%s', if_name: '%s'", reply->interface_name, dctx_interface_name);
-
- if (dctx->is_subif)
- {
- if (is_subinterface((const char*)reply->interface_name,
- dctx_interface_name, dctx->subinterface_index))
- sw_subinterface_dump_cb_inner(reply, dctx);
- }
- else
- {
- if (0 == strcmp(dctx_interface_name, (char *)reply->interface_name))
- {
- dctx->sw_interface_details_query.sw_interface_details = *reply;
- dctx->sw_interface_details_query.interface_found = true;
-
- sw_interface_dump_cb_inner(reply, dctx);
- }
- }
- }
-
- return VAPI_OK;
-}
-
-static vapi_error_e sysr_sw_interface_dump(sys_sw_interface_dump_ctx * dctx)
-{
- vapi_msg_sw_interface_dump *dump;
- vapi_error_e rv;
-
- ARG_CHECK(VAPI_EINVAL, dctx);
-
- dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance);
-
- dump->payload.name_filter_valid = true;
- strcpy((char*)dump->payload.name_filter, (const char *)dctx->sw_interface_details_query.sw_interface_details.interface_name);
-
- VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, dump, sw_interface_dump_vapi_cb,
- dctx));
-
- if (VAPI_OK != rv) {
- SRP_LOG_DBG("vapi_sw_interface_dump error=%d", rv);
- }
-
- return rv;
-}
-
-int openconfig_interfaces_interfaces_interface_state_cb(
- const char *xpath, sr_val_t **values,
- size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
-{
- sr_xpath_ctx_t state = {0};
- char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
-
- SRP_LOG_INF_MSG("In openconfig_interfaces_interfaces_interface_state_cb");
-
- ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
-
- tmp = xpath_find_first_key(xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("Interface name not found in sysrepo database");
- return SR_ERR_INVAL_ARG;
- }
-
- strncpy(interface_name, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
-
- sys_sw_interface_dump_ctx dctx = {
- .is_subif = false
- };
- sw_interface_details_query_set_name(&dctx.sw_interface_details_query,
- interface_name);
-
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE,
- "/openconfig-interfaces:interfaces/interface[name='%s']/state",
- interface_name);
-
- sysr_sw_interface_dump(&dctx);
-
- if (!dctx.sw_interface_details_query.interface_found) {
- SRP_LOG_ERR_MSG("interface not found");
- return SR_ERR_NOT_FOUND;
- }
-
- sr_xpath_recover(&state);
- *values = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
-
- return SR_ERR_OK;
-}
-
-int oc_dump_ip_helper(char *address_ip, u8 prefix_len,
- sysr_values_ctx_t *sysr_values_ctx)
-{
- sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0;
-
- ARG_CHECK2(SR_ERR_INVAL_ARG, address_ip, sysr_values_ctx);
-
- vc = 3;
- /* convenient functions such as this can be found in sysrepo/values.h */
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
-
- sr_val_build_xpath(&vals[0], "%s/openconfig-if-ip:ip",
- sysr_values_ctx->xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T, address_ip);
-
- sr_val_build_xpath(&vals[1], "%s/openconfig-if-ip:prefix-length",
- sysr_values_ctx->xpath_root);
- vals[1].type = SR_UINT8_T;
- vals[1].data.uint8_val = prefix_len;
-
- sr_val_build_xpath(&vals[2], "%s/openconfig-if-ip:origin",
- sysr_values_ctx->xpath_root);
- sr_val_set_str_data(&vals[2], SR_ENUM_T, "STATIC");
-
- sysr_values_ctx->values = vals;
- sysr_values_ctx->values_cnt = vc;
-
- return SR_ERR_OK;
-}
-
-//TODO: for some arcane reason, this doesn't work
-int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb(
+// 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,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
+ 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};
- int rc;
char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
+ char interface_name[VPP_INTFC_NAME_LEN] = {0};
char subinterface_index[XPATH_SIZE] = {0};
- char address_ip[XPATH_SIZE] = {0};
- u8 prefix_len;
+ 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_MSG("In oc-interfaces oc-ip");
+ SRP_LOG_INF("In %s", __FUNCTION__);
- tmp = xpath_find_first_key(xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("interface_name not found.");
+ 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, XPATH_SIZE);
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
sr_xpath_recover(&state);
- tmp = xpath_find_first_key(xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("subinterface_index not found.");
+ 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);
- tmp = xpath_find_first_key(xpath, "ip", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("address_ip not found.");
- return SR_ERR_INVAL_ARG;
- }
-
- strncpy(address_ip, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
-
- sysr_values_ctx_t dctx = {0};
- snprintf(dctx.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);
+ snprintf(xpath_root, XPATH_SIZE,
+ "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state",
+ interface_name, subinterface_index);
- 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;
+ 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 = oc_dump_ip_helper(address_ip, prefix_len, &dctx);
- if (!rc) {
- SRP_LOG_ERR_MSG("oc_dump_ip_helper failed");
- return rc;
+ /* 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;
}
- sr_xpath_recover(&state);
- *values = dctx.values;
- *values_cnt = dctx.values_cnt;
-
- return SR_ERR_OK;
-}
+ /* 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;
+ }
-// openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state
-int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
-{
- sr_xpath_ctx_t state = {0};
- char *tmp = NULL;
- char interface_name[XPATH_SIZE] = {0};
- char subinterface_index[XPATH_SIZE] = {0};
+ rc = sr_new_values(vc, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
+ 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;
- tmp = xpath_find_first_key(xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("interface_name not found.");
- return SR_ERR_INVAL_ARG;
- }
+ sr_val_build_xpath(&vals[val_idx], "%s/description", xpath_root);
+ sr_val_set_str_data(&vals[val_idx++], SR_STRING_T, NOT_AVAL);
- strncpy(interface_name, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ 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;
- tmp = xpath_find_first_key(xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("subinterface_index not found.");
- return SR_ERR_INVAL_ARG;
- }
+ //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);
- strncpy(subinterface_index, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ // 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;
- sys_sw_interface_dump_ctx dctx =
- {
- .is_subif = true,
- .subinterface_index = atoi(subinterface_index)
- };
- sw_interface_details_query_set_name(&dctx.sw_interface_details_query,
- interface_name);
+ 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");
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE, "/openconfig-interfaces:interfaces/interface[name='%s']/subinterfaces/subinterface[index='%s']/state",
- interface_name, subinterface_index);
+ 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");
- sysr_sw_interface_dump(&dctx);
+ //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);
- if (!dctx.sw_interface_details_query.interface_found) {
- SRP_LOG_DBG_MSG("interface not found");
- return SR_ERR_NOT_FOUND;
- }
+ 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 = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
+
+ *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/
-int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb(
+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,
- __attribute__((unused)) void *private_ctx)
+ void *private_ctx)
{
+ UNUSED(private_ctx);
sr_change_iter_t *it = NULL;
sr_change_oper_t oper;
- sr_val_t *old_val = NULL;
- sr_val_t *new_val = NULL;
+ 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};
+ 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};
@@ -662,82 +466,69 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
// if we receive event SR_EV_APPLY - config has changed
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
-
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY)
return SR_ERR_OK;
- }
if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
sr_free_change_iter(it);
return SR_ERR_OK;
}
- while (sr_get_change_next(ds, it, &oper, &old_val, &new_val) == SR_ERR_OK) {
-
- log_recv_oper(oper, "subtree_change_cb received");
+ foreach_change (ds, it, oper, old, new) {
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
+ SRP_LOG_DBG("xpath: %s", new->xpath);
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "name", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("interface_name NOT found.");
- continue;
+ 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);
+ strncpy(interface_name, tmp, VPP_INTFC_NAME_LEN);
sr_xpath_recover(&state);
- tmp = xpath_find_first_key(new_val->xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("subinterface_index NOT found.");
- continue;
+ 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_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(new->xpath, "ip")) {
ip_set = true;
- strncpy(address_ip, new_val->data.string_val, XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
+ 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_val->data.uint8_val;
+ prefix_len = new->data.uint8_val;
}
- if (ip_set && prefix_len_set) {
- //add ipv4
+ 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_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(old->xpath, "ip")) {
old_ip_set = true;
- strncpy(old_address_ip, old_val->data.string_val,
+ strncpy(old_address_ip, old->data.string_val,
XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
+ } else if (sr_xpath_node_name_eq(old->xpath,
" prefix-length")) {
old_prefix_len_set = true;
- old_prefix_len = old_val->data.uint8_val;
+ old_prefix_len = old->data.uint8_val;
}
- if (sr_xpath_node_name_eq(new_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(new->xpath, "ip")) {
ip_set = true;
- strncpy(address_ip, new_val->data.string_val, XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
+ 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_val->data.uint8_val;
+ prefix_len = new->data.uint8_val;
}
if (old_ip_set && old_prefix_len_set) {
@@ -760,14 +551,14 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
break;
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "ip")) {
+ if (sr_xpath_node_name_eq(old->xpath, "ip")) {
old_ip_set = true;
- strncpy(old_address_ip, old_val->data.string_val,
+ strncpy(old_address_ip, old->data.string_val,
XPATH_SIZE);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
+ } else if (sr_xpath_node_name_eq(old->xpath,
"prefix-length")) {
old_prefix_len_set = true;
- old_prefix_len = old_val->data.uint8_val;
+ old_prefix_len = old->data.uint8_val;
}
if (old_ip_set && old_prefix_len_set) {
@@ -781,8 +572,8 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
if (0 != rc) {
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
sr_free_change_iter(it);
@@ -791,8 +582,8 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
sr_xpath_recover(&state);
- sr_free_val(old_val);
- sr_free_val(new_val);
+ sr_free_val(old);
+ sr_free_val(new);
}
sr_free_change_iter(it);
@@ -801,16 +592,6 @@ int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_
const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE] = {
{
- .xpath = "openconfig-interfaces",
- .method = MODULE,
- .datastore = SR_DS_RUNNING,
- .cb.mcb = openconfig_interface_mod_cb,
- .private_ctx = NULL,
- .priority = 0,
- //.opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY
- .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE
- },
- {
.xpath = "/openconfig-interfaces:interfaces/interface/config",
.method = XPATH,
.datastore = SR_DS_RUNNING,
diff --git a/src/plugins/openconfig/openconfig_interfaces.h b/src/plugins/openconfig/openconfig_interfaces.h
deleted file mode 100644
index 88d5fe0..0000000
--- a/src/plugins/openconfig/openconfig_interfaces.h
+++ /dev/null
@@ -1,26 +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.
- */
-
-
-#ifndef __OPENCONFIG_INTERFACES_H__
-#define __OPENCONFIG_INTERFACES_H__
-
-#include "../sc_model.h"
-
-#define OC_INTERFACES_SIZE 6
-extern const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE];
-
-#endif /* __OPENCONFIG_INTERFACES_H__ */
diff --git a/src/plugins/openconfig/openconfig_local_routing.c b/src/plugins/openconfig/openconfig_local_routing.c
index 5c63eaa..5d18b52 100644
--- a/src/plugins/openconfig/openconfig_local_routing.c
+++ b/src/plugins/openconfig/openconfig_local_routing.c
@@ -17,732 +17,494 @@
#include <assert.h>
#include <string.h>
-#include "openconfig_local_routing.h"
+#include <scvpp/comm.h>
+#include <scvpp/interface.h>
+#include <scvpp/ip.h>
+#include "../sc_model.h"
#include "../sys_util.h"
-#include "sc_vpp_comm.h"
-#include "sc_vpp_interface.h"
-#include "sc_vpp_ip.h"
+#define HOP_INDEX_SIZE 10 //number of digit in max 32 bit integer
-#define XPATH_SIZE 2000
-
-int openconfig_local_routing_mod_cb(
- __attribute__((unused)) sr_session_ctx_t* session,
- __attribute__((unused)) const char* module_name,
- __attribute__((unused)) sr_notif_event_t event,
- __attribute__((unused)) void* private_ctx)
+static inline int
+_set_route (const char *prefix, const char *nhop, bool is_add,
+ const char *iface)
{
- SRP_LOG_DBG("Local routing module subscribe: %s", module_name);
+ 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;
}
-static int set_route(sr_session_ctx_t *sess, const char *index,
- const char *n_interface /*NULLABLE*/,
- const char *n_next_hop /*NULLABLE*/,
- const char *prefix, bool is_add)
-{
- int rc = SR_ERR_OK;
- sr_val_t *value = NULL;
- char xpath[XPATH_SIZE] = {0};
- const char *interface = NULL;
- const char *next_hop = NULL;
+#define STR(string) #string
- ARG_CHECK3(SR_ERR_INVAL_ARG, sess, index, prefix);
+#define ROOT "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/%s"
- if (NULL == n_interface) {
- snprintf(xpath, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/interface-ref/config/interface", prefix, index);
+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;
- rc = sr_get_item(sess, xpath, &value);
- if (SR_ERR_OK != rc) {
- SRP_LOG_DBG_MSG("Interface not set");
- return 0;
- }
+ snprintf(xpath, XPATH_SIZE, ROOT, prefix, index, sub);
- interface = value->data.string_val;
- } else {
- interface = n_interface;
+ rc = sr_get_item(sess, xpath, &value);
+ if (SR_ERR_OK != rc) {
+ SRP_LOG_DBG("XPATH %s not set", xpath);
+ return NULL;
}
- if (NULL == n_next_hop) {
- snprintf(xpath, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/config/next-hop", prefix, index);
+ return value->data.string_val;
+}
- rc = sr_get_item(sess, xpath, &value);
- if (SR_ERR_OK != rc) {
- SRP_LOG_DBG_MSG("Next-hop not set");
- return 0;
- }
+/* @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;
- next_hop = value->data.string_val;
- } else {
- next_hop = n_next_hop;
- }
+ ARG_CHECK3(SR_ERR_INVAL_ARG, sess, index, prefix);
- int mask = ip_prefix_split(prefix);
- if (mask < 1) {
+ if (!interface && !next_hop)
return SR_ERR_INVAL_ARG;
- }
- rc = ipv46_config_add_del_route(prefix, mask, next_hop, is_add, 0,
- interface);
- if (!rc) {
- 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/
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_config_cb(
- sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+static int oc_next_hop_config_cb(sr_session_ctx_t *ds, const char *xpath,
+ sr_notif_event_t event, void *private_ctx)
{
- sr_change_iter_t *it = NULL;
+ 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_val = NULL;
- sr_val_t *new_val = NULL;
+ sr_val_t *old, *new, *tmp;
+ sr_xpath_ctx_t state = {0};
int rc = SR_ERR_OK;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- char next_hop_index[XPATH_SIZE] = {0};
- char next_hop[XPATH_SIZE] = {0};
- char old_next_hop_index[XPATH_SIZE] = {0};
- char old_next_hop[XPATH_SIZE] = {0};
- bool index_set = false, next_hop_set = false;
- bool old_index_set = false, old_next_hop_set = false;
+ UNUSED(private_ctx);
ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath);
- // if we receive event SR_EV_APPLY - config has changed
+ SRP_LOG_INF("In %s", __FUNCTION__);
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
-
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY) //SR_EV_VERIFY already applied the changes
return SR_ERR_OK;
- }
- if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
+ rc = sr_get_changes_iter(ds, (char *)xpath, &it);
+ if (rc != SR_ERR_OK) {
sr_free_change_iter(it);
- return SR_ERR_OK;
+ return rc;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
-
- log_recv_oper(oper, "subtree_change_cb received");
-
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
-
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("static_prefix NOT found.");
- continue;
- }
+ foreach_change(ds, it, oper, old, new) {
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ 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_CREATED:
- if (sr_xpath_node_name_eq(new_val->xpath, "index")) {
- strncpy(next_hop_index, new_val->data.string_val,
- XPATH_SIZE);
- index_set = true;
- } else if(sr_xpath_node_name_eq(new_val->xpath, "next-hop")) {
- next_hop_set = true;
- strncpy(next_hop, new_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(new_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(new_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (index_set && next_hop_set) {
- rc = set_route(ds, next_hop_index, NULL, next_hop,
- static_prefix, true);
- }
- break;
-
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(old_val->xpath, "index")) {
- strncpy(old_next_hop_index, old_val->data.string_val,
- XPATH_SIZE);
- old_index_set = true;
- } else if(sr_xpath_node_name_eq(old_val->xpath, "next-hop")) {
- old_next_hop_set = true;
- strncpy(old_next_hop, old_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(old_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(old_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (sr_xpath_node_name_eq(new_val->xpath, "index")) {
- strncpy(next_hop_index, new_val->data.string_val,
- XPATH_SIZE);
- index_set = true;
- } else if(sr_xpath_node_name_eq(new_val->xpath, "next-hop")) {
- next_hop_set = true;
- strncpy(next_hop, new_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(new_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(new_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (old_index_set && old_next_hop_set) {
- rc = set_route(ds, old_next_hop_index, NULL, old_next_hop,
- static_prefix, false);
- }
-
- if (index_set && next_hop_set) {
- rc = set_route(ds, next_hop_index, NULL, next_hop,
- static_prefix, true);
- }
- break;
-
- case SR_OP_MOVED:
+ case SR_OP_CREATED:
+ tmp = new;
break;
-
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "index")) {
- strncpy(old_next_hop_index, old_val->data.string_val,
- XPATH_SIZE);
- old_index_set = true;
- } else if(sr_xpath_node_name_eq(old_val->xpath, "next-hop")) {
- old_next_hop_set = true;
- strncpy(old_next_hop, old_val->data.string_val, XPATH_SIZE);
- } else if(sr_xpath_node_name_eq(old_val->xpath, "metric")) {
- //TODO: LEAF: metric, type: uint32
- } else if(sr_xpath_node_name_eq(old_val->xpath, "recurse")) {
- //TODO: LEAF: recurse, type: boolean
- }
-
- if (old_index_set && old_next_hop_set) {
- rc = set_route(ds, old_next_hop_index, NULL, old_next_hop,
- static_prefix, false);
- }
+ tmp = old;
+ break;
+ default:
+ SRP_LOG_WRN_MSG("Operation not supported");
break;
}
- if (SR_ERR_OK != rc) {
- sr_xpath_recover(&state);
+ 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;
+ }
- sr_free_val(old_val);
- sr_free_val(new_val);
+ 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);
+ }
- sr_free_change_iter(it);
- return SR_ERR_OPERATION_FAILED;
+ 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_val(old_val);
- sr_free_val(new_val);
}
sr_free_change_iter(it);
- return SR_ERR_OK;
+ 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/
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_config_cb(
- sr_session_ctx_t *ds, const char *xpath, sr_notif_event_t event,
- __attribute__((unused)) void *private_ctx)
+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_val = NULL;
- sr_val_t *new_val = NULL;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- char next_hop_index[XPATH_SIZE] = {0};
- char interface[XPATH_SIZE] = {0};
- char old_interface[XPATH_SIZE] = {0};
+ sr_val_t *old, *new, *tmp;
+ sr_xpath_ctx_t state = {0};
+ bool interface_set = false;
int rc = SR_ERR_OK;
+ UNUSED(private_ctx);
- // if we receive event SR_EV_APPLY - config has changed
-
- log_recv_event(event, "subtree_change_cb received");
- SRP_LOG_DBG("[SRP_LOG_DBG] xpath: %s", xpath);
+ SRP_LOG_INF("In %s", __FUNCTION__);
- if (event != SR_EV_APPLY) {
+ if (event == SR_EV_APPLY)
return SR_ERR_OK;
- }
- if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) {
- // in example he calls even on fale
+ rc = sr_get_changes_iter(ds, (char *)xpath, &it);
+ if (rc != SR_ERR_OK) {
sr_free_change_iter(it);
- return SR_ERR_OK;
+ return rc;
}
- while (sr_get_change_next(ds, it, &oper,
- &old_val, &new_val) == SR_ERR_OK) {
+ foreach_change(ds, it, oper, old, new) {
- log_recv_oper(oper, "subtree_change_cb received");
+ SRP_LOG_DBG("xpath: %s", new->xpath);
- SRP_LOG_DBG("xpath: %s", new_val->xpath);
+ rc = get_xpath_key(prefix, new->xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- sr_xpath_ctx_t state = {0};
-
- tmp = xpath_find_first_key(new_val->xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("static_prefix NOT found.");
- continue;
- }
-
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
-
- tmp = xpath_find_first_key(new_val->xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_DBG_MSG("next-hop_index NOT found.");
- continue;
- }
-
- strncpy(next_hop_index, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ rc |= get_xpath_key(index, new->xpath, "next-hop", "index",
+ HOP_INDEX_SIZE, &state);
+ if (rc)
+ goto error;
switch (oper) {
- case SR_OP_CREATED:
- if (sr_xpath_node_name_eq(new_val->xpath, "interface")) {
- strncpy(interface, new_val->data.string_val, XPATH_SIZE);
- rc = set_route(ds, next_hop_index, interface, NULL,
- static_prefix, true);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
- "subinterface")) {
- }
- break;
-
case SR_OP_MODIFIED:
- if (sr_xpath_node_name_eq(old_val->xpath, "interface")) {
- strncpy(old_interface, old_val->data.string_val,
- XPATH_SIZE);
- rc = set_route(ds, next_hop_index, old_interface, NULL,
- static_prefix, false);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
- "subinterface")) {
- }
-
- if (sr_xpath_node_name_eq(new_val->xpath, "interface")) {
- strncpy(interface, new_val->data.string_val, XPATH_SIZE);
- rc = set_route(ds, next_hop_index, interface, NULL,
- static_prefix, true);
- } else if (sr_xpath_node_name_eq(new_val->xpath,
- "subinterface")) {
- }
- break;
-
- case SR_OP_MOVED:
+ case SR_OP_CREATED:
+ tmp = new;
break;
-
case SR_OP_DELETED:
- if (sr_xpath_node_name_eq(old_val->xpath, "interface")) {
- strncpy(old_interface, old_val->data.string_val,
- XPATH_SIZE);
- rc = set_route(ds, next_hop_index, old_interface, NULL,
- static_prefix, false);
- } else if (sr_xpath_node_name_eq(old_val->xpath,
- "subinterface")) {
- }
+ tmp = old;
+ break;
+ default:
+ SRP_LOG_WRN_MSG("Operation not supported");
break;
}
- if (SR_ERR_OK != rc) {
- sr_xpath_recover(&state);
+ 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;
+ }
- sr_free_val(old_val);
- sr_free_val(new_val);
+ 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;
+ }
- sr_free_change_iter(it);
- return SR_ERR_OPERATION_FAILED;
+ 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_val(old_val);
- sr_free_val(new_val);
}
sr_free_change_iter(it);
return SR_ERR_OK;
-}
-
-typedef struct
-{
- u8 length;
- u8 address[4];
-} address_prefix_t;
-
-typedef struct {
- char *next_hop_index;
- address_prefix_t address_prefix;
- const bool is_interface_ref;
- sw_interface_details_query_t sw_interface_details_query;
- sysr_values_ctx_t sysr_values_ctx;
-} sysr_ip_fib_details_ctx_t;
-
-static
-bool address_prefix_cmp(address_prefix_t* address_prefix,
- vapi_payload_ip_fib_details* reply)
-{
- ARG_CHECK2(false, address_prefix, reply);
-
- if (address_prefix->length == reply->address_length)
- {
- if (0 == memcmp(address_prefix->address, reply->address, sizeof(reply->address)))
- return true;
- }
-
- return false;
-}
-
-static
-bool address_prefix_init(address_prefix_t* address_prefix, char* str_prefix)
-{
- ARG_CHECK2(false, address_prefix, str_prefix);
-
- address_prefix->length = ip_prefix_split(str_prefix);
- if(address_prefix->length < 1)
- {
- SRP_LOG_ERR_MSG("not a valid prefix");
- return false;
- }
- return sc_aton(str_prefix, address_prefix->address,
- sizeof(address_prefix->address));
+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
-int openconfig_local_routing_local_routes_static_routes_static_state_vapi_cb(
- vapi_payload_ip_fib_details *reply,
- sysr_ip_fib_details_ctx_t *sysr_ip_fib_details_ctx)
+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;
- int vc = 0;
- char address_prefix[INET_ADDRSTRLEN + 3] = {0};
- vc = 1;
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, sysr_ip_fib_details_ctx);
+ ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
+ SRP_LOG_INF("In %s", __FUNCTION__);
- //Filling the structure
- snprintf(address_prefix, sizeof(address_prefix), "%s/%u",
- sc_ntoa(reply->address), reply->address_length);
+ rc = get_xpath_key(prefix, (char *)xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
+ if (rc != 0)
+ return SR_ERR_INVAL_ARG;
- sr_val_build_xpath(&vals[0], "%s/prefix",
- sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T, address_prefix);
+ 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;
+ }
- sysr_ip_fib_details_ctx->sysr_values_ctx.values = vals;
- sysr_ip_fib_details_ctx->sysr_values_ctx.values_cnt = vc;
+ /* Allocation for number of elements dumped by ipv4_fib_dump_all */
+ rc = sr_new_values(vc, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- return SR_ERR_OK;
-}
+ sr_val_build_xpath(&vals[0], "%s/prefix", xpath);
+ sr_val_set_str_data(&vals[0], SR_STRING_T, prefix);
-vapi_error_e
-ip_routing_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_ip_fib_details * reply)
-{
- if (is_last)
- {
- assert (NULL == reply);
- }
- else
- {
- sysr_ip_fib_details_ctx_t *dctx = callback_ctx;
- assert(dctx && reply);
+ sr_xpath_recover(&state);
- if (address_prefix_cmp(&dctx->address_prefix, reply))
- {
- openconfig_local_routing_local_routes_static_routes_static_state_vapi_cb(reply,
- dctx);
- }
- }
+ free(reply);
+ *values = vals;
+ *values_cnt = vc;
- return VAPI_OK;
+ return SR_ERR_OK;
}
-int openconfig_local_routing_local_routes_static_routes_static_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) const char *original_xpath,
- __attribute__((unused)) void *private_ctx)
+// 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};
- vapi_error_e rv = 0;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- sysr_ip_fib_details_ctx_t dctx = {0};
+ sr_val_t *vals = NULL;
+ int vc = 3;
+ int rc = 0;
ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- tmp = xpath_find_first_key(xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("static_prefix not found.");
- return SR_ERR_INVAL_ARG;
- }
+ SRP_LOG_INF("In %s", __FUNCTION__);
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ /* Get prefix and index key from XPATH */
+ rc = get_xpath_key(prefix, (char *)xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- //VPP callback
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE, "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/state", static_prefix);
+ rc |= get_xpath_key(index, (char*)xpath, "next-hop", "index",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- if (!address_prefix_init(&dctx.address_prefix, static_prefix))
- {
+ if (rc != 0)
return SR_ERR_INVAL_ARG;
- }
-
- vapi_msg_ip_fib_dump *mp = vapi_alloc_ip_fib_dump (g_vapi_ctx_instance);
-
- VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx_instance, mp, ip_routing_dump_cb, &dctx));
- if(VAPI_OK != rv)
- {
- SRP_LOG_ERR_MSG("VAPI call failed");
+ 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;
}
- sr_xpath_recover(&state);
- *values = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
-
- return SR_ERR_OK;
-}
-
-// // XPATH: /openconfig-local-routing:local-routes/static-routes/l/next-hops/next-hop/state
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_vapi_cb(
- vapi_type_fib_path *reply,
- sysr_ip_fib_details_ctx_t *sysr_ip_fib_details_ctx)
-{
- sr_val_t *vals = NULL;
- int rc = 0;
- int vc = 0;
- char next_hop[INET_ADDRSTRLEN] = {0};
-
- ARG_CHECK2(SR_ERR_INVAL_ARG, reply, sysr_ip_fib_details_ctx);
-
- vc = 3;
- /* convenient functions such as this can be found in sysrepo/values.h */
rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
+ 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 %d", index, strtoul(index, NULL, 0));
+ return SR_ERR_INVAL_ARG;
}
- sr_val_build_xpath(&vals[0], "%s/index",
- sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T,
- sysr_ip_fib_details_ctx->next_hop_index);
+ 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->next_hop), sizeof(next_hop));
- sr_val_build_xpath(&vals[1], "%s/next-hop", sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[1], SR_STRING_T, next_hop);
+ 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", sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
+ sr_val_build_xpath(&vals[2], "%s/metric", xpath);
vals[2].type = SR_UINT32_T;
- vals[2].data.uint32_val = reply->weight;
-
- // sr_val_build_xpath(&vals[3], "%s/recurse", sysr_ip_fib_details_ctx->sysr_values_ctx.xpath_root);
- // vals[3].type = SR_BOOL_T;
- // vals[3].data.bool_val = YANG INPUT TYPE: boolean;
+ vals[2].data.uint32_val = reply->path[0].weight;
- sysr_ip_fib_details_ctx->sysr_values_ctx.values = vals;
- sysr_ip_fib_details_ctx->sysr_values_ctx.values_cnt = vc;
+ free(reply);
+ sr_xpath_recover(&state);
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
-// // XPATH: /openconfig-local-routing:local-routes/static-routes/l/next-hops/next-hop/interface-ref/state
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_vapi_cb(
- sysr_ip_fib_details_ctx_t * dctx)
+// 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;
- int vc = 0;
-
- ARG_CHECK(SR_ERR_INVAL_ARG, dctx);
-
- vc = 2;
- /* convenient functions such as this can be found in sysrepo/values.h */
- rc = sr_new_values(vc, &vals);
- if (SR_ERR_OK != rc) {
- return rc;
- }
- sr_val_build_xpath(&vals[0], "%s/interface",
- dctx->sysr_values_ctx.xpath_root);
- sr_val_set_str_data(&vals[0], SR_STRING_T,
- (const char*)dctx->sw_interface_details_query.sw_interface_details.interface_name);
+ //ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
- sr_val_build_xpath(&vals[1], "%s/subinterface",
- dctx->sysr_values_ctx.xpath_root);
- vals[1].type = SR_UINT32_T;
- vals[1].data.uint32_val = 0;
+ SRP_LOG_INF("In %s", __FUNCTION__);
- dctx->sysr_values_ctx.values = vals;
- dctx->sysr_values_ctx.values_cnt = vc;
+ ///* Get prefix key from XPATH */
+ rc = get_xpath_key(prefix, (char*) xpath, "static", "prefix",
+ VPP_IP4_PREFIX_STRING_LEN, &state);
- return SR_ERR_OK;
-}
-
-vapi_error_e
-ip_routing_next_hop_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx,
- vapi_error_e rv, bool is_last,
- vapi_payload_ip_fib_details * reply)
-{
- ARG_CHECK(VAPI_EINVAL, callback_ctx);
-
- sysr_ip_fib_details_ctx_t *dctx = callback_ctx;
-
- if (is_last)
- {
- assert (NULL == reply);
- }
- else
- {
- assert (NULL != reply);
-
- if (reply->count > 0 && address_prefix_cmp(&dctx->address_prefix, reply))
- {
- if (dctx->is_interface_ref)
- {
- dctx->sw_interface_details_query.interface_found = true;
- dctx->sw_interface_details_query.sw_interface_details.sw_if_index = reply->path[0].sw_if_index;
- //sw_interface_dump will have to be called outside this VAPI
- }
- else
- {
- openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_vapi_cb(reply->path, dctx);
- }
- }
- }
-
- return VAPI_OK;
-}
-
-int next_hop_inner(
- bool is_interface_ref, const char *xpath, sr_val_t **values,
- size_t *values_cnt, __attribute__((unused)) uint64_t request_id,
- __attribute__((unused)) void *private_ctx)
-{
- sr_xpath_ctx_t state = {0};
- vapi_error_e rv;
- char *tmp = NULL;
- char static_prefix[XPATH_SIZE] = {0};
- char next_hop_index[XPATH_SIZE] = {0};
- sysr_ip_fib_details_ctx_t dctx = {.is_interface_ref = is_interface_ref};
-
- ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt);
+ rc |= get_xpath_key(index, (char *)xpath, "next-hop", "index",
+ HOP_INDEX_SIZE, &state);
- tmp = xpath_find_first_key(xpath, "prefix", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("static_prefix not found.");
+ if (rc != 0)
return SR_ERR_INVAL_ARG;
- }
- strncpy(static_prefix, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
- tmp = xpath_find_first_key(xpath, "index", &state);
- if (NULL == tmp) {
- SRP_LOG_ERR_MSG("index not found.");
+ 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;
}
- strncpy(next_hop_index, tmp, XPATH_SIZE);
- sr_xpath_recover(&state);
+ //TODO: check nhop?
- //VPP callback
- dctx.next_hop_index = next_hop_index;
- if (is_interface_ref) {
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/interface-ref/state",
- static_prefix, next_hop_index);
- } else {
- snprintf(dctx.sysr_values_ctx.xpath_root, XPATH_SIZE,
- "/openconfig-local-routing:local-routes/static-routes/static[prefix='%s']/next-hops/next-hop[index='%s']/state",
- static_prefix, next_hop_index);
- }
+ rc = sr_new_values(vc, &vals);
+ if (SR_ERR_OK != rc)
+ return rc;
- if (!address_prefix_init(&dctx.address_prefix, static_prefix))
- {
+ // 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 %d", index, strtoul(index, NULL, 0));
return SR_ERR_INVAL_ARG;
}
- vapi_msg_ip_fib_dump *mp = vapi_alloc_ip_fib_dump (g_vapi_ctx_instance);
- VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx_instance, mp, ip_routing_next_hop_dump_cb, &dctx));
- if (VAPI_OK != rv)
- {
- SRP_LOG_ERR_MSG("VAPI call failed");
+ 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;
}
- if (is_interface_ref)
- {
- if (dctx.sw_interface_details_query.interface_found)
- {
- if (!get_interface_name(&dctx.sw_interface_details_query))
- {
- return SR_ERR_INVAL_ARG;
- }
- if (strlen((const char*)
- dctx.sw_interface_details_query.sw_interface_details.interface_name)) {
- openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_vapi_cb(&dctx);
- }
- }
- }
+ 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 = dctx.sysr_values_ctx.values;
- *values_cnt = dctx.sysr_values_ctx.values_cnt;
+ *values = vals;
+ *values_cnt = vc;
return SR_ERR_OK;
}
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_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)
-{
- return next_hop_inner(false, xpath, values, values_cnt, request_id,
- private_ctx);
-}
-
-int openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_cb(
- const char *xpath, sr_val_t **values, size_t *values_cnt,
- uint64_t request_id, const char *original_xpath, void *private_ctx)
-{
- return next_hop_inner(true, xpath, values, values_cnt, request_id,
- private_ctx);
-}
-
const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
{
- .xpath = "openconfig-local-routing",
- .method = MODULE,
+ .xpath = "/openconfig-local-routing:local-routes/static-routes/static/config",
+ .method = XPATH,
.datastore = SR_DS_RUNNING,
- .cb.mcb = openconfig_local_routing_mod_cb,
+ .cb.scb = oc_prefix_config_cb,
.private_ctx = NULL,
.priority = 0,
- //.opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY
- .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE
+ //.opts = SR_SUBSCR_DEFAULT
+ .opts = SR_SUBSCR_CTX_REUSE
},
{
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/config",
.method = XPATH,
.datastore = SR_DS_RUNNING,
- .cb.scb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_config_cb,
+ .cb.scb = oc_next_hop_config_cb,
.private_ctx = NULL,
.priority = 0,
//.opts = SR_SUBSCR_DEFAULT
@@ -752,7 +514,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/config",
.method = XPATH,
.datastore = SR_DS_RUNNING,
- .cb.scb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_config_cb,
+ .cb.scb = oc_next_hop_interface_config_cb,
.private_ctx = NULL,
.priority = 0,
//.opts = SR_SUBSCR_DEFAULT
@@ -762,7 +524,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/state",
.method = GETITEM,
.datastore = SR_DS_RUNNING,
- .cb.gcb = openconfig_local_routing_local_routes_static_routes_static_state_cb,
+ .cb.gcb = oc_prefix_state_cb,
.private_ctx = NULL,
.priority = 0,
.opts = SR_SUBSCR_CTX_REUSE
@@ -771,7 +533,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state",
.method = GETITEM,
.datastore = SR_DS_RUNNING,
- .cb.gcb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_state_cb,
+ .cb.gcb = oc_next_hop_state_cb,
.private_ctx = NULL,
.priority = 0,
.opts = SR_SUBSCR_CTX_REUSE
@@ -780,7 +542,7 @@ const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = {
.xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state",
.method = GETITEM,
.datastore = SR_DS_RUNNING,
- .cb.gcb = openconfig_local_routing_local_routes_static_routes_static_next_hops_next_hop_interface_ref_state_cb,
+ .cb.gcb = oc_next_hop_interface_state_cb,
.private_ctx = NULL,
.priority = 0,
.opts = SR_SUBSCR_CTX_REUSE
diff --git a/src/plugins/openconfig/openconfig_local_routing.h b/src/plugins/openconfig/openconfig_local_routing.h
deleted file mode 100644
index 13d2982..0000000
--- a/src/plugins/openconfig/openconfig_local_routing.h
+++ /dev/null
@@ -1,25 +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.
- */
-
-#ifndef __OPENCONFIG_LOCAL_ROUTING_H__
-#define __OPENCONFIG_LOCAL_ROUTING_H__
-
-#include "../sc_model.h"
-
-#define OC_LROUTING_SIZE 6
-extern const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE];
-
-#endif /* __OPENCONFIG_LOCAL_ROUTING_H__ */