diff options
author | YohanPipereau <ypiperea@cisco.com> | 2019-03-06 14:01:58 +0100 |
---|---|---|
committer | YohanPipereau <ypiperea@cisco.com> | 2019-03-29 14:39:36 +0100 |
commit | a760dfb253161911fc3aa3c8b879c461d53ade6e (patch) | |
tree | 0e79953f4ed5615879a58f49a74df3f9c6739a42 /src | |
parent | 2b9b6b9b130b75799a40989c0ebe5040fa3e45fb (diff) |
Sweetcomb global cleanup
-Merge IETF and Openconfig to use SCVPP 2
-Move L2 bridge from sc_vpp_interface to sc_vpp_v3po
-Implement tav2 dump
-Make openconfig-interfaces functions static
-Try one more dispatch after failure in VAPI_CALL
-Add error return code for scvpp
-Remove unused length maccros
-Return appropriate error code for interface dump when interface not found
-Improve scvpp test suite
-Change get_interface_id prototype
-Use interface_dump_iface in openconfig_interface.
-No more vapi types in openconfig_interfaces.c
-Move openconfig_local_routing VAPI operations to sc_vpp_ip
-Implement a multiple dump with a stack data structure
-Comment out state_cb code from openconfig_local_routing to use new
functions later.
-Rename YANG model to their fully qualified name : <module>@<revision>
-Remove headers almost empty and put registration declaration in
sc_model.h
-Shorten vapi context global variable name
-Reorganize scvpp unit test suite
-Add instructions to Makefile to install/uninstall YANG models in sysrepo.
-Add this new instructions to README.md.
-Reimplement interface_dump_all
-Use a common message at INFO Log Level to know when sysrepo callbacks
are triggered
-Remove old structure to perform dump of all interfaces
-Reimplement get_interface_name and add scvpp test for it
-Clean sys_util
-Use UNUSED maccro everywhere to have lighter prototypes
-Have ietf-interfaces:interfaces-state work with new dump function
-Add setup and teardown for NAT tests
-Remove unused tapv2 dump
-Remove useless sysrepo module callback
-Remove xpath_find_first_key usage in openconfig-interfaces
-Remove xpath_find_first_key in oc_local_routing and in the rest of
sweetcomb
-Reorganize scvpp include dir and fix scvpp_test new warnings
-Fix scvpp tests for ip routes
-Factorize scvpp nat and test return code of its function
-Correct test_dump_if_all if there is an existing hardware interface
-Implement a per-prefix dump in scvpp
-free changes iterator in ietf-interfaces
-Add new XPATH in oc local-routing
-Introduce helper methods for sysrepo config callbacks
-Factorize config callback
-Refactor the openconfig-local-routing config callback
-Use common foreach_change to iterate over changes in all models
-Create a sample directory gathering example of configurations supposed
to work with sweetcomb
-Fix state callback of oc-local-routing
-Add new sample for get operation on next-hop
-foreach_elt maccro condition forgets to read one element
Change-Id: I8e87fce577a00337977588f057a6e095a20f457c
Signed-off-by: YohanPipereau <ypiperea@cisco.com>
Diffstat (limited to 'src')
52 files changed, 3632 insertions, 3032 deletions
diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index d8dba04..d7f38e0 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -55,7 +55,6 @@ set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FL set(PLUGINS_SOURCES sc_plugins.c sc_model.c - sys_util.c ietf/ietf_interface.c ietf/ietf_nat.c openconfig/openconfig_interfaces.c diff --git a/src/plugins/ietf/ietf_interface.c b/src/plugins/ietf/ietf_interface.c index 922c84f..0f8c37e 100644 --- a/src/plugins/ietf/ietf_interface.c +++ b/src/plugins/ietf/ietf_interface.c @@ -15,33 +15,12 @@ #include <stdio.h> #include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include "ietf_interface.h" +#include "../sc_model.h" +#include "../sys_util.h" -#include "sc_vpp_interface.h" -#include "sc_vpp_ip.h" - -/** - * @brief Helper function for converting netmask (ex: 255.255.255.0) - * to prefix length (ex: 24). - */ -static uint8_t -netmask_to_prefix(const char *netmask) -{ - in_addr_t n = 0; - uint8_t i = 0; - - inet_pton(AF_INET, netmask, &n); - - while (n > 0) { - n = n >> 1; - i++; - } - - return i; -} +#include <scvpp/interface.h> +#include <scvpp/ip.h> /** * @brief Callback to be called by any config change of @@ -51,6 +30,7 @@ static int ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath, sr_notif_event_t event, void *private_ctx) { + UNUSED(private_ctx); char *if_name = NULL; sr_change_iter_t *iter = NULL; sr_change_oper_t op = SR_OP_CREATED; @@ -60,22 +40,22 @@ ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath, int rc = SR_ERR_OK, op_rc = SR_ERR_OK; SRP_LOG_INF("In %s", __FUNCTION__); + /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */ - if (SR_EV_APPLY == event) { + if (SR_EV_APPLY == event) return SR_ERR_OK; - } + SRP_LOG_DBG("'%s' modified, event=%d", xpath, event); /* get changes iterator */ rc = sr_get_changes_iter(session, xpath, &iter); if (SR_ERR_OK != rc) { + sr_free_change_iter(iter); SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc)); return rc; } - /* iterate over all changes */ - while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) && - (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) { + foreach_change (session, iter, op, old_val, new_val) { SRP_LOG_DBG("A change detected in '%s', op=%d", new_val ? new_val->xpath : old_val->xpath, op); if_name = sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx); @@ -102,23 +82,6 @@ ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath, return op_rc; } -static int free_sw_interface_dump_ctx(dump_all_ctx * dctx) -{ - if(dctx == NULL) - return -1; - - if(dctx->intfcArray != NULL) - { - free(dctx->intfcArray); - } - - dctx->intfcArray = NULL; - dctx->capacity = 0; - dctx->num_ifs = 0; - - return 0; -} - /** * @brief Modify existing IPv4/IPv6 config on an interface. */ @@ -169,7 +132,8 @@ interface_ipv46_config_modify(const char *if_name, sr_val_t *old_val, } /** - * @brief Callback to be called by any config change in subtrees "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address" + * @brief Callback to be called by any config change in subtrees + * "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address" * or "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address". */ static int @@ -178,6 +142,7 @@ ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session, sr_notif_event_t event, void *private_ctx) { + UNUSED(private_ctx); sr_change_iter_t *iter = NULL; sr_change_oper_t op = SR_OP_CREATED; sr_val_t *old_val = NULL; @@ -207,13 +172,12 @@ ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session, /* get changes iterator */ rc = sr_get_changes_iter(session, xpath, &iter); if (SR_ERR_OK != rc) { + sr_free_change_iter(iter); SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc)); return rc; } - /* iterate over all changes */ - while ((SR_ERR_OK == op_rc || event == SR_EV_ABORT) && - (SR_ERR_OK == (rc = sr_get_change_next(session, iter, &op, &old_val, &new_val)))) { + foreach_change(session, iter, op, old_val, new_val) { SRP_LOG_DBG("A change detected in '%s', op=%d", new_val ? new_val->xpath : old_val->xpath, op); if_name = strdup(sr_xpath_key_value(new_val ? new_val->xpath : old_val->xpath, "interface", "name", &xpath_ctx)); @@ -287,8 +251,9 @@ static int ietf_interface_change_cb(sr_session_ctx_t *session, const char *xpath, sr_notif_event_t event, void *private_ctx) { + UNUSED(session); UNUSED(xpath); UNUSED(event); UNUSED(private_ctx); + SRP_LOG_INF("In %s", __FUNCTION__); - SRP_LOG_DBG("'%s' modified, event=%d", xpath, event); return SR_ERR_OK; } @@ -298,87 +263,80 @@ ietf_interface_change_cb(sr_session_ctx_t *session, const char *xpath, */ static int ietf_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) + size_t *values_cnt, uint64_t request_id, + const char *original_xpath, void *private_ctx) { - sr_val_t *values_arr = NULL; - int values_arr_size = 0, values_arr_cnt = 0; - dump_all_ctx dctx; - int nb_iface; - vpp_interface_t* if_details; - int rc = 0; + UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); + struct elt* stack; + sw_interface_dump_t *dump; + sr_val_t *val = NULL; + int vc = 5; //number of answer per interfaces + int cnt = 0; //value counter + int rc = SR_ERR_OK; SRP_LOG_INF("In %s", __FUNCTION__); - if (! sr_xpath_node_name_eq(xpath, "interface")) { - /* statistics, ipv4 and ipv6 state data not supported */ - *values = NULL; - *values_cnt = 0; - return SR_ERR_OK; - } + if (!sr_xpath_node_name_eq(xpath, "interface")) + goto nothing_todo; //no interface field specified /* dump interfaces */ - nb_iface = interface_dump_all(&dctx); - if (nb_iface <= 0) { - SRP_LOG_ERR_MSG("Error by processing of a interface dump request."); - free_sw_interface_dump_ctx(&dctx); - return SR_ERR_INTERNAL; - } + stack = interface_dump_all(); + if (!stack) + goto nothing_todo; //no element returned /* allocate array of values to be returned */ - values_arr_size = nb_iface * 5; - rc = sr_new_values(values_arr_size, &values_arr); - if (0 != rc) { - free_sw_interface_dump_ctx(&dctx); - return rc; - } - - int i = 0; - for (; i < nb_iface; i++) { - if_details = dctx.intfcArray+i; - - /* currently the only supported interface types are propVirtual / ethernetCsmacd */ - sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/type", xpath, if_details->interface_name); - sr_val_set_str_data(&values_arr[values_arr_cnt], SR_IDENTITYREF_T, - strstr((char*)if_details->interface_name, "local0") ? "iana-if-type:propVirtual" : "iana-if-type:ethernetCsmacd"); - values_arr_cnt++; - - sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/admin-status", xpath, if_details->interface_name); - sr_val_set_str_data(&values_arr[values_arr_cnt], SR_ENUM_T, if_details->admin_up_down ? "up" : "down"); - values_arr_cnt++; - - sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/oper-status", xpath, if_details->interface_name); - sr_val_set_str_data(&values_arr[values_arr_cnt], SR_ENUM_T, if_details->link_up_down ? "up" : "down"); - values_arr_cnt++; - - if (if_details->l2_address_length > 0) { - sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/phys-address", xpath, if_details->interface_name); - sr_val_build_str_data(&values_arr[values_arr_cnt], SR_STRING_T, "%02x:%02x:%02x:%02x:%02x:%02x", - if_details->l2_address[0], if_details->l2_address[1], if_details->l2_address[2], - if_details->l2_address[3], if_details->l2_address[4], if_details->l2_address[5]); - values_arr_cnt++; + SRP_LOG_DBG("number of interfaces: %d", stack->id+1); + rc = sr_new_values((stack->id + 1)* vc, &val); + if (0 != rc) + goto nothing_todo; + + foreach_stack_elt(stack) { + dump = (sw_interface_dump_t *) data; + + SRP_LOG_DBG("State of interface %s", dump->interface_name); + //TODO need support for type propvirtual + sr_val_build_xpath(&val[cnt], "%s[name='%s']/type", xpath, dump->interface_name); + sr_val_set_str_data(&val[cnt], SR_IDENTITYREF_T, "iana-if-type:ethernetCsmacd"); + cnt++; + + //Be careful, it needs if-mib feature to work ! + sr_val_build_xpath(&val[cnt], "%s[name='%s']/admin-status", xpath, dump->interface_name); + sr_val_set_str_data(&val[cnt], SR_ENUM_T, dump->link_up_down ? "up" : "down"); + cnt++; + + sr_val_build_xpath(&val[cnt], "%s[name='%s']/oper-status", xpath, dump->interface_name); + sr_val_set_str_data(&val[cnt], SR_ENUM_T, dump->link_up_down ? "up" : "down"); + cnt++; + + sr_val_build_xpath(&val[cnt], "%s[name='%s']/phys-address", xpath, dump->interface_name); + if (dump->l2_address_length > 0) { + sr_val_build_str_data(&val[cnt], SR_STRING_T, + "%02x:%02x:%02x:%02x:%02x:%02x", + dump->l2_address[0], dump->l2_address[1], + dump->l2_address[2], dump->l2_address[3], + dump->l2_address[4], dump->l2_address[5]); } else { - sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/phys-address", xpath, if_details->interface_name); - sr_val_build_str_data(&values_arr[values_arr_cnt], SR_STRING_T, "%02x:%02x:%02x:%02x:%02x:%02x", 0,0,0,0,0,0); - values_arr_cnt++; + sr_val_build_str_data(&val[cnt], SR_STRING_T, "%02x:%02x:%02x:%02x:%02x:%02x", 0,0,0,0,0,0); } + cnt++; - sr_val_build_xpath(&values_arr[values_arr_cnt], "%s[name='%s']/speed", xpath, if_details->interface_name); - values_arr[values_arr_cnt].type = SR_UINT64_T; - values_arr[values_arr_cnt].data.uint64_val = if_details->link_speed; - values_arr_cnt++; - } - - SRP_LOG_DBG("Returning %zu state data elements for '%s'", values_arr, xpath); + sr_val_build_xpath(&val[cnt], "%s[name='%s']/speed", xpath, dump->interface_name); + val[cnt].type = SR_UINT64_T; + val[cnt].data.uint64_val = dump->link_speed; + cnt++; - *values = values_arr; - *values_cnt = values_arr_cnt; + free(dump); + } - free_sw_interface_dump_ctx(&dctx); + *values = val; + *values_cnt = cnt; return SR_ERR_OK; + +nothing_todo: + *values = NULL; + *values_cnt = 0; + return rc; } const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE] = { diff --git a/src/plugins/ietf/ietf_interface.h b/src/plugins/ietf/ietf_interface.h deleted file mode 100644 index 28a3783..0000000 --- a/src/plugins/ietf/ietf_interface.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2018 HUACHENTEL and/or its affiliates. - * 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 __IETF_INTERFACE_H__ -#define __IETF_INTERFACE_H__ - -#include "../sc_model.h" - -#define IETF_INTERFACES_SIZE 5 -extern const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE]; - -#endif /* __IETF_INTERFACE_H__ */ - diff --git a/src/plugins/ietf/ietf_nat.c b/src/plugins/ietf/ietf_nat.c index 86c8570..9b2890e 100644 --- a/src/plugins/ietf/ietf_nat.c +++ b/src/plugins/ietf/ietf_nat.c @@ -14,10 +14,11 @@ * limitations under the License. */ -#include "ietf_nat.h" -#include "sc_vpp_comm.h" -#include "sc_vpp_interface.h" -#include "sc_vpp_nat.h" +#include <scvpp/comm.h> +#include <scvpp/interface.h> +#include <scvpp/nat.h> + +#include "../sc_model.h" #include <assert.h> #include <string.h> @@ -30,17 +31,6 @@ #include "../sys_util.h" -static int ietf_nat_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("Module subscribe: %s", module_name); - - return SR_ERR_OK; -} - /** * @brief Wrapper struct for VAPI address range payload. */ @@ -103,8 +93,7 @@ static int parse_instance_policy_external_ip_address_pool( if (sr_xpath_node_name_eq(val->xpath, "pool-id")) { SRP_LOG_WRN("%s not supported.", val->xpath); } else if(sr_xpath_node_name_eq(val->xpath, "external-ip-pool")) { - rc = get_address_from_prefix(tmp_str, val->data.string_val, - VPP_IP4_ADDRESS_STRING_LEN, &prefix); + rc = prefix2address(tmp_str, val->data.string_val, &prefix); if (0 != rc) { SRP_LOG_ERR_MSG("Error translate"); return SR_ERR_INVAL_ARG; @@ -136,8 +125,9 @@ static int parse_instance_policy_external_ip_address_pool( // XPATH: /ietf-nat:nat/instances/instance[id='%s']/policy[id='%s']/external-ip-address-pool[pool-id='%s']/ static int instances_instance_policy_external_ip_address_pool_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_error_t rc = SR_ERR_OK; sr_change_iter_t *it = NULL; sr_change_oper_t oper; @@ -150,6 +140,8 @@ static int instances_instance_policy_external_ip_address_pool_cb( ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); + SRP_LOG_INF("In %s", __FUNCTION__); + new_address_r.payload.vrf_id = ~0; old_address_r.payload.vrf_id = ~0; @@ -165,8 +157,7 @@ static int instances_instance_policy_external_ip_address_pool_cb( 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_val, new_val) { SRP_LOG_DBG("A change detected in '%s', op=%d", new_val ? new_val->xpath : old_val->xpath, oper); @@ -345,8 +336,7 @@ static int parse_instance_mapping_table_mapping_entry( return SR_ERR_INVAL_ARG; } - rc = get_address_from_prefix(tmp_str, val->data.string_val, - VPP_IP4_PREFIX_STRING_LEN, NULL); + rc = prefix2address(tmp_str, val->data.string_val, NULL); if (0 != rc) { SRP_LOG_ERR_MSG("Error translate"); return SR_ERR_INVAL_ARG; @@ -367,8 +357,7 @@ static int parse_instance_mapping_table_mapping_entry( return SR_ERR_INVAL_ARG; } - rc = get_address_from_prefix(tmp_str, val->data.string_val, - VPP_IP4_ADDRESS_STRING_LEN, NULL); + rc = prefix2address(tmp_str, val->data.string_val, NULL); if (0 != rc) { SRP_LOG_ERR_MSG("Error translate"); return SR_ERR_INVAL_ARG; @@ -402,8 +391,9 @@ static int parse_instance_mapping_table_mapping_entry( // XPATH: /ietf-nat:nat/instances/instance[id='%s']/mapping-table/mapping-entry[index='%s']/ static int instances_instance_mapping_table_mapping_entry_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_error_t rc = SR_ERR_OK; sr_change_iter_t *it = NULL; sr_change_oper_t oper; @@ -416,6 +406,8 @@ static int instances_instance_mapping_table_mapping_entry_cb( ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); + SRP_LOG_INF("In %s", __FUNCTION__); + new_mapping.mtype = UNKNOWN; old_mapping.mtype = UNKNOWN; @@ -431,8 +423,7 @@ static int instances_instance_mapping_table_mapping_entry_cb( 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_val, new_val) { SRP_LOG_DBG("A change detected in '%s', op=%d", new_val ? new_val->xpath : old_val->xpath, oper); @@ -503,15 +494,6 @@ error: const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE] = { { - .xpath = "ietf-nat", - .method = MODULE, - .datastore = SR_DS_RUNNING, - .cb.mcb = ietf_nat_mod_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_EV_ENABLED | SR_SUBSCR_APPLY_ONLY | SR_SUBSCR_CTX_REUSE - }, - { .xpath = "/ietf-nat:nat/instances/instance/policy/external-ip-address-pool", .method = XPATH, .datastore = SR_DS_RUNNING, diff --git a/src/plugins/ietf/ietf_nat.h b/src/plugins/ietf/ietf_nat.h deleted file mode 100644 index 7495209..0000000 --- a/src/plugins/ietf/ietf_nat.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2019 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 __IETF_NAT_H__ -#define __IETF_NAT_H__ - -#include "../sc_model.h" - -#define IETF_NAT_SIZE 3 -extern const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE]; - -#endif 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__ */ diff --git a/src/plugins/sc_model.h b/src/plugins/sc_model.h index ad4055b..a9392f9 100644 --- a/src/plugins/sc_model.h +++ b/src/plugins/sc_model.h @@ -29,7 +29,7 @@ #include <sysrepo/values.h> #include <sysrepo/plugins.h> -#include "sc_vpp_comm.h" //for ARG_CHECK only +#include <scvpp/comm.h> //for ARG_CHECK only typedef enum { MODULE, @@ -68,4 +68,18 @@ typedef struct { int model_register(plugin_main_t *plugin_main, const xpath_t *xpaths, size_t size); +/* Declare registration */ + +#define OC_INTERFACES_SIZE 5 +extern const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE]; + +#define OC_LROUTING_SIZE 6 +extern const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE]; + +#define IETF_NAT_SIZE 2 +extern const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE]; + +#define IETF_INTERFACES_SIZE 5 +extern const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE]; + #endif /* __SC_MODEL_H__ */ diff --git a/src/plugins/sc_plugins.c b/src/plugins/sc_plugins.c index 87ea2d7..4dc6751 100644 --- a/src/plugins/sc_plugins.c +++ b/src/plugins/sc_plugins.c @@ -16,11 +16,6 @@ #include "sc_plugins.h" #include "sc_model.h" -#include "ietf/ietf_interface.h" -#include "ietf/ietf_nat.h" -#include "openconfig/openconfig_interfaces.h" -#include "openconfig/openconfig_local_routing.h" - int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) { plugin_main_t plugin_main; diff --git a/src/plugins/sys_util.c b/src/plugins/sys_util.c deleted file mode 100644 index a3ee0c9..0000000 --- a/src/plugins/sys_util.c +++ /dev/null @@ -1,170 +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 "sys_util.h" -#include "sc_vpp_comm.h" - -#include <string.h> -#include <sysrepo/plugins.h> - -char* xpath_find_first_key(const char *xpath, char *key, sr_xpath_ctx_t *state) -{ - char *value = NULL; - - if (sr_xpath_next_node((char *)xpath, state) == NULL) { - return NULL; - } - - while (((value = sr_xpath_node_key_value(NULL, - key, state)) == NULL) && - (sr_xpath_next_node(NULL, state) != NULL)); - - return value; -} - -// we can call sr_get_item after change is called to see if the value has or has not -// changed (simpleton solution :D) -// sr_get_item(sess, "/ietf-interfaces:interfaces/interface[name='eth0']/enabled", &value); - -void log_recv_event(sr_notif_event_t event, const char *msg) { - const char *event_s; - switch (event) { - case SR_EV_VERIFY: event_s = "SR_EV_VERIFY"; break; - case SR_EV_APPLY: event_s = "SR_EV_APPLY"; break; - case SR_EV_ABORT: event_s = "SR_EV_ABORT"; break; - default: event_s = "SR_EV_UNKNOWN"; - } - SRP_LOG_DBG("%s: %s\n", msg, event_s); -} - -void log_recv_oper(sr_change_oper_t oper, const char *msg) { - const char *oper_s; - switch (oper) { - case SR_OP_CREATED: oper_s = "SR_OP_CREATED"; break; - case SR_OP_DELETED: oper_s = "SR_OP_DELETED"; break; - case SR_OP_MODIFIED: oper_s = "SR_OP_MODIFIED"; break; - case SR_OP_MOVED: oper_s = "SR_OP_MOVED"; break; - default: oper_s = "SR_OP_UNKNOWN"; break; - } - SRP_LOG_DBG("%s: %s\n", msg, oper_s); -} - -int ip_prefix_split(const char* ip_prefix) -{ - //find the slash - char* slash = strchr(ip_prefix, '/'); - if (NULL == slash) - return -1; - - //extract subnet mask length - char * eptr = NULL; - u8 mask = strtoul(slash + 1, &eptr, 10); - if (*eptr || mask <= 0) - return -1; - - //keep just the address part - *slash = '\0'; //replace '/' with 0 - - //return mask length - return mask; -} - -/** - * @brief Get IPv4 host address from IPv4 prefix. - * - * @param[out] dst Host IPv4 address. - * @param[in] src IPv4 Prefix. - * @param[in] length dst buffer length. - * @param[out] prefix Get Prefix length, optional value. Can be NULL. - * @return -1 when failure, 0 on success. - */ -int get_address_from_prefix(char *dst, const char *src, size_t length, - uint8_t *prefix_length) -{ - ARG_CHECK2(-1, src, dst); - - size_t size = 0; - char *p = strchr(src, '/'); - if (NULL == p) { - return -1; - } - - size = p - src; - - // + 1, need size for \0 - if ((size + 1) > length) { - return -1; - } - - strncpy(dst, src, size); - - if (NULL != prefix_length) { - *prefix_length = atoi(++p); - } - - return 0; -} - -/** - * @brief Get IPv4 broadcast IP address form IPv4 network address. - * - * @param[out] broadcat Broadcast Ipv4 address. - * @param[in] network Network IPv4 address. - * @param[in] prefix Prefix number. - * @return -1 when failure, 0 on success. - */ -int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network, - uint8_t prefix_length) -{ - uint8_t mask = ~0; - uint8_t tmp_p = prefix_length; - int i; - - ARG_CHECK2(-1, network, broadcast); - - if (32 < prefix_length) { - SRP_LOG_ERR_MSG("Prefix length to big."); - return -1; - } - - for (i = 0; i < 4 ; i++) { - broadcast->address[i] = network->address[i] | - (mask >> (tmp_p > 8 ? 8 : tmp_p)); - if (tmp_p >= 8) { - tmp_p -= 8; - } else { - tmp_p = 0; - } - } - - return 0; -} - -/** - * @brief Get last IPv4 address from the IP range. - * - * @param[out] last_ip_address Last Ipv4 address. - * @param[in] first_ip_address First IPv4 address. - * @param[in] prefix Prefix number. - * @return -1 when failure, 0 on success. - */ -int get_last_ip_address(sc_ipv4_addr* last_ip_address, - const sc_ipv4_addr* first_ip_address, - uint8_t prefix_length) -{ - return get_network_broadcast(last_ip_address, first_ip_address, - prefix_length); -} diff --git a/src/plugins/sys_util.h b/src/plugins/sys_util.h index d449712..692a012 100644 --- a/src/plugins/sys_util.h +++ b/src/plugins/sys_util.h @@ -19,20 +19,71 @@ #include <sysrepo.h> #include <sysrepo/xpath.h> +#include <sysrepo/plugins.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <string.h> + +#include <scvpp/comm.h> + +/* BEGIN sysrepo utils */ + +#define foreach_change(ds, it, oper, old, new) \ + while( (event != SR_EV_ABORT) && \ + sr_get_change_next(ds, it, &oper, &old, &new) == SR_ERR_OK) #define XPATH_SIZE 2000 +#define NOT_AVAL "NOT AVAILABLE" + +static inline int +get_xpath_key(char *dst, char *xpath, char *node, char *key, int length, + sr_xpath_ctx_t *state) { + char *tmp; + + tmp = sr_xpath_key_value(xpath, node, key, state); + if (!tmp) { + SRP_LOG_ERR("%s %s not found.", node, key); + return SR_ERR_INVAL_ARG; + } + strncpy(dst, tmp, length); + sr_xpath_recover(state); + + return 0; +} + +/* END of sysrepo utils */ typedef struct { - char xpath_root[XPATH_SIZE]; - sr_val_t * values; - size_t values_cnt; -} sysr_values_ctx_t; + uint8_t address[4]; +} sc_ipv4_addr; -char* xpath_find_first_key(const char *xpath, char *key, sr_xpath_ctx_t *state); -void log_recv_event(sr_notif_event_t event, const char *msg); -void log_recv_oper(sr_change_oper_t oper, const char *msg); -int ip_prefix_split(const char* ip_prefix); +/** + * @brief Extract IP "AAA.BBB.CCC.DDD" from an IP prefix: "AAA.BBB.CCC.DDD/XX" + * @param prefix - IPv4 or IPv6 prefix: + * @return prefix length + */ +static inline int ip_prefix_split(const char* ip_prefix) +{ + //find the slash + char* slash = strchr(ip_prefix, '/'); + if (NULL == slash) + return -1; + + //extract subnet mask length + char * eptr = NULL; + uint8_t plen = strtoul(slash + 1, &eptr, 10); + if (*eptr || plen <= 0) + return -1; + + //keep just the address part + *slash = '\0'; //replace '/' with 0 + + //return prefix length + return plen; +} /** * @brief Get IPv4 host address from IPv4 prefix. @@ -43,13 +94,61 @@ int ip_prefix_split(const char* ip_prefix); * @param[out] prefix Get Prefix length, optional value. Can be NULL. * @return -1 when failure, 0 on success. */ -int get_address_from_prefix(char* dst, const char* src, size_t length, - uint8_t* prefix_length); +static inline int +prefix2address(char *dst, const char *src, uint8_t *prefix_length) +{ + if (!src || !dst) + return -1; -typedef struct + char *p = strchr(src, '/'); + if (!p) + return -1; // '/' not found + + if ((p - src + 1) > VPP_IP4_ADDRESS_STRING_LEN) //+ 1 needed for \0 + return -1; + + strncpy(dst, src, VPP_IP4_ADDRESS_STRING_LEN); + + if (!prefix_length) + *prefix_length = atoi(++p); + + return 0; +} + +/** + * @brief Helper function for converting netmask (ex: 255.255.255.0) + * to prefix length (ex: 24). + * @param netmask - string of netmask "AAA.BBB.CCC.DDD" + * @return prefix length + */ +static inline uint8_t netmask_to_prefix(const char *netmask) { - uint8_t address[4]; -} sc_ipv4_addr; + in_addr_t n = 0; + uint8_t i = 0; + + inet_pton(AF_INET, netmask, &n); + + while (n > 0) { + n = n >> 1; + i++; + } + + return i; +} + +/** + * @brief Convert prefix length to netmask + * @param prefix - prefix length (ex: 24) + * @return netmask - integer (ex: 111111111111111111111111100000000b ) + */ +static inline uint32_t prefix2mask(int prefix) +{ + if (prefix) { + return htonl(~((1 << (32 - prefix)) - 1)); + } else { + return htonl(0); + } +} /** * @brief Get IPv4 broadcast IP address form IPv4 network address. @@ -59,8 +158,32 @@ typedef struct * @param[in] prefix Prefix number. * @return -1 when failure, 0 on success. */ -int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network, - uint8_t prefix_length); +static inline int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network, + uint8_t prefix_length) +{ + uint8_t mask = ~0; + uint8_t tmp_p = prefix_length; + int i; + + ARG_CHECK2(-1, network, broadcast); + + if (32 < prefix_length) { + SRP_LOG_ERR_MSG("Prefix length to big."); + return -1; + } + + for (i = 0; i < 4 ; i++) { + broadcast->address[i] = network->address[i] | + (mask >> (tmp_p > 8 ? 8 : tmp_p)); + if (tmp_p >= 8) { + tmp_p -= 8; + } else { + tmp_p = 0; + } + } + + return 0; +} /** * @brief Get last IPv4 address from the IP range. @@ -70,8 +193,12 @@ int get_network_broadcast(sc_ipv4_addr *broadcast, const sc_ipv4_addr *network, * @param[in] prefix Prefix number. * @return -1 when failure, 0 on success. */ -int get_last_ip_address(sc_ipv4_addr *last_ip_address, - const sc_ipv4_addr *first_ip_address, - uint8_t prefix_length); +static inline int get_last_ip_address(sc_ipv4_addr* last_ip_address, + const sc_ipv4_addr* first_ip_address, + uint8_t prefix_length) +{ + return get_network_broadcast(last_ip_address, first_ip_address, + prefix_length); +} #endif /* __SYS_UTIL_H__ */ diff --git a/src/plugins/yang/ietf-interfaces.data.xml b/src/plugins/yang/ietf-interfaces.data.xml deleted file mode 100644 index 3aae96e..0000000 --- a/src/plugins/yang/ietf-interfaces.data.xml +++ /dev/null @@ -1,21 +0,0 @@ -<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"> - <interface> - <name>GigabitEthernet0/8/0</name> - <description>Ethernet 8</description> - <type>ethernetCsmacd</type> - <enabled>true</enabled> - <ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"> - <address> - <ip>192.168.2.100</ip> - <prefix-length>24</prefix-length> - </address> - </ipv4> - <ipv6 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"> - <address> - <ip>2001:db8::10</ip> - <prefix-length>32</prefix-length> - </address> - </ipv6> - </interface> -</interfaces> - diff --git a/src/plugins/yang/ietf/iana-if-type@2017-01-19.yang b/src/plugins/yang/ietf/iana-if-type@2017-01-19.yang new file mode 100644 index 0000000..7bfee36 --- /dev/null +++ b/src/plugins/yang/ietf/iana-if-type@2017-01-19.yang @@ -0,0 +1,1619 @@ +module iana-if-type { + namespace "urn:ietf:params:xml:ns:yang:iana-if-type"; + prefix ianaift; + + import ietf-interfaces { + prefix if; + } + + organization "IANA"; + contact + " Internet Assigned Numbers Authority + + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States + + Tel: +1 310 301 5800 + <mailto:iana&iana.org>"; + description + "This YANG module defines YANG identities for IANA-registered + interface types. + + This YANG module is maintained by IANA and reflects the + 'ifType definitions' registry. + + The latest revision of this YANG module can be obtained from + the IANA web site. + + Requests for new values should be made to IANA via + email (iana&iana.org). + + Copyright (c) 2014 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + The initial version of this YANG module is part of RFC 7224; + see the RFC itself for full legal notices."; + reference + "IANA 'ifType definitions' registry. + <http://www.iana.org/assignments/smi-numbers>"; + + revision 2017-01-19 { + description + "Registered ifType 289."; + } + + revision 2016-11-23 { + description + "Registered ifTypes 283-288."; + } + + revision 2016-06-09 { + description + "Registered ifType 282."; + } + revision 2016-05-03 { + description + "Registered ifType 281."; + } + revision 2015-06-12 { + description + "Corrected formatting issue."; + } + revision 2014-09-24 { + description + "Registered ifType 280."; + } + revision 2014-09-19 { + description + "Registered ifType 279."; + } + revision 2014-07-03 { + description + "Registered ifTypes 277-278."; + } + revision 2014-05-19 { + description + "Updated the contact address."; + } + revision 2014-05-08 { + description + "Initial revision."; + reference + "RFC 7224: IANA Interface Type YANG Module"; + } + + identity iana-interface-type { + base if:interface-type; + description + "This identity is used as a base for all interface types + defined in the 'ifType definitions' registry."; + } + + identity other { + base iana-interface-type; + } + identity regular1822 { + base iana-interface-type; + } + identity hdh1822 { + base iana-interface-type; + } + identity ddnX25 { + base iana-interface-type; + } + identity rfc877x25 { + base iana-interface-type; + reference + "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer"; + } + identity ethernetCsmacd { + base iana-interface-type; + description + "For all Ethernet-like interfaces, regardless of speed, + as per RFC 3635."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88023Csmacd { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity iso88024TokenBus { + base iana-interface-type; + } + identity iso88025TokenRing { + base iana-interface-type; + } + identity iso88026Man { + base iana-interface-type; + } + identity starLan { + base iana-interface-type; + status deprecated; + description + "Deprecated via RFC 3635. + Use ethernetCsmacd(6) instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity proteon10Mbit { + base iana-interface-type; + } + identity proteon80Mbit { + base iana-interface-type; + } + identity hyperchannel { + base iana-interface-type; + } + identity fddi { + base iana-interface-type; + reference + "RFC 1512 - FDDI Management Information Base"; + } + identity lapb { + base iana-interface-type; + reference + "RFC 1381 - SNMP MIB Extension for X.25 LAPB"; + } + identity sdlc { + base iana-interface-type; + } + identity ds1 { + base iana-interface-type; + description + "DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity e1 { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + reference + "RFC 4805 - Definitions of Managed Objects for the + DS1, J1, E1, DS2, and E2 Interface Types"; + } + identity basicISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity primaryISDN { + base iana-interface-type; + description + "No longer used. See also RFC 2127."; + } + identity propPointToPointSerial { + base iana-interface-type; + description + "Proprietary serial."; + } + identity ppp { + base iana-interface-type; + } + identity softwareLoopback { + base iana-interface-type; + } + identity eon { + base iana-interface-type; + description + "CLNP over IP."; + } + identity ethernet3Mbit { + base iana-interface-type; + } + identity nsip { + base iana-interface-type; + description + "XNS over IP."; + } + identity slip { + base iana-interface-type; + description + "Generic SLIP."; + } + identity ultra { + base iana-interface-type; + description + "Ultra Technologies."; + } + identity ds3 { + base iana-interface-type; + description + "DS3-MIB."; + reference + "RFC 3896 - Definitions of Managed Objects for the + DS3/E3 Interface Type"; + } + identity sip { + base iana-interface-type; + description + "SMDS, coffee."; + reference + "RFC 1694 - Definitions of Managed Objects for SMDS + Interfaces using SMIv2"; + } + identity frameRelay { + base iana-interface-type; + description + "DTE only."; + reference + "RFC 2115 - Management Information Base for Frame Relay + DTEs Using SMIv2"; + } + identity rs232 { + base iana-interface-type; + reference + "RFC 1659 - Definitions of Managed Objects for RS-232-like + Hardware Devices using SMIv2"; + } + identity para { + base iana-interface-type; + description + "Parallel-port."; + reference + "RFC 1660 - Definitions of Managed Objects for + Parallel-printer-like Hardware Devices using + SMIv2"; + } + identity arcnet { + base iana-interface-type; + description + "ARCnet."; + } + identity arcnetPlus { + base iana-interface-type; + description + "ARCnet Plus."; + } + identity atm { + base iana-interface-type; + description + "ATM cells."; + } + identity miox25 { + base iana-interface-type; + reference + "RFC 1461 - SNMP MIB extension for Multiprotocol + Interconnect over X.25"; + } + identity sonet { + base iana-interface-type; + description + "SONET or SDH."; + } + identity x25ple { + base iana-interface-type; + reference + "RFC 2127 - ISDN Management Information Base using SMIv2"; + } + identity iso88022llc { + base iana-interface-type; + } + identity localTalk { + base iana-interface-type; + } + identity smdsDxi { + base iana-interface-type; + } + identity frameRelayService { + base iana-interface-type; + description + "FRNETSERV-MIB."; + reference + "RFC 2954 - Definitions of Managed Objects for Frame + Relay Service"; + } + identity v35 { + base iana-interface-type; + } + identity hssi { + base iana-interface-type; + } + identity hippi { + base iana-interface-type; + } + identity modem { + base iana-interface-type; + description + "Generic modem."; + } + identity aal5 { + base iana-interface-type; + description + "AAL5 over ATM."; + } + identity sonetPath { + base iana-interface-type; + } + identity sonetVT { + base iana-interface-type; + } + identity smdsIcip { + base iana-interface-type; + description + "SMDS InterCarrier Interface."; + } + identity propVirtual { + base iana-interface-type; + description + "Proprietary virtual/internal."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity propMultiplexor { + base iana-interface-type; + description + "Proprietary multiplexing."; + reference + "RFC 2863 - The Interfaces Group MIB"; + } + identity ieee80212 { + base iana-interface-type; + description + "100BaseVG."; + } + identity fibreChannel { + base iana-interface-type; + description + "Fibre Channel."; + } + identity hippiInterface { + base iana-interface-type; + description + "HIPPI interfaces."; + } + identity frameRelayInterconnect { + base iana-interface-type; + status obsolete; + description + "Obsolete; use either + frameRelay(32) or frameRelayService(44)."; + } + identity aflane8023 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.3."; + } + identity aflane8025 { + base iana-interface-type; + description + "ATM Emulated LAN for 802.5."; + } + identity cctEmul { + base iana-interface-type; + description + "ATM Emulated circuit."; + } + identity fastEther { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity isdn { + base iana-interface-type; + description + "ISDN and X.25."; + reference + "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN + in the Packet Mode"; + } + identity v11 { + base iana-interface-type; + description + "CCITT V.11/X.21."; + } + identity v36 { + base iana-interface-type; + description + "CCITT V.36."; + } + identity g703at64k { + base iana-interface-type; + description + "CCITT G703 at 64Kbps."; + } + identity g703at2mb { + base iana-interface-type; + status obsolete; + description + "Obsolete; see DS1-MIB."; + } + identity qllc { + base iana-interface-type; + description + "SNA QLLC."; + } + identity fastEtherFX { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity channel { + base iana-interface-type; + description + "Channel."; + } + identity ieee80211 { + base iana-interface-type; + description + "Radio spread spectrum."; + } + identity ibm370parChan { + base iana-interface-type; + description + "IBM System 360/370 OEMI Channel."; + } + identity escon { + base iana-interface-type; + description + "IBM Enterprise Systems Connection."; + } + identity dlsw { + base iana-interface-type; + description + "Data Link Switching."; + } + identity isdns { + base iana-interface-type; + description + "ISDN S/T interface."; + } + identity isdnu { + base iana-interface-type; + description + "ISDN U interface."; + } + identity lapd { + base iana-interface-type; + description + "Link Access Protocol D."; + } + identity ipSwitch { + base iana-interface-type; + description + "IP Switching Objects."; + } + identity rsrb { + base iana-interface-type; + description + "Remote Source Route Bridging."; + } + identity atmLogical { + base iana-interface-type; + description + "ATM Logical Port."; + reference + "RFC 3606 - Definitions of Supplemental Managed Objects + for ATM Interface"; + } + identity ds0 { + base iana-interface-type; + description + "Digital Signal Level 0."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity ds0Bundle { + base iana-interface-type; + description + "Group of ds0s on the same ds1."; + reference + "RFC 2494 - Definitions of Managed Objects for the DS0 + and DS0 Bundle Interface Type"; + } + identity bsc { + base iana-interface-type; + description + "Bisynchronous Protocol."; + } + identity async { + base iana-interface-type; + description + "Asynchronous Protocol."; + } + identity cnr { + base iana-interface-type; + description + "Combat Net Radio."; + } + identity iso88025Dtr { + base iana-interface-type; + description + "ISO 802.5r DTR."; + } + identity eplrs { + base iana-interface-type; + description + "Ext Pos Loc Report Sys."; + } + identity arap { + base iana-interface-type; + description + "Appletalk Remote Access Protocol."; + } + identity propCnls { + base iana-interface-type; + description + "Proprietary Connectionless Protocol."; + } + identity hostPad { + base iana-interface-type; + description + "CCITT-ITU X.29 PAD Protocol."; + } + identity termPad { + base iana-interface-type; + description + "CCITT-ITU X.3 PAD Facility."; + } + identity frameRelayMPI { + base iana-interface-type; + description + "Multiproto Interconnect over FR."; + } + identity x213 { + base iana-interface-type; + description + "CCITT-ITU X213."; + } + identity adsl { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop."; + } + identity radsl { + base iana-interface-type; + description + "Rate-Adapt. Digital Subscriber Loop."; + } + identity sdsl { + base iana-interface-type; + description + "Symmetric Digital Subscriber Loop."; + } + identity vdsl { + base iana-interface-type; + description + "Very H-Speed Digital Subscrib. Loop."; + } + identity iso88025CRFPInt { + base iana-interface-type; + description + "ISO 802.5 CRFP."; + } + identity myrinet { + base iana-interface-type; + description + "Myricom Myrinet."; + } + identity voiceEM { + base iana-interface-type; + description + "Voice recEive and transMit."; + } + identity voiceFXO { + base iana-interface-type; + description + "Voice Foreign Exchange Office."; + } + identity voiceFXS { + base iana-interface-type; + description + "Voice Foreign Exchange Station."; + } + identity voiceEncap { + base iana-interface-type; + description + "Voice encapsulation."; + } + identity voiceOverIp { + base iana-interface-type; + description + "Voice over IP encapsulation."; + } + identity atmDxi { + base iana-interface-type; + description + "ATM DXI."; + } + identity atmFuni { + base iana-interface-type; + description + "ATM FUNI."; + } + identity atmIma { + base iana-interface-type; + description + "ATM IMA."; + } + identity pppMultilinkBundle { + base iana-interface-type; + description + "PPP Multilink Bundle."; + } + identity ipOverCdlc { + base iana-interface-type; + description + "IBM ipOverCdlc."; + } + identity ipOverClaw { + base iana-interface-type; + description + "IBM Common Link Access to Workstn."; + } + identity stackToStack { + base iana-interface-type; + description + "IBM stackToStack."; + } + identity virtualIpAddress { + base iana-interface-type; + description + "IBM VIPA."; + } + identity mpc { + base iana-interface-type; + description + "IBM multi-protocol channel support."; + } + identity ipOverAtm { + base iana-interface-type; + description + "IBM ipOverAtm."; + reference + "RFC 2320 - Definitions of Managed Objects for Classical IP + and ARP Over ATM Using SMIv2 (IPOA-MIB)"; + } + identity iso88025Fiber { + base iana-interface-type; + description + "ISO 802.5j Fiber Token Ring."; + } + identity tdlc { + base iana-interface-type; + description + "IBM twinaxial data link control."; + } + identity gigabitEthernet { + base iana-interface-type; + status deprecated; + description + "Obsoleted via RFC 3635. + ethernetCsmacd(6) should be used instead."; + reference + "RFC 3635 - Definitions of Managed Objects for the + Ethernet-like Interface Types"; + } + identity hdlc { + base iana-interface-type; + description + "HDLC."; + } + identity lapf { + base iana-interface-type; + description + "LAP F."; + } + identity v37 { + base iana-interface-type; + description + "V.37."; + } + identity x25mlp { + base iana-interface-type; + description + "Multi-Link Protocol."; + } + identity x25huntGroup { + base iana-interface-type; + description + "X25 Hunt Group."; + } + identity transpHdlc { + base iana-interface-type; + description + "Transp HDLC."; + } + identity interleave { + base iana-interface-type; + description + "Interleave channel."; + } + identity fast { + base iana-interface-type; + description + "Fast channel."; + } + identity ip { + base iana-interface-type; + description + "IP (for APPN HPR in IP networks)."; + } + identity docsCableMaclayer { + base iana-interface-type; + description + "CATV Mac Layer."; + } + identity docsCableDownstream { + base iana-interface-type; + description + "CATV Downstream interface."; + } + identity docsCableUpstream { + base iana-interface-type; + description + "CATV Upstream interface."; + } + identity a12MppSwitch { + base iana-interface-type; + description + "Avalon Parallel Processor."; + } + identity tunnel { + base iana-interface-type; + description + "Encapsulation interface."; + } + identity coffee { + base iana-interface-type; + description + "Coffee pot."; + reference + "RFC 2325 - Coffee MIB"; + } + identity ces { + base iana-interface-type; + description + "Circuit Emulation Service."; + } + identity atmSubInterface { + base iana-interface-type; + description + "ATM Sub Interface."; + } + identity l2vlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using 802.1Q."; + } + identity l3ipvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IP."; + } + identity l3ipxvlan { + base iana-interface-type; + description + "Layer 3 Virtual LAN using IPX."; + } + identity digitalPowerline { + base iana-interface-type; + description + "IP over Power Lines."; + } + identity mediaMailOverIp { + base iana-interface-type; + description + "Multimedia Mail over IP."; + } + identity dtm { + base iana-interface-type; + description + "Dynamic synchronous Transfer Mode."; + } + identity dcn { + base iana-interface-type; + description + "Data Communications Network."; + } + identity ipForward { + base iana-interface-type; + description + "IP Forwarding Interface."; + } + identity msdsl { + base iana-interface-type; + description + "Multi-rate Symmetric DSL."; + } + identity ieee1394 { + base iana-interface-type; + + description + "IEEE1394 High Performance Serial Bus."; + } + identity if-gsn { + base iana-interface-type; + description + "HIPPI-6400."; + } + identity dvbRccMacLayer { + base iana-interface-type; + description + "DVB-RCC MAC Layer."; + } + identity dvbRccDownstream { + base iana-interface-type; + description + "DVB-RCC Downstream Channel."; + } + identity dvbRccUpstream { + base iana-interface-type; + description + "DVB-RCC Upstream Channel."; + } + identity atmVirtual { + base iana-interface-type; + description + "ATM Virtual Interface."; + } + identity mplsTunnel { + base iana-interface-type; + description + "MPLS Tunnel Virtual Interface."; + } + identity srp { + base iana-interface-type; + description + "Spatial Reuse Protocol."; + } + identity voiceOverAtm { + base iana-interface-type; + description + "Voice over ATM."; + } + identity voiceOverFrameRelay { + base iana-interface-type; + description + "Voice Over Frame Relay."; + } + identity idsl { + base iana-interface-type; + description + "Digital Subscriber Loop over ISDN."; + } + identity compositeLink { + base iana-interface-type; + description + "Avici Composite Link Interface."; + } + identity ss7SigLink { + base iana-interface-type; + description + "SS7 Signaling Link."; + } + identity propWirelessP2P { + base iana-interface-type; + description + "Prop. P2P wireless interface."; + } + identity frForward { + base iana-interface-type; + description + "Frame Forward Interface."; + } + identity rfc1483 { + base iana-interface-type; + description + "Multiprotocol over ATM AAL5."; + reference + "RFC 1483 - Multiprotocol Encapsulation over ATM + Adaptation Layer 5"; + } + identity usb { + base iana-interface-type; + description + "USB Interface."; + } + identity ieee8023adLag { + base iana-interface-type; + description + "IEEE 802.3ad Link Aggregate."; + } + identity bgppolicyaccounting { + base iana-interface-type; + description + "BGP Policy Accounting."; + } + identity frf16MfrBundle { + base iana-interface-type; + description + "FRF.16 Multilink Frame Relay."; + } + identity h323Gatekeeper { + base iana-interface-type; + description + "H323 Gatekeeper."; + } + identity h323Proxy { + base iana-interface-type; + description + "H323 Voice and Video Proxy."; + } + identity mpls { + base iana-interface-type; + description + "MPLS."; + } + identity mfSigLink { + base iana-interface-type; + description + "Multi-frequency signaling link."; + } + identity hdsl2 { + base iana-interface-type; + description + "High Bit-Rate DSL - 2nd generation."; + } + identity shdsl { + base iana-interface-type; + description + "Multirate HDSL2."; + } + identity ds1FDL { + base iana-interface-type; + description + "Facility Data Link (4Kbps) on a DS1."; + } + identity pos { + base iana-interface-type; + description + "Packet over SONET/SDH Interface."; + } + identity dvbAsiIn { + base iana-interface-type; + description + "DVB-ASI Input."; + } + identity dvbAsiOut { + base iana-interface-type; + description + "DVB-ASI Output."; + } + identity plc { + base iana-interface-type; + description + "Power Line Communications."; + } + identity nfas { + base iana-interface-type; + description + "Non-Facility Associated Signaling."; + } + identity tr008 { + base iana-interface-type; + description + "TR008."; + } + identity gr303RDT { + base iana-interface-type; + description + "Remote Digital Terminal."; + } + identity gr303IDT { + base iana-interface-type; + description + "Integrated Digital Terminal."; + } + identity isup { + base iana-interface-type; + description + "ISUP."; + } + identity propDocsWirelessMaclayer { + base iana-interface-type; + description + "Cisco proprietary Maclayer."; + } + identity propDocsWirelessDownstream { + base iana-interface-type; + description + "Cisco proprietary Downstream."; + } + identity propDocsWirelessUpstream { + base iana-interface-type; + description + "Cisco proprietary Upstream."; + } + identity hiperlan2 { + base iana-interface-type; + description + "HIPERLAN Type 2 Radio Interface."; + } + identity propBWAp2Mp { + base iana-interface-type; + description + "PropBroadbandWirelessAccesspt2Multipt (use of this value + for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f + is deprecated, and ieee80216WMAN(237) should be used + instead)."; + } + identity sonetOverheadChannel { + base iana-interface-type; + description + "SONET Overhead Channel."; + } + identity digitalWrapperOverheadChannel { + base iana-interface-type; + description + "Digital Wrapper."; + } + identity aal2 { + base iana-interface-type; + description + "ATM adaptation layer 2."; + } + identity radioMAC { + base iana-interface-type; + description + "MAC layer over radio links."; + } + identity atmRadio { + base iana-interface-type; + description + "ATM over radio links."; + } + identity imt { + base iana-interface-type; + description + "Inter-Machine Trunks."; + } + identity mvl { + base iana-interface-type; + description + "Multiple Virtual Lines DSL."; + } + identity reachDSL { + base iana-interface-type; + description + "Long Reach DSL."; + } + identity frDlciEndPt { + base iana-interface-type; + description + "Frame Relay DLCI End Point."; + } + identity atmVciEndPt { + base iana-interface-type; + description + "ATM VCI End Point."; + } + identity opticalChannel { + base iana-interface-type; + description + "Optical Channel."; + } + identity opticalTransport { + base iana-interface-type; + description + "Optical Transport."; + } + identity propAtm { + base iana-interface-type; + description + "Proprietary ATM."; + } + identity voiceOverCable { + base iana-interface-type; + description + "Voice Over Cable Interface."; + } + identity infiniband { + base iana-interface-type; + description + "Infiniband."; + } + identity teLink { + base iana-interface-type; + description + "TE Link."; + } + identity q2931 { + base iana-interface-type; + description + "Q.2931."; + } + identity virtualTg { + base iana-interface-type; + description + "Virtual Trunk Group."; + } + identity sipTg { + base iana-interface-type; + description + "SIP Trunk Group."; + } + identity sipSig { + base iana-interface-type; + description + "SIP Signaling."; + } + identity docsCableUpstreamChannel { + base iana-interface-type; + description + "CATV Upstream Channel."; + } + identity econet { + base iana-interface-type; + description + "Acorn Econet."; + } + identity pon155 { + base iana-interface-type; + description + "FSAN 155Mb Symetrical PON interface."; + } + identity pon622 { + base iana-interface-type; + description + "FSAN 622Mb Symetrical PON interface."; + } + identity bridge { + base iana-interface-type; + description + "Transparent bridge interface."; + } + identity linegroup { + base iana-interface-type; + description + "Interface common to multiple lines."; + } + identity voiceEMFGD { + base iana-interface-type; + description + "Voice E&M Feature Group D."; + } + identity voiceFGDEANA { + base iana-interface-type; + description + "Voice FGD Exchange Access North American."; + } + identity voiceDID { + base iana-interface-type; + description + "Voice Direct Inward Dialing."; + } + identity mpegTransport { + base iana-interface-type; + description + "MPEG transport interface."; + } + identity sixToFour { + base iana-interface-type; + status deprecated; + description + "6to4 interface (DEPRECATED)."; + reference + "RFC 4087 - IP Tunnel MIB"; + } + identity gtp { + base iana-interface-type; + description + "GTP (GPRS Tunneling Protocol)."; + } + identity pdnEtherLoop1 { + base iana-interface-type; + description + "Paradyne EtherLoop 1."; + } + identity pdnEtherLoop2 { + base iana-interface-type; + description + "Paradyne EtherLoop 2."; + } + identity opticalChannelGroup { + base iana-interface-type; + description + "Optical Channel Group."; + } + identity homepna { + base iana-interface-type; + description + "HomePNA ITU-T G.989."; + } + identity gfp { + base iana-interface-type; + description + "Generic Framing Procedure (GFP)."; + } + identity ciscoISLvlan { + base iana-interface-type; + description + "Layer 2 Virtual LAN using Cisco ISL."; + } + identity actelisMetaLOOP { + base iana-interface-type; + description + "Acteleis proprietary MetaLOOP High Speed Link."; + } + identity fcipLink { + base iana-interface-type; + description + "FCIP Link."; + } + identity rpr { + base iana-interface-type; + description + "Resilient Packet Ring Interface Type."; + } + identity qam { + base iana-interface-type; + description + "RF Qam Interface."; + } + identity lmp { + base iana-interface-type; + description + "Link Management Protocol."; + reference + "RFC 4327 - Link Management Protocol (LMP) Management + Information Base (MIB)"; + } + identity cblVectaStar { + base iana-interface-type; + description + "Cambridge Broadband Networks Limited VectaStar."; + } + identity docsCableMCmtsDownstream { + base iana-interface-type; + description + "CATV Modular CMTS Downstream Interface."; + } + identity adsl2 { + base iana-interface-type; + status deprecated; + description + "Asymmetric Digital Subscriber Loop Version 2 + (DEPRECATED/OBSOLETED - please use adsl2plus(238) + instead)."; + reference + "RFC 4706 - Definitions of Managed Objects for Asymmetric + Digital Subscriber Line 2 (ADSL2)"; + } + identity macSecControlledIF { + base iana-interface-type; + description + "MACSecControlled."; + } + identity macSecUncontrolledIF { + base iana-interface-type; + description + "MACSecUncontrolled."; + } + identity aviciOpticalEther { + base iana-interface-type; + description + "Avici Optical Ethernet Aggregate."; + } + identity atmbond { + base iana-interface-type; + description + "atmbond."; + } + identity voiceFGDOS { + base iana-interface-type; + description + "Voice FGD Operator Services."; + } + identity mocaVersion1 { + base iana-interface-type; + description + "MultiMedia over Coax Alliance (MoCA) Interface + as documented in information provided privately to IANA."; + } + identity ieee80216WMAN { + base iana-interface-type; + description + "IEEE 802.16 WMAN interface."; + } + identity adsl2plus { + base iana-interface-type; + description + "Asymmetric Digital Subscriber Loop Version 2 - + Version 2 Plus and all variants."; + } + identity dvbRcsMacLayer { + base iana-interface-type; + description + "DVB-RCS MAC Layer."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbTdm { + base iana-interface-type; + description + "DVB Satellite TDM."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity dvbRcsTdma { + base iana-interface-type; + description + "DVB-RCS TDMA."; + reference + "RFC 5728 - The SatLabs Group DVB-RCS MIB"; + } + identity x86Laps { + base iana-interface-type; + description + "LAPS based on ITU-T X.86/Y.1323."; + } + identity wwanPP { + base iana-interface-type; + description + "3GPP WWAN."; + } + identity wwanPP2 { + base iana-interface-type; + description + "3GPP2 WWAN."; + } + identity voiceEBS { + base iana-interface-type; + description + "Voice P-phone EBS physical interface."; + } + identity ifPwType { + base iana-interface-type; + description + "Pseudowire interface type."; + reference + "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)"; + } + identity ilan { + base iana-interface-type; + description + "Internal LAN on a bridge per IEEE 802.1ap."; + } + identity pip { + base iana-interface-type; + description + "Provider Instance Port on a bridge per IEEE 802.1ah PBB."; + } + identity aluELP { + base iana-interface-type; + description + "Alcatel-Lucent Ethernet Link Protection."; + } + identity gpon { + base iana-interface-type; + description + "Gigabit-capable passive optical networks (G-PON) as per + ITU-T G.948."; + } + identity vdsl2 { + base iana-interface-type; + description + "Very high speed digital subscriber line Version 2 + (as per ITU-T Recommendation G.993.2)."; + reference + "RFC 5650 - Definitions of Managed Objects for Very High + Speed Digital Subscriber Line 2 (VDSL2)"; + } + identity capwapDot11Profile { + base iana-interface-type; + description + "WLAN Profile Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapDot11Bss { + base iana-interface-type; + description + "WLAN BSS Interface."; + reference + "RFC 5834 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Binding MIB for + IEEE 802.11"; + } + identity capwapWtpVirtualRadio { + base iana-interface-type; + description + "WTP Virtual Radio Interface."; + reference + "RFC 5833 - Control and Provisioning of Wireless Access + Points (CAPWAP) Protocol Base MIB"; + } + identity bits { + base iana-interface-type; + description + "bitsport."; + } + identity docsCableUpstreamRfPort { + base iana-interface-type; + description + "DOCSIS CATV Upstream RF Port."; + } + identity cableDownstreamRfPort { + base iana-interface-type; + description + "CATV downstream RF Port."; + } + identity vmwareVirtualNic { + base iana-interface-type; + description + "VMware Virtual Network Interface."; + } + identity ieee802154 { + base iana-interface-type; + description + "IEEE 802.15.4 WPAN interface."; + reference + "IEEE 802.15.4-2006"; + } + identity otnOdu { + base iana-interface-type; + description + "OTN Optical Data Unit."; + } + identity otnOtu { + base iana-interface-type; + description + "OTN Optical channel Transport Unit."; + } + identity ifVfiType { + base iana-interface-type; + description + "VPLS Forwarding Instance Interface Type."; + } + identity g9981 { + base iana-interface-type; + description + "G.998.1 bonded interface."; + } + identity g9982 { + base iana-interface-type; + description + "G.998.2 bonded interface."; + } + identity g9983 { + base iana-interface-type; + description + "G.998.3 bonded interface."; + } + + identity aluEpon { + base iana-interface-type; + description + "Ethernet Passive Optical Networks (E-PON)."; + } + identity aluEponOnu { + base iana-interface-type; + description + "EPON Optical Network Unit."; + } + identity aluEponPhysicalUni { + base iana-interface-type; + description + "EPON physical User to Network interface."; + } + identity aluEponLogicalLink { + base iana-interface-type; + description + "The emulation of a point-to-point link over the EPON + layer."; + } + identity aluGponOnu { + base iana-interface-type; + description + "GPON Optical Network Unit."; + reference + "ITU-T G.984.2"; + } + identity aluGponPhysicalUni { + base iana-interface-type; + description + "GPON physical User to Network interface."; + reference + "ITU-T G.984.2"; + } + identity vmwareNicTeam { + base iana-interface-type; + description + "VMware NIC Team."; + } + identity docsOfdmDownstream { + base iana-interface-type; + description + "CATV Downstream OFDM interface."; + } + identity docsOfdmaUpstream { + base iana-interface-type; + description + "CATV Upstream OFDMA interface."; + } + identity gfast { + base iana-interface-type; + description + "G.fast port."; + reference + "ITU-T G.9701"; + } + identity sdci { + base iana-interface-type; + description + "SDCI (IO-Link)."; + reference + "IEC 61131-9 Edition 1.0 2013-09"; + } + identity xboxWireless { + base iana-interface-type; + description + "Xbox wireless."; + } + identity fastdsl { + base iana-interface-type; + description + "FastDSL."; + reference + "BBF TR-355"; + } + identity docsCableScte55d1FwdOob { + base iana-interface-type; + description + "Cable SCTE 55-1 OOB Forward Channel."; + } + identity docsCableScte55d1RetOob { + base iana-interface-type; + description + "Cable SCTE 55-1 OOB Return Channel."; + } + identity docsCableScte55d2DsOob { + base iana-interface-type; + description + "Cable SCTE 55-2 OOB Downstream Channel."; + } + identity docsCableScte55d2UsOob { + base iana-interface-type; + description + "Cable SCTE 55-2 OOB Upstream Channel."; + } + identity docsCableNdf { + base iana-interface-type; + description + "Cable Narrowband Digital Forward."; + } + identity docsCableNdr { + base iana-interface-type; + description + "Cable Narrowband Digital Return."; + } + identity ptm { + base iana-interface-type; + description + "Packet Transfer Mode."; + } +} diff --git a/src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang b/src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang deleted file mode 100644 index a0eb30e..0000000 --- a/src/plugins/yang/ietf/ietf-interfaces@2014-05-08.yang +++ /dev/null @@ -1,707 +0,0 @@ -module ietf-interfaces { - - yang-version 1; - - namespace - "urn:ietf:params:xml:ns:yang:ietf-interfaces"; - - prefix if; - - import ietf-yang-types { - prefix yang; - } - - organization - "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; - - contact - "WG Web: <http://tools.ietf.org/wg/netmod/> - WG List: <mailto:netmod@ietf.org> - - WG Chair: Thomas Nadeau - <mailto:tnadeau@lucidvision.com> - - WG Chair: Juergen Schoenwaelder - <mailto:j.schoenwaelder@jacobs-university.de> - - Editor: Martin Bjorklund - <mailto:mbj@tail-f.com>"; - - description - "This module contains a collection of YANG definitions for - managing network interfaces. - - Copyright (c) 2014 IETF Trust and the persons identified as - authors of the code. All rights reserved. - - Redistribution and use in source and binary forms, with or - without modification, is permitted pursuant to, and subject - to the license terms contained in, the Simplified BSD License - set forth in Section 4.c of the IETF Trust's Legal Provisions - Relating to IETF Documents - (http://trustee.ietf.org/license-info). - - This version of this YANG module is part of RFC 7223; see - the RFC itself for full legal notices."; - - revision "2014-05-08" { - description "Initial revision."; - reference - "RFC 7223: A YANG Data Model for Interface Management"; - - } - - - typedef interface-ref { - type leafref { - path "/if:interfaces/if:interface/if:name"; - } - description - "This type is used by data models that need to reference - configured interfaces."; - } - - typedef interface-state-ref { - type leafref { - path "/if:interfaces-state/if:interface/if:name"; - } - description - "This type is used by data models that need to reference - the operationally present interfaces."; - } - - identity interface-type { - description - "Base identity from which specific interface types are - derived."; - } - - feature arbitrary-names { - description - "This feature indicates that the device allows user-controlled - interfaces to be named arbitrarily."; - } - - feature pre-provisioning { - description - "This feature indicates that the device supports - pre-provisioning of interface configuration, i.e., it is - possible to configure an interface whose physical interface - hardware is not present on the device."; - } - - feature if-mib { - description - "This feature indicates that the device implements - the IF-MIB."; - reference - "RFC 2863: The Interfaces Group MIB"; - - } - - container interfaces { - description - "Interface configuration parameters."; - list interface { - key "name"; - description - "The list of configured interfaces on the device. - - The operational state of an interface is available in the - /interfaces-state/interface list. If the configuration of a - system-controlled interface cannot be used by the system - (e.g., the interface hardware present does not match the - interface type), then the configuration is not applied to - the system-controlled interface shown in the - /interfaces-state/interface list. If the configuration - of a user-controlled interface cannot be used by the system, - the configured interface is not instantiated in the - /interfaces-state/interface list."; - leaf name { - type string; - description - "The name of the interface. - - A device MAY restrict the allowed values for this leaf, - possibly depending on the type of the interface. - For system-controlled interfaces, this leaf is the - device-specific name of the interface. The 'config false' - list /interfaces-state/interface contains the currently - existing interfaces on the device. - - If a client tries to create configuration for a - system-controlled interface that is not present in the - /interfaces-state/interface list, the server MAY reject - the request if the implementation does not support - pre-provisioning of interfaces or if the name refers to - an interface that can never exist in the system. A - NETCONF server MUST reply with an rpc-error with the - error-tag 'invalid-value' in this case. - - If the device supports pre-provisioning of interface - configuration, the 'pre-provisioning' feature is - advertised. - - If the device allows arbitrarily named user-controlled - interfaces, the 'arbitrary-names' feature is advertised. - - When a configured user-controlled interface is created by - the system, it is instantiated with the same name in the - /interface-state/interface list."; - } - - leaf description { - type string; - description - "A textual description of the interface. - - A server implementation MAY map this leaf to the ifAlias - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and ifAlias. The definition of - such a mechanism is outside the scope of this document. - - Since ifAlias is defined to be stored in non-volatile - storage, the MIB implementation MUST map ifAlias to the - value of 'description' in the persistently stored - datastore. - - Specifically, if the device supports ':startup', when - ifAlias is read the device MUST return the value of - 'description' in the 'startup' datastore, and when it is - written, it MUST be written to the 'running' and 'startup' - datastores. Note that it is up to the implementation to - - decide whether to modify this single leaf in 'startup' or - perform an implicit copy-config from 'running' to - 'startup'. - - If the device does not support ':startup', ifAlias MUST - be mapped to the 'description' leaf in the 'running' - datastore."; - reference - "RFC 2863: The Interfaces Group MIB - ifAlias"; - - } - - leaf type { - type identityref { - base interface-type; - } - mandatory true; - description - "The type of the interface. - - When an interface entry is created, a server MAY - initialize the type leaf with a valid value, e.g., if it - is possible to derive the type from the name of the - interface. - - If a client tries to set the type of an interface to a - value that can never be used by the system, e.g., if the - type is not supported or if the type does not match the - name of the interface, the server MUST reject the request. - A NETCONF server MUST reply with an rpc-error with the - error-tag 'invalid-value' in this case."; - reference - "RFC 2863: The Interfaces Group MIB - ifType"; - - } - - leaf enabled { - type boolean; - default "true"; - description - "This leaf contains the configured, desired state of the - interface. - - Systems that implement the IF-MIB use the value of this - leaf in the 'running' datastore to set - IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry - has been initialized, as described in RFC 2863. - - - - Changes in this leaf in the 'running' datastore are - reflected in ifAdminStatus, but if ifAdminStatus is - changed over SNMP, this leaf is not affected."; - reference - "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; - - } - - leaf link-up-down-trap-enable { - if-feature if-mib; - type enumeration { - enum "enabled" { - value 1; - } - enum "disabled" { - value 2; - } - } - description - "Controls whether linkUp/linkDown SNMP notifications - should be generated for this interface. - - If this node is not configured, the value 'enabled' is - operationally used by the server for interfaces that do - not operate on top of any other interface (i.e., there are - no 'lower-layer-if' entries), and 'disabled' otherwise."; - reference - "RFC 2863: The Interfaces Group MIB - - ifLinkUpDownTrapEnable"; - - } - } // list interface - } // container interfaces - - container interfaces-state { - config false; - description - "Data nodes for the operational state of interfaces."; - list interface { - key "name"; - description - "The list of interfaces on the device. - - System-controlled interfaces created by the system are - always present in this list, whether they are configured or - not."; - leaf name { - type string; - description - "The name of the interface. - - A server implementation MAY map this leaf to the ifName - MIB object. Such an implementation needs to use some - mechanism to handle the differences in size and characters - allowed between this leaf and ifName. The definition of - such a mechanism is outside the scope of this document."; - reference - "RFC 2863: The Interfaces Group MIB - ifName"; - - } - - leaf type { - type identityref { - base interface-type; - } - mandatory true; - description - "The type of the interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifType"; - - } - - leaf admin-status { - if-feature if-mib; - type enumeration { - enum "up" { - value 1; - description - "Ready to pass packets."; - } - enum "down" { - value 2; - description - "Not ready to pass packets and not in some test mode."; - } - enum "testing" { - value 3; - description - "In some test mode."; - } - } - mandatory true; - description - "The desired state of the interface. - - This leaf has the same read semantics as ifAdminStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifAdminStatus"; - - } - - leaf oper-status { - type enumeration { - enum "up" { - value 1; - description - "Ready to pass packets."; - } - enum "down" { - value 2; - description - "The interface does not pass any packets."; - } - enum "testing" { - value 3; - description - "In some test mode. No operational packets can - be passed."; - } - enum "unknown" { - value 4; - description - "Status cannot be determined for some reason."; - } - enum "dormant" { - value 5; - description - "Waiting for some external event."; - } - enum "not-present" { - value 6; - description - "Some component (typically hardware) is missing."; - } - enum "lower-layer-down" { - value 7; - description - "Down due to state of lower-layer interface(s)."; - } - } - mandatory true; - description - "The current operational state of the interface. - - This leaf has the same semantics as ifOperStatus."; - reference - "RFC 2863: The Interfaces Group MIB - ifOperStatus"; - - } - - leaf last-change { - type yang:date-and-time; - description - "The time the interface entered its current operational - state. If the current state was entered prior to the - last re-initialization of the local network management - subsystem, then this node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - ifLastChange"; - - } - - leaf if-index { - if-feature if-mib; - type int32 { - range "1..2147483647"; - } - mandatory true; - description - "The ifIndex value for the ifEntry represented by this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifIndex"; - - } - - leaf phys-address { - type yang:phys-address; - description - "The interface's address at its protocol sub-layer. For - example, for an 802.x interface, this object normally - contains a Media Access Control (MAC) address. The - interface's media-specific modules must define the bit - - - and byte ordering and the format of the value of this - object. For interfaces that do not have such an address - (e.g., a serial line), this node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - ifPhysAddress"; - - } - - leaf-list higher-layer-if { - type interface-state-ref; - description - "A list of references to interfaces layered on top of this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifStackTable"; - - } - - leaf-list lower-layer-if { - type interface-state-ref; - description - "A list of references to interfaces layered underneath this - interface."; - reference - "RFC 2863: The Interfaces Group MIB - ifStackTable"; - - } - - leaf speed { - type yang:gauge64; - units "bits/second"; - description - "An estimate of the interface's current bandwidth in bits - per second. For interfaces that do not vary in - bandwidth or for those where no accurate estimation can - be made, this node should contain the nominal bandwidth. - For interfaces that have no concept of bandwidth, this - node is not present."; - reference - "RFC 2863: The Interfaces Group MIB - - ifSpeed, ifHighSpeed"; - - } - - container statistics { - description - "A collection of interface-related statistics objects."; - leaf discontinuity-time { - type yang:date-and-time; - mandatory true; - description - "The time on the most recent occasion at which any one or - more of this interface's counters suffered a - discontinuity. If no such discontinuities have occurred - since the last re-initialization of the local management - subsystem, then this node contains the time the local - management subsystem re-initialized itself."; - } - - leaf in-octets { - type yang:counter64; - description - "The total number of octets received on the interface, - including framing characters. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCInOctets"; - - } - - leaf in-unicast-pkts { - type yang:counter64; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were not addressed to a - multicast or broadcast address at this sub-layer. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts"; - - } - - leaf in-broadcast-pkts { - type yang:counter64; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were addressed to a broadcast - address at this sub-layer. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCInBroadcastPkts"; - - } - - leaf in-multicast-pkts { - type yang:counter64; - description - "The number of packets, delivered by this sub-layer to a - higher (sub-)layer, that were addressed to a multicast - address at this sub-layer. For a MAC-layer protocol, - this includes both Group and Functional addresses. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCInMulticastPkts"; - - } - - leaf in-discards { - type yang:counter32; - description - "The number of inbound packets that were chosen to be - discarded even though no errors had been detected to - prevent their being deliverable to a higher-layer - protocol. One possible reason for discarding such a - packet could be to free up buffer space. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInDiscards"; - - } - - leaf in-errors { - type yang:counter32; - description - "For packet-oriented interfaces, the number of inbound - packets that contained errors preventing them from being - deliverable to a higher-layer protocol. For character- - oriented or fixed-length interfaces, the number of - inbound transmission units that contained errors - preventing them from being deliverable to a higher-layer - protocol. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInErrors"; - - } - - leaf in-unknown-protos { - type yang:counter32; - description - "For packet-oriented interfaces, the number of packets - received via the interface that were discarded because - of an unknown or unsupported protocol. For - character-oriented or fixed-length interfaces that - support protocol multiplexing, the number of - transmission units received via the interface that were - discarded because of an unknown or unsupported protocol. - For any interface that does not support protocol - multiplexing, this counter is not present. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos"; - - } - - leaf out-octets { - type yang:counter64; - description - "The total number of octets transmitted out of the - interface, including framing characters. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCOutOctets"; - - } - - leaf out-unicast-pkts { - type yang:counter64; - description - "The total number of packets that higher-level protocols - requested be transmitted, and that were not addressed - to a multicast or broadcast address at this sub-layer, - including those that were discarded or not sent. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts"; - - } - - leaf out-broadcast-pkts { - type yang:counter64; - description - "The total number of packets that higher-level protocols - requested be transmitted, and that were addressed to a - broadcast address at this sub-layer, including those - that were discarded or not sent. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCOutBroadcastPkts"; - - } - - leaf out-multicast-pkts { - type yang:counter64; - description - "The total number of packets that higher-level protocols - requested be transmitted, and that were addressed to a - multicast address at this sub-layer, including those - that were discarded or not sent. For a MAC-layer - protocol, this includes both Group and Functional - addresses. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - - ifHCOutMulticastPkts"; - - } - - leaf out-discards { - type yang:counter32; - description - "The number of outbound packets that were chosen to be - discarded even though no errors had been detected to - prevent their being transmitted. One possible reason - for discarding such a packet could be to free up buffer - space. - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifOutDiscards"; - - } - - leaf out-errors { - type yang:counter32; - description - "For packet-oriented interfaces, the number of outbound - packets that could not be transmitted because of errors. - For character-oriented or fixed-length interfaces, the - number of outbound transmission units that could not be - transmitted because of errors. - - - - - Discontinuities in the value of this counter can occur - at re-initialization of the management system, and at - other times as indicated by the value of - 'discontinuity-time'."; - reference - "RFC 2863: The Interfaces Group MIB - ifOutErrors"; - - } - } // container statistics - } // list interface - } // container interfaces-state - } // module ietf-interfaces diff --git a/src/plugins/yang/ietf/ietf-interfaces.yang b/src/plugins/yang/ietf/ietf-interfaces@2018-02-20.yang index f66c205..f66c205 100644 --- a/src/plugins/yang/ietf/ietf-interfaces.yang +++ b/src/plugins/yang/ietf/ietf-interfaces@2018-02-20.yang diff --git a/src/plugins/yang/openconfig/openconfig-extensions.yang b/src/plugins/yang/openconfig/openconfig-extensions@2017-04-11.yang index f39ecf6..f39ecf6 100644 --- a/src/plugins/yang/openconfig/openconfig-extensions.yang +++ b/src/plugins/yang/openconfig/openconfig-extensions@2017-04-11.yang diff --git a/src/plugins/yang/openconfig/openconfig-if-aggregate.yang b/src/plugins/yang/openconfig/openconfig-if-aggregate@2018-03-23.yang index 5aa80bb..5aa80bb 100644 --- a/src/plugins/yang/openconfig/openconfig-if-aggregate.yang +++ b/src/plugins/yang/openconfig/openconfig-if-aggregate@2018-03-23.yang diff --git a/src/plugins/yang/openconfig/openconfig-if-ethernet.yang b/src/plugins/yang/openconfig/openconfig-if-ethernet@2018-09-04.yang index cd6b526..cd6b526 100644 --- a/src/plugins/yang/openconfig/openconfig-if-ethernet.yang +++ b/src/plugins/yang/openconfig/openconfig-if-ethernet@2018-09-04.yang diff --git a/src/plugins/yang/openconfig/openconfig-if-ip.yang b/src/plugins/yang/openconfig/openconfig-if-ip@2018-01-05.yang index a20e21c..a20e21c 100644 --- a/src/plugins/yang/openconfig/openconfig-if-ip.yang +++ b/src/plugins/yang/openconfig/openconfig-if-ip@2018-01-05.yang diff --git a/src/plugins/yang/openconfig/openconfig-if-types.yang b/src/plugins/yang/openconfig/openconfig-if-types@2018-01-05.yang index 3743878..3743878 100644 --- a/src/plugins/yang/openconfig/openconfig-if-types.yang +++ b/src/plugins/yang/openconfig/openconfig-if-types@2018-01-05.yang diff --git a/src/plugins/yang/openconfig/openconfig-inet-types.yang b/src/plugins/yang/openconfig/openconfig-inet-types@2017-08-24.yang index fbb872f..fbb872f 100644 --- a/src/plugins/yang/openconfig/openconfig-inet-types.yang +++ b/src/plugins/yang/openconfig/openconfig-inet-types@2017-08-24.yang diff --git a/src/plugins/yang/openconfig/openconfig-interfaces.yang b/src/plugins/yang/openconfig/openconfig-interfaces@2018-08-07.yang index d11e0b2..d11e0b2 100644 --- a/src/plugins/yang/openconfig/openconfig-interfaces.yang +++ b/src/plugins/yang/openconfig/openconfig-interfaces@2018-08-07.yang diff --git a/src/plugins/yang/openconfig/openconfig-local-routing.yang b/src/plugins/yang/openconfig/openconfig-local-routing@2017-05-15.yang index 5184fe7..5184fe7 100644 --- a/src/plugins/yang/openconfig/openconfig-local-routing.yang +++ b/src/plugins/yang/openconfig/openconfig-local-routing@2017-05-15.yang diff --git a/src/plugins/yang/openconfig/openconfig-policy-types.yang b/src/plugins/yang/openconfig/openconfig-policy-types@2018-06-05.yang index ef47f33..ef47f33 100644 --- a/src/plugins/yang/openconfig/openconfig-policy-types.yang +++ b/src/plugins/yang/openconfig/openconfig-policy-types@2018-06-05.yang diff --git a/src/plugins/yang/openconfig/openconfig-types.yang b/src/plugins/yang/openconfig/openconfig-types@2018-05-05.yang index 01713b3..01713b3 100644 --- a/src/plugins/yang/openconfig/openconfig-types.yang +++ b/src/plugins/yang/openconfig/openconfig-types@2018-05-05.yang diff --git a/src/plugins/yang/openconfig/openconfig-vlan-types.yang b/src/plugins/yang/openconfig/openconfig-vlan-types@2018-02-14.yang index 6d9ab55..6d9ab55 100644 --- a/src/plugins/yang/openconfig/openconfig-vlan-types.yang +++ b/src/plugins/yang/openconfig/openconfig-vlan-types@2018-02-14.yang diff --git a/src/plugins/yang/openconfig/openconfig-vlan.yang b/src/plugins/yang/openconfig/openconfig-vlan@2018-06-05.yang index 97348c0..97348c0 100644 --- a/src/plugins/yang/openconfig/openconfig-vlan.yang +++ b/src/plugins/yang/openconfig/openconfig-vlan@2018-06-05.yang diff --git a/src/plugins/yang/openconfig/openconfig-yang-types.yang b/src/plugins/yang/openconfig/openconfig-yang-types@2018-04-24.yang index b3b2c16..b3b2c16 100644 --- a/src/plugins/yang/openconfig/openconfig-yang-types.yang +++ b/src/plugins/yang/openconfig/openconfig-yang-types@2018-04-24.yang diff --git a/src/scvpp/CMakeLists.txt b/src/scvpp/CMakeLists.txt index 2dc42d6..8d04085 100644 --- a/src/scvpp/CMakeLists.txt +++ b/src/scvpp/CMakeLists.txt @@ -16,8 +16,57 @@ cmake_minimum_required(VERSION 2.8) project(scvpp) -# DEPENDENCIES -############## +# COMPILER & LINKER +################### + +# scvpp sources +set(SCVPP_SOURCES + src/comm.c + src/interface.c + src/ip.c + src/v3po.c + src/nat.c +) + +# scvpp public headers +set(SCVPP_HEADERS + inc/scvpp/comm.h + inc/scvpp/interface.h + inc/scvpp/ip.h + inc/scvpp/v3po.h + inc/scvpp/nat.h +) + +#define CMAKE_INSTALL_LIBDIR/INCLUDEDIR +include(GNUInstallDirs) + +# Generate a compile_commands.json with compile options +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +#set compiler and linker flags +set(RIGOROUS_C_FLAGS "-Wlogical-op -Wformat=2") +set(CMAKE_C_FLAGS "-Wall -Wextra -std=gnu99 ${RIGOROUS_C_FLAGS}") +set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}") +#NDEBUG to skip assert checks +set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}") + +# libraries to link with +set(LINK_LIBRARIES vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl) + +# build instructions +add_library(scvpp SHARED ${SCVPP_SOURCES}) +add_library(scvpp_a ${SCVPP_SOURCES}) + +# linker instructions +target_link_libraries(scvpp ${LINK_LIBRARIES}) +target_link_libraries(scvpp_a ${LINK_LIBRARIES}) + +# to build shared and static library for scvpp, include project private directory inc before installing header file +target_include_directories(scvpp PRIVATE inc) +target_include_directories(scvpp_a PRIVATE inc) + +# TESTING +######### # enable testing if requested and possible SET(ENABLE_TESTS 1 CACHE BOOL "Enable unit tests.") @@ -32,16 +81,13 @@ if(ENABLE_TESTS) endif(CMOCKA_FOUND) endif(ENABLE_TESTS) -# COMPILER & LINKER & INSTALL -############################# - -#define CMAKE_INSTALL_LIBDIR/INCLUDEDIR -include(GNUInstallDirs) -add_subdirectory(src) +# INSTALL +######### -# MORE INSTALL -############## +# install rules +install(TARGETS scvpp DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(FILES ${SCVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/scvpp) find_package(PkgConfig QUIET) #QUIET disables message if not found if(PKG_CONFIG_FOUND) diff --git a/src/scvpp/src/sc_vpp_comm.h b/src/scvpp/inc/scvpp/comm.h index eeeaaf9..9a27517 100644 --- a/src/scvpp/src/sc_vpp_comm.h +++ b/src/scvpp/inc/scvpp/comm.h @@ -23,22 +23,30 @@ #include <vapi/vapi_common.h> #include <vapi/vpe.api.vapi.h> +typedef enum { + SCVPP_OK = 0, /* Success */ + SCVPP_EINVAL, /* Invalid value encountered */ + SCVPP_EAGAIN, /* Operation would block */ + SCVPP_ENOTSUP, /* Operation not supported */ + SCVPP_ENOMEM, /* Out of memory */ + SCVPP_NOT_FOUND, /* Required element can not be found */ +} scvpp_error_e; + // Use VAPI macros to define symbols DEFINE_VAPI_MSG_IDS_VPE_API_JSON; -#define VPP_INTFC_NAME_LEN 64 -#define VPP_TAPV2_NAME_LEN VPP_INTFC_NAME_LEN -#define VPP_IP4_ADDRESS_LEN 4 -#define VPP_IP6_ADDRESS_LEN 16 -#define VPP_IP4_ADDRESS_STRING_LEN 16 -#define VPP_IP4_PREFIX_STRING_LEN 19 #define VPP_IP4_HOST_PREFIX_LEN 32 -#define VPP_IP6_ADDRESS_STRING_LEN 46 -#define VPP_MAC_ADDRESS_LEN 8 -#define VPP_TAG_LEN VPP_INTFC_NAME_LEN -#define VPP_IKEV2_PROFILE_NAME_LEN VPP_INTFC_NAME_LEN -#define VPP_IKEV2_PSK_LEN VPP_INTFC_NAME_LEN -#define VPP_IKEV2_ID_LEN 32 +#define VPP_INTFC_NAME_LEN 64 /* Interface name max length */ +#define VPP_IP4_ADDRESS_LEN 4 /* IPv4 length in VPP format */ +#define VPP_IP6_ADDRESS_LEN 16 /* IPv6 length in VPP format */ +#define VPP_MAC_ADDRESS_LEN 8 /* MAC length in VPP format */ +/* IPv4 and IPv6 length in string format */ +#define VPP_IP4_ADDRESS_STRING_LEN INET_ADDRSTRLEN //16, include '\0' +#define VPP_IP6_ADDRESS_STRING_LEN INET6_ADDRSTRLEN //46, include '\0' +#define VPP_IP4_PREFIX_STRING_LEN \ + INET_ADDRSTRLEN + sizeof('/') + 2 // include '\0' +#define VPP_IP6_PREFIX_STRING_LEN \ + INET6_ADDRSTRLEN + sizeof('/') + 3 // include '\0' /**********************************MACROS**********************************/ #define ARG_CHECK(retval, arg) \ @@ -86,9 +94,10 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last, vapi_payload_##api_name##_reply * reply) \ { \ UNUSED(ctx); UNUSED(rv); UNUSED(is_last); \ + vapi_payload_##api_name##_reply * passed; \ if (caller_ctx) \ { \ - vapi_payload_##api_name##_reply * passed = (vapi_payload_##api_name##_reply *)caller_ctx; \ + passed = (vapi_payload_##api_name##_reply *)caller_ctx; \ *passed = *reply; \ } \ return VAPI_OK; \ @@ -104,13 +113,81 @@ api_name##_cb (vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last, else \ { \ while (VAPI_EAGAIN == (rv = call_code)); \ - rv = vapi_dispatch (g_vapi_ctx_instance); \ + if (rv != VAPI_OK) { /* try once more to get reply */ \ + rv = vapi_dispatch (g_vapi_ctx); \ + } \ } \ } \ while (0) #define VAPI_CALL(call_code) VAPI_CALL_MODE(call_code, g_vapi_mode) +struct elt { + void *data; //vapi_payload structure + struct elt *next; + int id; //id of the stack element to count total nb of elements +}; + +static inline int push(struct elt **stack, void *data, int length) +{ + struct elt *el; + + //new stack node + el = malloc(sizeof(struct elt)); + if (!el) + return -ENOMEM; + el->data = malloc(length); + if (!el->data) + return -ENOMEM; + + memcpy(el->data, data, length); + if (*stack) + el->id = (*stack)->id++; + else + el->id = 0; + el->next = *stack; //point to old value of stack + *stack = el; //el is new stack head + + return 0; +} + +static inline void * pop(struct elt **stack) +{ + struct elt *prev; + void *data; + + if (!(*stack)) + return NULL; + + data = (*stack)->data; //get data at stack head + prev = *stack; //save stack to free memory later + *stack = (*stack)->next; //new stack + + free(prev); + prev = NULL; + + return data; +} + +#define VAPI_DUMP_LIST_CB(api_name) \ +static vapi_error_e \ +api_name##_all_cb(vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last, \ + vapi_payload_##api_name##_details *reply) \ +{ \ + UNUSED(ctx); UNUSED(rv); UNUSED(is_last); \ + struct elt **stackp; \ + ARG_CHECK2(VAPI_EINVAL, caller_ctx, reply); \ + \ + stackp = (struct elt**) caller_ctx; \ + push(stackp, reply, sizeof(*reply)); \ + \ + return VAPI_OK; \ +} + +#define foreach_stack_elt(stack) \ + for(void *data = pop(&stack); data != NULL ; data = pop(&stack)) +//for(void *data = pop(&stack); stack != NULL ; data = pop(&stack)) // No!! + int sc_aton(const char *cp, u8 * buf, size_t length); char * sc_ntoa(const u8 * buf); @@ -126,7 +203,7 @@ uint32_t hardntohlu32(uint8_t host[4]); * VPP */ -extern vapi_ctx_t g_vapi_ctx_instance; +extern vapi_ctx_t g_vapi_ctx; extern vapi_mode_e g_vapi_mode; int sc_connect_vpp(); diff --git a/src/scvpp/inc/scvpp/interface.h b/src/scvpp/inc/scvpp/interface.h new file mode 100644 index 0000000..86cd185 --- /dev/null +++ b/src/scvpp/inc/scvpp/interface.h @@ -0,0 +1,69 @@ +/* + * 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 __BAPI_INTERFACE_H__ +#define __BAPI_INTERFACE_H__ + +#include <vapi/interface.api.vapi.h> +#include <scvpp/comm.h> + +typedef vapi_payload_sw_interface_details sw_interface_dump_t; + +/** + * @brief Change an interface state + * @param interface_name - name of target interface + * @param enable - true=state up, false=state down + * @return 0 for success, else negative SCVPP error code + */ +int interface_enable(const char *interface_name, const bool enable); + +/** + * @brief Dump details about all existing interfaces + * @return stack structure containing all interfaces or NULL if empty + */ +extern struct elt * interface_dump_all(); + + +/** + * @brief Dump details about a specific interface + * @param details - where answer will be written + * @param interface_name - name of the interface to dump + * @return 0 for success or negative SCVPP error code + */ +extern int interface_dump_iface(sw_interface_dump_t *details, + const char *interface_name); + +/* + * Library internal helper functions. Symbols should not be exported eventually + */ + +/* + * @brief Get VPP internal index for an interface + * @param interface_name - name of the interface to get id from + * @param sw_if_index - pointer to interface index to be returned + * @return 0 upon success or negative SCVPP error code + */ +extern int get_interface_id(const char *interface_name, uint32_t *sw_if_index); + +/* @brief Get interface name from an interface ID. This is a super expensive + * operation !!! Avoid using it. + * @param interface_name - pointer to string holding returned interface name + * @param sw_if_index - interface index provided + * @return 0 upon success or negative SCVPP error code + */ +extern int get_interface_name(char *interface_name, uint32_t sw_if_index); + +#endif /* __BAPI_INTERFACE_H__ */ diff --git a/src/scvpp/inc/scvpp/ip.h b/src/scvpp/inc/scvpp/ip.h new file mode 100644 index 0000000..f8805b3 --- /dev/null +++ b/src/scvpp/inc/scvpp/ip.h @@ -0,0 +1,77 @@ +/* + * 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 __BAPI_IP_H__ +#define __BAPI_IP_H__ + +#include <vapi/interface.api.vapi.h> +#include <vapi/ip.api.vapi.h> + +typedef vapi_payload_ip_fib_details fib_dump_t; + +/* + * @brief Dump IPv4/IPv6 address from an interface. + * @param interface_name - name of the interface to get ip from. + * @param ip_addr - where dump will store IP. If IP not found, returns 0.0.0.0 + * @param prefix_len - pointer where dump will store prefix + * @param is_ipv6 - true = IPv6, false = IPv4 + * @return 0 on success, or nergative SCVPP error code + */ +extern int ipv46_address_dump(const char *interface_name, char *ip_addr, + u8 *prefix_len, bool is_ipv6); + +/** + * @brief Add or remove IPv4/IPv6 address to/from an interface. + * @param interface_name - name of interface to configure + * @param addr - address to add + * @param prefix_len - prefix length of interface + * @param is_ipv6 - true if ipv6, false otherwise + * @param add - true to add, false to remove + */ +extern int ipv46_config_add_remove(const char *interface_name, const char *addr, + uint8_t prefix_len, bool is_ipv6, bool add); + +/* + * TODO should add a field is_ipv6 because it only do ipv4 now + * @brief Add or remove an IP route + * @param dst_address - subnet IP you wish to route + * @param dst_address_length - prefix length for subnet you wish to route + * @param next_address - Next hop IP (can use next_hop_interface instead) + * @param is_add - true to add, false to remove + * @param table_id - id of the tab in FIB + * @param next_hop_interface - Next hop interface (can use next_address instead) + */ +extern int +ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length, + const char* next_address, u8 is_add, u32 table_id, + const char *next_hop_interface); + +/** + * @brief Dump all FIB tables entries + * @return stacked answers on success, or NULL on failure + */ +extern struct elt* ipv4_fib_dump_all(); + +/* + * @brief Dump information about a prefix, based on fib_dump_all + * @param prefix_xpath - prefix to look for in FIB + * @param reply - FIB entry dump replied + * @return SCVPP_OK if prefix found or SCVPP_NOT_FOUND + */ +extern int ipv4_fib_dump_prefix(const char *prefix_xpath, fib_dump_t **reply); + +#endif /* __BAPI_IP_H__ */ diff --git a/src/scvpp/src/sc_vpp_nat.h b/src/scvpp/inc/scvpp/nat.h index 40e727e..40e727e 100644 --- a/src/scvpp/src/sc_vpp_nat.h +++ b/src/scvpp/inc/scvpp/nat.h diff --git a/src/scvpp/inc/scvpp/v3po.h b/src/scvpp/inc/scvpp/v3po.h new file mode 100644 index 0000000..f876ab4 --- /dev/null +++ b/src/scvpp/inc/scvpp/v3po.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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 _V3PO__INTERFACE_H__ +#define _V3PO__INTERFACE_H__ + +#include <vapi/tapv2.api.vapi.h> +#include <vapi/l2.api.vapi.h> + +/** + * V3PO defines operations for specific interfaces used by VPP like: + * - tapv2 + */ + +/* tapv2 */ + +typedef vapi_payload_tap_create_v2 tapv2_create_t; +typedef vapi_payload_sw_interface_tap_v2_details tapv2_dump_t; + +/** + * TODO problem: vapi_payload_sw_interface_tap_v2_details reply is NULL + * @brief Dump information about a tap interface + * @param dump - where dump information will be stored + * @return 0 on success, or negative SCVPP error code + */ +extern int dump_tapv2(tapv2_dump_t *dump); + +/** + * @brief Create a tapv2 interface + * @param query - required structure for the creation of a VPP tapv2 interface + * @return 0 on success, or negative SCVPP error code + */ +extern int create_tapv2(tapv2_create_t *query); + +/** + * @brief Delete a tapv2 interface + * @param interface_name - name of the interface to delete + * @return 0 on success, or negative SCVPP error code + */ +extern int delete_tapv2(char *interface_name); + +#endif /* __V3PO_INTERFACE_H__ */ diff --git a/src/scvpp/src/CMakeLists.txt b/src/scvpp/src/CMakeLists.txt deleted file mode 100644 index 71a891f..0000000 --- a/src/scvpp/src/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (c) 2018 Cisco and/or its affiliates. -# 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. -# - -# scvpp sources -set(SCVPP_SOURCES - sc_vpp_comm.c - sc_vpp_interface.c - sc_vpp_ip.c - sc_vpp_v3po.c - sc_vpp_nat.c -) - -# scvpp public headers -set(SCVPP_HEADERS - sc_vpp_comm.h - sc_vpp_interface.h - sc_vpp_ip.h - sc_vpp_v3po.h - sc_vpp_nat.h -) - -# Generate a compile_commands.json with compile options -set(CMAKE_EXPORT_COMPILE_COMMANDS 1) - -#set compiler and linker flags -set(RIGOROUS_C_FLAGS "-Wlogical-op -Wformat=2") -set(CMAKE_C_FLAGS "-Wall -Wextra -std=gnu99 ${RIGOROUS_C_FLAGS}") -set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}") -#NDEBUG to skip assert checks -set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}") - -# libraries to link with -set(LINK_LIBRARIES vlibmemoryclient vapiclient vppapiclient svm vppinfra pthread rt dl) - -# build instructions -add_library(scvpp SHARED ${SCVPP_SOURCES}) -add_library(scvpp_a ${SCVPP_SOURCES}) - -# linker instructions -target_link_libraries(scvpp ${LINK_LIBRARIES}) -target_link_libraries(scvpp_a ${LINK_LIBRARIES}) - -# install rules -install(TARGETS scvpp DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(FILES ${SCVPP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/src/scvpp/src/sc_vpp_comm.c b/src/scvpp/src/comm.c index cd0b035..a065b58 100644 --- a/src/scvpp/src/sc_vpp_comm.c +++ b/src/scvpp/src/comm.c @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "sc_vpp_comm.h" +#include <scvpp/comm.h> #include <assert.h> #include <string.h> @@ -24,21 +24,21 @@ #define MAX_OUTSTANDING_REQUESTS 4 #define RESPONSE_QUEUE_SIZE 2 -vapi_ctx_t g_vapi_ctx_instance = NULL; +vapi_ctx_t g_vapi_ctx = NULL; vapi_mode_e g_vapi_mode = VAPI_MODE_NONBLOCKING; int sc_connect_vpp() { - if (g_vapi_ctx_instance == NULL) + if (g_vapi_ctx == NULL) { - vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance); - rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL, + vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx); + rv = vapi_connect(g_vapi_ctx, APP_NAME, NULL, MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE, VAPI_MODE_BLOCKING, true); if (rv != VAPI_OK) { - vapi_ctx_free(g_vapi_ctx_instance); - g_vapi_ctx_instance = NULL; + vapi_ctx_free(g_vapi_ctx); + g_vapi_ctx = NULL; return -1; } } @@ -48,11 +48,11 @@ int sc_connect_vpp() int sc_disconnect_vpp() { - if (NULL != g_vapi_ctx_instance) + if (NULL != g_vapi_ctx) { - vapi_disconnect(g_vapi_ctx_instance); - vapi_ctx_free(g_vapi_ctx_instance); - g_vapi_ctx_instance = NULL; + vapi_disconnect(g_vapi_ctx); + vapi_ctx_free(g_vapi_ctx); + g_vapi_ctx = NULL; } return 0; } diff --git a/src/scvpp/src/interface.c b/src/scvpp/src/interface.c new file mode 100644 index 0000000..53cea1c --- /dev/null +++ b/src/scvpp/src/interface.c @@ -0,0 +1,176 @@ +/* + * 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 <stdbool.h> + +#include <scvpp/comm.h> +#include <scvpp/interface.h> + +// Use VAPI macros to define symbols +DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON + +static vapi_error_e +sw_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx, + vapi_error_e rv, bool is_last, + vapi_payload_sw_interface_details *reply) +{ + UNUSED(rv); UNUSED(ctx); UNUSED(is_last); + + vapi_payload_sw_interface_details *passed; + + ARG_CHECK2(VAPI_EINVAL, callback_ctx, reply); + + //copy + passed = (vapi_payload_sw_interface_details *) callback_ctx; + *passed = *reply; + + return VAPI_OK; +} + +static vapi_error_e +bin_api_sw_interface_dump(vapi_payload_sw_interface_details *details, + const char *iface_name) +{ + vapi_msg_sw_interface_dump *mp; + vapi_error_e rv; + + mp = vapi_alloc_sw_interface_dump(g_vapi_ctx); + assert(NULL != mp); + + /* Dump a specific interfaces */ + mp->payload.name_filter_valid = true; + strncpy((char *)mp->payload.name_filter, iface_name, VPP_INTFC_NAME_LEN); + + VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx, mp, + sw_interface_dump_cb, details)); + if (rv != VAPI_OK) + return -SCVPP_EINVAL; + + return rv; +} + +int get_interface_id(const char *if_name, uint32_t *sw_if_index) +{ + vapi_payload_sw_interface_details details = {0}; + vapi_error_e rv; + + ARG_CHECK2(-SCVPP_EINVAL, if_name, sw_if_index); + + rv = bin_api_sw_interface_dump(&details, if_name); + if (rv != VAPI_OK) + return -SCVPP_EINVAL; + + if (strncmp(if_name, (char*) details.interface_name, VPP_INTFC_NAME_LEN) + != 0) + return -SCVPP_NOT_FOUND; + + *sw_if_index = details.sw_if_index; + + return 0; +} + +/* + * dump only a specific interface + */ +int interface_dump_iface(sw_interface_dump_t *details, const char *iface_name) +{ + vapi_error_e rv; + + rv = bin_api_sw_interface_dump(details, iface_name); + if (rv != VAPI_OK) + return -SCVPP_EINVAL; + + if (strncmp(iface_name, (char*) details->interface_name, VPP_INTFC_NAME_LEN) + != 0) + return -SCVPP_NOT_FOUND; + + return SCVPP_OK; +} + +VAPI_DUMP_LIST_CB(sw_interface) + +struct elt* interface_dump_all() +{ + struct elt* stack = NULL; + vapi_msg_sw_interface_dump *mp; + vapi_error_e rv; + + mp = vapi_alloc_sw_interface_dump(g_vapi_ctx); + + /* Dump all */ + mp->payload.name_filter_valid = false; + memset(mp->payload.name_filter, 0, sizeof(mp->payload.name_filter)); + + VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx, mp, sw_interface_all_cb, + &stack)); + if (VAPI_OK != rv) + return NULL; + + return stack; +} + +VAPI_RETVAL_CB(sw_interface_set_flags); + +int interface_enable(const char *interface_name, const bool enable) +{ + vapi_msg_sw_interface_set_flags *mp; + uint32_t sw_if_index; + vapi_error_e rv; + int rc; + + ARG_CHECK(-SCVPP_EINVAL, interface_name); + + rc = get_interface_id(interface_name, &sw_if_index); + if (rc != 0) + return -SCVPP_NOT_FOUND; + + mp = vapi_alloc_sw_interface_set_flags(g_vapi_ctx); + assert(NULL != mp); + mp->payload.sw_if_index = sw_if_index; + mp->payload.admin_up_down = enable; + + VAPI_CALL(vapi_sw_interface_set_flags(g_vapi_ctx, mp, + sw_interface_set_flags_cb, NULL)); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; + + return 0; +} + +int get_interface_name(char *interface_name, uint32_t sw_if_index) +{ + struct elt *stack= NULL; + sw_interface_dump_t *dump; + int rc = -SCVPP_NOT_FOUND; + + stack = interface_dump_all(); + if (!stack) + return -SCVPP_NOT_FOUND; + + foreach_stack_elt(stack) { + dump = (sw_interface_dump_t *) data; + + if (dump->sw_if_index == sw_if_index) { + strncpy(interface_name, (char *)dump->interface_name, VPP_INTFC_NAME_LEN); + rc = SCVPP_OK; + } + + free(dump); + } + + return rc; +} diff --git a/src/scvpp/src/sc_vpp_ip.c b/src/scvpp/src/ip.c index 0dfd108..2dc991c 100644 --- a/src/scvpp/src/sc_vpp_ip.c +++ b/src/scvpp/src/ip.c @@ -14,12 +14,12 @@ * limitations under the License. */ -#include "sc_vpp_comm.h" -#include "sc_vpp_ip.h" - -#include "sc_vpp_interface.h" +#include <scvpp/comm.h> +#include <scvpp/ip.h> +#include <scvpp/interface.h> #include <assert.h> +#include <stdio.h> // Use VAPI macros to define symbols DEFINE_VAPI_MSG_IDS_IP_API_JSON @@ -36,7 +36,7 @@ bin_api_sw_interface_add_del_address(u32 sw_if_index, bool is_add, bool is_ipv6, ARG_CHECK(VAPI_EINVAL, ip_address); - mp = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance); + mp = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx); assert(NULL != mp); mp->payload.sw_if_index = sw_if_index; @@ -44,10 +44,10 @@ bin_api_sw_interface_add_del_address(u32 sw_if_index, bool is_add, bool is_ipv6, mp->payload.is_ipv6 = is_ipv6; mp->payload.del_all = del_all; mp->payload.address_length = address_length; - if (sc_aton(ip_address, mp->payload.address, sizeof(mp->payload.address))) + if (sc_aton(ip_address, mp->payload.address, VPP_IP4_ADDRESS_LEN)) return VAPI_EINVAL; - VAPI_CALL(vapi_sw_interface_add_del_address(g_vapi_ctx_instance, mp, + VAPI_CALL(vapi_sw_interface_add_del_address(g_vapi_ctx, mp, sw_interface_add_del_address_cb, NULL)); return rv; @@ -59,38 +59,41 @@ static vapi_error_e bin_api_ip_add_del_route(vapi_payload_ip_add_del_route_reply * reply, const char* dst_address, uint8_t dst_address_length, const char* next_hop, uint8_t is_add, - uint32_t table_id, const char *interface_name) + uint32_t table_id, const char *next_interface) { - sw_interface_details_query_t query = {0}; vapi_msg_ip_add_del_route *mp; + uint32_t sw_if_index; + vapi_error_e rv ; + int rc; - ARG_CHECK4(VAPI_EINVAL, reply, dst_address, next_hop, interface_name); - - sw_interface_details_query_set_name(&query, interface_name); + ARG_CHECK2(VAPI_EINVAL, reply, dst_address); - if (!get_interface_id(&query)) + //Require interface or next hop IP or both + if (!next_interface && !next_hop) return VAPI_EINVAL; - mp = vapi_alloc_ip_add_del_route (g_vapi_ctx_instance, 1); + mp = vapi_alloc_ip_add_del_route(g_vapi_ctx, 1); assert(NULL != mp); - //ip route add 2.2.2.2/24 via 5.5.5.5 - //show ip fib table 0 2.2.2.0/24 detail + if (next_interface) { + rc = get_interface_id(next_interface, &sw_if_index); + if (rc < 0) + return VAPI_EINVAL; + } mp->payload.is_add = is_add; - mp->payload.dst_address_length = dst_address_length; mp->payload.table_id = table_id; - mp->payload.next_hop_sw_if_index = query.sw_interface_details.sw_if_index; - - if (sc_aton(dst_address, mp->payload.dst_address, - sizeof(mp->payload.dst_address))) - return VAPI_EINVAL; - if (sc_aton(next_hop, mp->payload.next_hop_address, - sizeof(mp->payload.next_hop_address))) - return VAPI_EINVAL; + mp->payload.is_ipv6 = false; + mp->payload.is_local = false; + sc_aton(dst_address, mp->payload.dst_address, VPP_IP4_ADDRESS_LEN); + mp->payload.dst_address_length = dst_address_length; + if (next_interface) //interface is not mandatory + mp->payload.next_hop_sw_if_index = sw_if_index; + if (next_hop) //next hop ip is not mandatory + sc_aton(next_hop, mp->payload.next_hop_address, VPP_IP4_ADDRESS_LEN); - vapi_error_e rv ; - VAPI_CALL(vapi_ip_add_del_route(g_vapi_ctx_instance, mp, ip_add_del_route_cb, reply)); + VAPI_CALL(vapi_ip_add_del_route(g_vapi_ctx, mp, + ip_add_del_route_cb, reply)); return rv; } @@ -100,12 +103,13 @@ ip_address_dump_cb (struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, vapi_payload_ip_address_details *reply) { UNUSED(rv); + vapi_payload_ip_address_details *passed; + ARG_CHECK3(VAPI_EINVAL, ctx, callback_ctx, reply); //copy dump reply in callback context - if (!is_last && callback_ctx) { - vapi_payload_ip_address_details *passed = - (vapi_payload_ip_address_details *) callback_ctx; + if (!is_last) { + passed = (vapi_payload_ip_address_details *) callback_ctx; *passed = *reply; } @@ -119,11 +123,13 @@ bin_api_ip_address_dump(u32 sw_if_index, bool is_ipv6, vapi_msg_ip_address_dump *mp; vapi_error_e rv; - mp = vapi_alloc_ip_address_dump(g_vapi_ctx_instance); + mp = vapi_alloc_ip_address_dump(g_vapi_ctx); + assert(mp != NULL); + mp->payload.sw_if_index = sw_if_index; mp->payload.is_ipv6 = is_ipv6; - VAPI_CALL(vapi_ip_address_dump(g_vapi_ctx_instance, mp, ip_address_dump_cb, + VAPI_CALL(vapi_ip_address_dump(g_vapi_ctx, mp, ip_address_dump_cb, dctx)); if (rv != VAPI_OK) return rv; @@ -131,64 +137,112 @@ bin_api_ip_address_dump(u32 sw_if_index, bool is_ipv6, return VAPI_OK; } -/* - * @brief Dump IPv4/IPv6 address from an interface. - * @param interface_name Name of the interface to dump. - * @param ip_addr pointer where dump will store IP. - * @param prefix_len pointer where dump will store prefix - */ +///VAPI_DUMP_LIST_CB(ip_fib); can not be used because of path flexible array + +static vapi_error_e +ip_fib_all_cb(vapi_ctx_t ctx, void *caller_ctx, vapi_error_e rv, bool is_last, + vapi_payload_ip_fib_details *reply) +{ + UNUSED(ctx); UNUSED(rv); UNUSED(is_last); + struct elt **stackp; + ARG_CHECK2(VAPI_EINVAL, caller_ctx, reply); + + stackp = (struct elt**) caller_ctx; + push(stackp, reply, sizeof(*reply)+reply->count*sizeof(vapi_type_fib_path)); + + return VAPI_OK; +} + +struct elt* ipv4_fib_dump_all() +{ + struct elt *stack = NULL; + vapi_msg_ip_fib_dump *mp; + vapi_error_e rv; + + mp = vapi_alloc_ip_fib_dump(g_vapi_ctx); + assert(mp != NULL); + + VAPI_CALL(vapi_ip_fib_dump(g_vapi_ctx, mp, ip_fib_all_cb, &stack)); + if(VAPI_OK != rv) + return NULL; + + return stack; +} + +int ipv4_fib_dump_prefix(const char *prefix_xpath, fib_dump_t **reply) +{ + struct elt *stack = NULL; + char prefix[VPP_IP4_PREFIX_STRING_LEN]; + fib_dump_t *dump; + int rc = -SCVPP_NOT_FOUND; + + stack = ipv4_fib_dump_all(); + if (!stack) + return rc; + + foreach_stack_elt(stack) { + dump = (fib_dump_t *) data; + + if (rc == -SCVPP_NOT_FOUND) { + snprintf(prefix, VPP_IP4_PREFIX_STRING_LEN, "%s/%u", + sc_ntoa(dump->address), dump->address_length); + if (!strncmp(prefix_xpath, prefix, VPP_IP4_PREFIX_STRING_LEN)) { + *reply = dump; + rc = SCVPP_OK; + continue; + } + } + + free(dump); + } + + return rc; +} + int ipv46_address_dump(const char *interface_name, char *ip_addr, u8 *prefix_len, bool is_ipv6) { vapi_payload_ip_address_details dctx = {0}; - sw_interface_details_query_t query = {0}; + uint32_t sw_if_index; vapi_error_e rv; + int rc; - sw_interface_details_query_set_name(&query, interface_name); - - if (!get_interface_id(&query)) - return -EINVAL; + rc = get_interface_id(interface_name, &sw_if_index); + if (rc < 0) + return rc; - rv = bin_api_ip_address_dump(query.sw_interface_details.sw_if_index, is_ipv6, &dctx); + rv = bin_api_ip_address_dump(sw_if_index, is_ipv6, &dctx); if (rv != VAPI_OK) - return -EAGAIN; + return -SCVPP_EINVAL; strcpy(ip_addr, sc_ntoa(dctx.ip)); //IP string *prefix_len = dctx.prefix_length; //prefix length - return 0; + return SCVPP_OK; } -/** - * @brief Add or remove IPv4/IPv6 address to/from an interface. - */ int ipv46_config_add_remove(const char *if_name, const char *addr, uint8_t prefix, bool is_ipv6, bool add) { vapi_error_e rv; + uint32_t sw_if_index; int rc; ARG_CHECK2(-1, if_name, addr); - /* get interface index */ - sw_interface_details_query_t query = {0}; - sw_interface_details_query_set_name(&query, if_name); - rc = get_interface_id(&query); - if (!rc) - return -EINVAL; + rc = get_interface_id(if_name, &sw_if_index); + if (rc < 0) + return rc; /* add del addr */ - rv = bin_api_sw_interface_add_del_address(query.sw_interface_details.sw_if_index, - add, is_ipv6, 0, prefix, addr); + rv = bin_api_sw_interface_add_del_address(sw_if_index, add, is_ipv6, 0, + prefix, addr); if (rv != VAPI_OK) - return -EINVAL; + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } -/* - * @brief Add or remove an IP route - */ int ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length, const char* next_address, u8 is_add, u32 table_id, const char *interface) @@ -198,9 +252,8 @@ int ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length, rv = bin_api_ip_add_del_route(&reply, dst_address, dst_address_length, next_address, is_add, table_id, interface); - if (VAPI_OK != rv || reply.retval > 0) { - return -EINVAL; - } + if (VAPI_OK != rv || reply.retval > 0) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } diff --git a/src/scvpp/src/sc_vpp_nat.c b/src/scvpp/src/nat.c index e4bf2b7..17ace64 100644 --- a/src/scvpp/src/sc_vpp_nat.c +++ b/src/scvpp/src/nat.c @@ -14,8 +14,8 @@ * limitations under the License. */ -#include "sc_vpp_comm.h" -#include "sc_vpp_nat.h" +#include <scvpp/comm.h> +#include <scvpp/nat.h> #include <assert.h> #include <stdbool.h> @@ -28,8 +28,7 @@ nat44_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, vapi_payload_nat44_interface_details *reply) { - UNUSED(ctx); - UNUSED(rv); + UNUSED(ctx); UNUSED(rv); vapi_payload_nat44_interface_details *dctx = callback_ctx; assert(dctx); @@ -56,10 +55,10 @@ bin_api_nat44_interface_dump(vapi_payload_nat44_interface_details *reply) ARG_CHECK(VAPI_EINVAL, reply); - mp = vapi_alloc_nat44_interface_dump(g_vapi_ctx_instance); + mp = vapi_alloc_nat44_interface_dump(g_vapi_ctx); assert(NULL != mp); - VAPI_CALL(vapi_nat44_interface_dump(g_vapi_ctx_instance, mp, + VAPI_CALL(vapi_nat44_interface_dump(g_vapi_ctx, mp, nat44_interface_dump_cb, reply)); return rv; @@ -76,12 +75,12 @@ bin_api_nat44_add_del_interface_addr( ARG_CHECK(VAPI_EINVAL, msg); - mp = vapi_alloc_nat44_add_del_interface_addr(g_vapi_ctx_instance); + mp = vapi_alloc_nat44_add_del_interface_addr(g_vapi_ctx); assert(NULL != mp); mp->payload = *msg; - VAPI_CALL(vapi_nat44_add_del_interface_addr(g_vapi_ctx_instance, mp, + VAPI_CALL(vapi_nat44_add_del_interface_addr(g_vapi_ctx, mp, nat44_add_del_interface_addr_cb, NULL)); @@ -99,13 +98,13 @@ bin_api_nat44_add_del_addr_range( ARG_CHECK(VAPI_EINVAL, range); - mp = vapi_alloc_nat44_add_del_address_range(g_vapi_ctx_instance); + mp = vapi_alloc_nat44_add_del_address_range(g_vapi_ctx); assert(NULL != mp); mp->payload = *range; - VAPI_CALL(vapi_nat44_add_del_address_range(g_vapi_ctx_instance, mp, + VAPI_CALL(vapi_nat44_add_del_address_range(g_vapi_ctx, mp, nat44_add_del_address_range_cb, NULL)); @@ -123,13 +122,12 @@ bin_api_nat44_add_del_static_mapping( ARG_CHECK(VAPI_EINVAL, msg); - mp = vapi_alloc_nat44_add_del_static_mapping(g_vapi_ctx_instance); - + mp = vapi_alloc_nat44_add_del_static_mapping(g_vapi_ctx); assert(NULL != mp); mp->payload = *msg; - VAPI_CALL(vapi_nat44_add_del_static_mapping(g_vapi_ctx_instance, mp, + VAPI_CALL(vapi_nat44_add_del_static_mapping(g_vapi_ctx, mp, nat44_add_del_static_mapping_cb, NULL)); @@ -140,8 +138,7 @@ static vapi_error_e nat44_static_mapping_dump_cb( struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last,vapi_payload_nat44_static_mapping_details *reply) { - UNUSED(rv); - UNUSED(ctx); + UNUSED(rv); UNUSED(ctx); vapi_payload_nat44_static_mapping_details *dctx = callback_ctx; assert(dctx); @@ -166,10 +163,10 @@ bin_api_nat44_static_mapping_dump( ARG_CHECK(VAPI_EINVAL, reply); - msg = vapi_alloc_nat44_static_mapping_dump(g_vapi_ctx_instance); + msg = vapi_alloc_nat44_static_mapping_dump(g_vapi_ctx); assert(NULL != msg); - VAPI_CALL(vapi_nat44_static_mapping_dump(g_vapi_ctx_instance, msg, + VAPI_CALL(vapi_nat44_static_mapping_dump(g_vapi_ctx, msg, nat44_static_mapping_dump_cb, reply)); @@ -186,13 +183,13 @@ static vapi_error_e bin_api_nat44_forwarding_enable_disable( ARG_CHECK(VAPI_EINVAL, msg); - mp = vapi_alloc_nat44_forwarding_enable_disable(g_vapi_ctx_instance); + mp = vapi_alloc_nat44_forwarding_enable_disable(g_vapi_ctx); assert(NULL != mp); mp->payload = *msg; VAPI_CALL(vapi_nat44_forwarding_enable_disable( - g_vapi_ctx_instance, mp, nat44_forwarding_enable_disable_cb, NULL)); + g_vapi_ctx, mp, nat44_forwarding_enable_disable_cb, NULL)); return rv; } @@ -207,113 +204,91 @@ bin_api_nat_set_workers(const vapi_payload_nat_set_workers *msg) ARG_CHECK(VAPI_EINVAL, msg); - mp = vapi_alloc_nat_set_workers(g_vapi_ctx_instance); + mp = vapi_alloc_nat_set_workers(g_vapi_ctx); assert(NULL != mp); mp->payload = *msg; - VAPI_CALL(vapi_nat_set_workers(g_vapi_ctx_instance, mp, nat_set_workers_cb, - NULL)); + VAPI_CALL(vapi_nat_set_workers(g_vapi_ctx, mp, nat_set_workers_cb, NULL)); return rv; } int nat44_interface_dump(nat44_interface_details_t *reply) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat44_interface_dump(reply); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat44_interface_dump(reply); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } int nat44_add_del_interface_addr(const nat44_add_del_interface_addr_t *msg) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat44_add_del_interface_addr(msg); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat44_add_del_interface_addr(msg); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } int nat44_add_del_addr_range(const nat44_add_del_address_range_t *range) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat44_add_del_addr_range(range); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat44_add_del_addr_range(range); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } int nat44_add_del_static_mapping(const nat44_add_del_static_mapping_t *msg) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat44_add_del_static_mapping(msg); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat44_add_del_static_mapping(msg); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } int nat44_static_mapping_dump(nat44_static_mapping_details_t *reply) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat44_static_mapping_dump(reply); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat44_static_mapping_dump(reply); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } -int nat44_forwarding_enable_disable( - const nat44_forwarding_enable_disable_t *msg) +int +nat44_forwarding_enable_disable(const nat44_forwarding_enable_disable_t *msg) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat44_forwarding_enable_disable(msg); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat44_forwarding_enable_disable(msg); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; return 0; } int nat_set_workers(const nat_set_workers_t *msg) { - vapi_error_e rc; + vapi_error_e rv; - rc = bin_api_nat_set_workers(msg); - if (VAPI_OK != rc) { - //TODO: Need implement log function -// ERROR("Error in nat44_interface_dump, error: %u", rc); - return -1; - } + rv = bin_api_nat_set_workers(msg); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - return 0; + return SCVPP_OK; } diff --git a/src/scvpp/src/sc_vpp_interface.c b/src/scvpp/src/sc_vpp_interface.c deleted file mode 100644 index bc5befc..0000000 --- a/src/scvpp/src/sc_vpp_interface.c +++ /dev/null @@ -1,252 +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 <stdbool.h> - -#include <vapi/l2.api.vapi.h> - -#include "sc_vpp_comm.h" -#include "sc_vpp_interface.h" - - -// Use VAPI macros to define symbols -DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON -DEFINE_VAPI_MSG_IDS_L2_API_JSON; - -void sw_interface_details_query_set_name(sw_interface_details_query_t * query, - const char * interface_name) -{ - assert(query && interface_name); - - memset(query, 0, sizeof(*query)); - - strncpy((char*) query->sw_interface_details.interface_name, interface_name, - sizeof(query->sw_interface_details.interface_name)); -} - -static vapi_error_e -sw_interface_dump_cb(struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_sw_interface_details *reply) -{ - UNUSED(rv); UNUSED(ctx); UNUSED(is_last); - - vapi_payload_sw_interface_details *passed; - - ARG_CHECK(-EINVAL, callback_ctx); - - passed = (vapi_payload_sw_interface_details *) callback_ctx; - - //Interface is found if index of query equals index of reply - if (passed->sw_if_index != reply->sw_if_index) - return -EINVAL; - - //copy - *passed = *reply; - - return VAPI_OK; -} - -static vapi_error_e -bin_api_sw_interface_dump(vapi_payload_sw_interface_details *details) -{ - vapi_msg_sw_interface_dump *mp; - vapi_error_e rv; - - mp = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance); - - mp->payload.name_filter_valid = 0; - memset(mp->payload.name_filter, 0, sizeof(mp->payload.name_filter)); - assert(NULL != mp); - - VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, mp, sw_interface_dump_cb, details)); - if (!rv) - return -EINVAL; - - return rv; -} - -static vapi_error_e -interface_dump_all_cb(struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_sw_interface_details * reply) -{ - UNUSED(ctx); UNUSED(rv); - dump_all_ctx *dctx = callback_ctx; - - if (is_last) - return VAPI_OK; - - if(dctx->capacity == 0 && dctx->intfcArray == NULL) { - dctx->capacity = 10; - dctx->intfcArray = (vpp_interface_t*)malloc( sizeof(vpp_interface_t)*dctx->capacity ); - } - if(dctx->num_ifs >= dctx->capacity-1) { - dctx->capacity += 10; - dctx->intfcArray = (vpp_interface_t*)realloc(dctx->intfcArray, sizeof(vpp_interface_t)*dctx->capacity ); - } - - vpp_interface_t * iface = &dctx->intfcArray[dctx->num_ifs]; - - iface->sw_if_index = reply->sw_if_index; - strncpy(iface->interface_name, (char*) reply->interface_name, - VPP_INTFC_NAME_LEN); - iface->l2_address_length = reply->l2_address_length; - memcpy(iface->l2_address, reply->l2_address, reply->l2_address_length ); - iface->link_speed = reply->link_speed; - - iface->link_mtu = reply->link_mtu; - iface->admin_up_down = reply->admin_up_down; - iface->link_up_down = reply->link_up_down; - - dctx->num_ifs += 1; - - return VAPI_OK; -} - -int interface_dump_all(dump_all_ctx * dctx) -{ - vapi_msg_sw_interface_dump *dump; - vapi_error_e rv; - - ARG_CHECK(-1, dctx); - - if(dctx == NULL) - return -1; - - dctx->intfcArray = NULL; - dctx->capacity = 0; - dctx->num_ifs = 0; - - dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance); - - dump->payload.name_filter_valid = 0; - memset(dump->payload.name_filter, 0, sizeof(dump->payload.name_filter)); - while (VAPI_EAGAIN == - (rv = - vapi_sw_interface_dump(g_vapi_ctx_instance, dump, interface_dump_all_cb, - dctx))); - - return dctx->num_ifs; -} - -static vapi_error_e -get_interface_id_cb (struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_sw_interface_details * reply) -{ - UNUSED(ctx); UNUSED(rv); - - sw_interface_details_query_t *dctx = callback_ctx; - assert(dctx); - - if (!dctx->interface_found) - { - if (is_last) - { - assert(NULL == reply); - } - else - { - assert(NULL != reply); - - if (0 == strcmp((const char*)dctx->sw_interface_details.interface_name, - (const char*)reply->interface_name)) - { - dctx->interface_found = true; - dctx->sw_interface_details = *reply; - } - } - } - - return VAPI_OK; -} - -// return error code instead of boolean -int get_interface_id(sw_interface_details_query_t * sw_interface_details_query) -{ - vapi_error_e rv; - - ARG_CHECK(false, sw_interface_details_query); - - sw_interface_details_query->interface_found = false; - - vapi_msg_sw_interface_dump *mp = vapi_alloc_sw_interface_dump (g_vapi_ctx_instance); - assert(NULL != mp); - - mp->payload.name_filter_valid = true; - memcpy(mp->payload.name_filter, sw_interface_details_query->sw_interface_details.interface_name, - sizeof(mp->payload.name_filter)); - - VAPI_CALL(vapi_sw_interface_dump(g_vapi_ctx_instance, mp, get_interface_id_cb, sw_interface_details_query)); - if (VAPI_OK != rv) - return false; - - return sw_interface_details_query->interface_found; -} - -int get_interface_name(sw_interface_details_query_t *query) -{ - vapi_error_e rv; - - ARG_CHECK(-EINVAL, query); - - query->interface_found = false; - - rv = bin_api_sw_interface_dump(&query->sw_interface_details); - if (rv == VAPI_OK) - query->interface_found = true; - - return query->interface_found; -} - -VAPI_RETVAL_CB(sw_interface_set_flags); - -static vapi_error_e -bin_api_sw_interface_set_flags(uint32_t if_index, uint8_t up) -{ - vapi_msg_sw_interface_set_flags *mp = vapi_alloc_sw_interface_set_flags (g_vapi_ctx_instance); - assert(NULL != mp); - - mp->payload.sw_if_index = if_index; - mp->payload.admin_up_down = up; - - vapi_error_e rv; - VAPI_CALL(vapi_sw_interface_set_flags(g_vapi_ctx_instance, mp, sw_interface_set_flags_cb, NULL)); - - return rv; -} - -int interface_enable(const char *interface_name, const bool enable) -{ - ARG_CHECK(-1, interface_name); - - int rc = 0; - sw_interface_details_query_t query = {0}; - sw_interface_details_query_set_name(&query, interface_name); - - rc = get_interface_id(&query); - if (!rc) - return -1; - - rc = bin_api_sw_interface_set_flags(query.sw_interface_details.sw_if_index, - enable); - if (VAPI_OK != rc) - return -1; - - return 0; -} diff --git a/src/scvpp/src/sc_vpp_interface.h b/src/scvpp/src/sc_vpp_interface.h deleted file mode 100644 index 32b61bc..0000000 --- a/src/scvpp/src/sc_vpp_interface.h +++ /dev/null @@ -1,61 +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 __BAPI_INTERFACE_H__ -#define __BAPI_INTERFACE_H__ - -#include <vapi/interface.api.vapi.h> - -int interface_enable(const char *interface_name, const bool enable); - -//TODO remove the following structures ASAP -typedef struct { - bool interface_found; - vapi_payload_sw_interface_details sw_interface_details; -} sw_interface_details_query_t; - -typedef struct _vpp_interface_t -{ - u32 sw_if_index; - char interface_name[VPP_INTFC_NAME_LEN]; - u8 l2_address[VPP_MAC_ADDRESS_LEN]; - u32 l2_address_length; - u64 link_speed; - u16 link_mtu; - u8 admin_up_down; - u8 link_up_down; -} vpp_interface_t; - -typedef struct _dump_all_ctx -{ - int num_ifs; - int capacity; - vpp_interface_t * intfcArray; -} dump_all_ctx; - -/* return the number of interfaces or a negative error code */ -extern int interface_dump_all(dump_all_ctx * dctx); - -extern void sw_interface_details_query_set_name(sw_interface_details_query_t * query, - const char * interface_name); - -//input - sw_interface_details_query shall contain interface_name -extern int get_interface_id(sw_interface_details_query_t * sw_interface_details_query); - -//input - sw_interface_details_query shall contain sw_if_index -extern int get_interface_name(sw_interface_details_query_t * sw_interface_details_query); - -#endif /* __BAPI_INTERFACE_H__ */ diff --git a/src/scvpp/src/sc_vpp_ip.h b/src/scvpp/src/sc_vpp_ip.h deleted file mode 100644 index a9f19d4..0000000 --- a/src/scvpp/src/sc_vpp_ip.h +++ /dev/null @@ -1,36 +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 __BAPI_IP_H__ -#define __BAPI_IP_H__ - -#include <vapi/interface.api.vapi.h> -#include <vapi/ip.api.vapi.h> - -/* If no IP has been found ip_addr will be "0.0.0.0" */ -extern int ipv46_address_dump(const char *interface_name, char *ip_addr, - u8 *prefix_len, bool is_ipv6); - -extern int ipv46_config_add_remove(const char *if_name, const char *addr, - uint8_t prefix, bool is_ipv6, bool add); - -extern int -ipv46_config_add_del_route(const char* dst_address, u8 dst_address_length, - const char* next_address, u8 is_add, u32 table_id, - const char *interface); - -#endif /* __BAPI_IP_H__ */ diff --git a/src/scvpp/src/sc_vpp_v3po.h b/src/scvpp/src/sc_vpp_v3po.h deleted file mode 100644 index 9c13569..0000000 --- a/src/scvpp/src/sc_vpp_v3po.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * 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 _V3PO__INTERFACE_H__ -#define _V3PO__INTERFACE_H__ - -#include <vapi/tapv2.api.vapi.h> - -typedef vapi_payload_tap_create_v2 tapv2_create_t; - -int create_tapv2(tapv2_create_t *query); -int delete_tapv2(char *iface_name); - -#endif /* __V3PO_INTERFACE_H__ */ diff --git a/src/scvpp/src/sc_vpp_v3po.c b/src/scvpp/src/v3po.c index d312331..f0a41c5 100644 --- a/src/scvpp/src/sc_vpp_v3po.c +++ b/src/scvpp/src/v3po.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2016 Cisco and/or its affiliates. + * 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: @@ -15,35 +17,18 @@ #include <assert.h> -#include "sc_vpp_comm.h" -#include "sc_vpp_v3po.h" -#include "sc_vpp_interface.h" +#include <scvpp/comm.h> +#include <scvpp/v3po.h> +#include <scvpp/interface.h> + +// Use VAPI macros to define symbols +DEFINE_VAPI_MSG_IDS_L2_API_JSON; +DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON /* * tap-v2 interfaces */ -DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON - -// Dump tapv2 - -//typedef struct __attribute__ ((__packed__)) { -// u32 sw_if_index; -// u32 id; -// u8 dev_name[64]; -// u16 tx_ring_sz; -// u16 rx_ring_sz; -// u8 host_mac_addr[6]; -// u8 host_if_name[64]; -// u8 host_namespace[64]; -// u8 host_bridge[64]; -// u8 host_ip4_addr[4]; -// u8 host_ip4_prefix_len; -// u8 host_ip6_addr[16]; -// u8 host_ip6_prefix_len; -// u32 tap_flags; -//} vapi_payload_sw_interface_tap_v2_details; - // Delete tapv2 VAPI_RETVAL_CB(tap_delete_v2); @@ -53,35 +38,33 @@ static vapi_error_e bin_api_delete_tapv2(u32 sw_if_index) vapi_msg_tap_delete_v2 *mp; vapi_error_e rv; - mp = vapi_alloc_tap_delete_v2(g_vapi_ctx_instance); + mp = vapi_alloc_tap_delete_v2(g_vapi_ctx); assert(NULL != mp); mp->payload.sw_if_index = sw_if_index; - VAPI_CALL(vapi_tap_delete_v2(g_vapi_ctx_instance, mp, tap_delete_v2_cb, - NULL)); + VAPI_CALL(vapi_tap_delete_v2(g_vapi_ctx, mp, tap_delete_v2_cb, NULL)); if (rv != VAPI_OK) - return -EAGAIN; + return -rv; - return rv; + return VAPI_OK; } int delete_tapv2(char *iface_name) { + uint32_t sw_if_index; + vapi_error_e rv; int rc; - sw_interface_details_query_t query = {0}; - sw_interface_details_query_set_name(&query, iface_name); + rc = get_interface_id(iface_name, &sw_if_index); + if (rc < 0) + return rc; - rc = get_interface_id(&query); - if (!rc) - return -1; + rv = bin_api_delete_tapv2(sw_if_index); + if (VAPI_OK != rv) + return -SCVPP_EINVAL; - rc = bin_api_delete_tapv2(query.sw_interface_details.sw_if_index); - if (VAPI_OK != rc) - return -1; - - return 0; + return SCVPP_OK; } // Create tapv2 @@ -93,13 +76,12 @@ int create_tapv2(tapv2_create_t *query) vapi_msg_tap_create_v2 *mp; vapi_error_e rv; - mp = vapi_alloc_tap_create_v2(g_vapi_ctx_instance); + mp = vapi_alloc_tap_create_v2(g_vapi_ctx); assert(NULL != mp); memcpy(&mp->payload, query, sizeof(tapv2_create_t)); - VAPI_CALL(vapi_tap_create_v2(g_vapi_ctx_instance, mp, tap_create_v2_cb, - NULL)); + VAPI_CALL(vapi_tap_create_v2(g_vapi_ctx, mp, tap_create_v2_cb, NULL)); if (rv != VAPI_OK) return -EAGAIN; diff --git a/src/scvpp/tests/CMakeLists.txt b/src/scvpp/tests/CMakeLists.txt index 3153fe0..2b6de4a 100644 --- a/src/scvpp/tests/CMakeLists.txt +++ b/src/scvpp/tests/CMakeLists.txt @@ -18,24 +18,23 @@ include_directories ("${PROJECT_SOURCE_DIR}/src") # check whether valgrind is installed find_program(valgrind_FOUND valgrind) -# macro for adding of an unit test -macro(ADD_UNIT_TEST TEST_NAME) - set(TEST_SRC - ${TEST_NAME}.c - scvpp_nat_test.c - ) - add_executable(${TEST_NAME} ${TEST_SRC}) - target_link_libraries(${TEST_NAME} ${CMOCKA_LIBRARIES} scvpp_a) - add_test(${TEST_NAME} ${TEST_NAME}) +set(TEST_SRC + scvpp_test.h + scvpp_test.c + scvpp_iface_test.c + scvpp_ip_test.c + scvpp_nat_test.c +) - if(valgrind_FOUND) - add_test(${TEST_NAME}_valgrind valgrind - --error-exitcode=1 --read-var-info=yes - --leak-check=full --show-leak-kinds=all - ./${TEST_NAME} - ) - endif(valgrind_FOUND) -endmacro(ADD_UNIT_TEST) +add_executable(scvpp_test ${TEST_SRC}) +target_link_libraries(scvpp_test ${CMOCKA_LIBRARIES} scvpp_a) +target_include_directories(scvpp_test PRIVATE ../inc) +add_test(scvpp_test scvpp_test) -# add individual unit-tests -ADD_UNIT_TEST(scvpp_test) +if(valgrind_FOUND) + add_test(${TEST_NAME}_valgrind valgrind + --error-exitcode=1 --read-var-info=yes + --leak-check=full --show-leak-kinds=all + ./${TEST_NAME} + ) +endif(valgrind_FOUND) diff --git a/src/scvpp/tests/scvpp_iface_test.c b/src/scvpp/tests/scvpp_iface_test.c new file mode 100644 index 0000000..6a96694 --- /dev/null +++ b/src/scvpp/tests/scvpp_iface_test.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * 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 <unistd.h> +#include <setjmp.h> +#include <stdarg.h> +#include <cmocka.h> + +#include "scvpp_test.h" + +#include <scvpp/interface.h> +#include <scvpp/v3po.h> + +static void test_enable_disable(void **state) +{ + UNUSED(state); + sw_interface_dump_t dump = {0}; + int rc; + + rc = interface_enable("tap0", 1); + assert_int_equal(rc, SCVPP_OK); + + rc = interface_dump_iface(&dump, "tap0"); + assert_int_equal(rc, SCVPP_OK); + + assert_int_equal(dump.admin_up_down, true); + + rc = interface_enable("tap0", 0); + assert_int_equal(rc, SCVPP_OK); +} + +static void test_create_tapv2(void **state) +{ + UNUSED(state); + tapv2_create_t query = {0}; + sw_interface_dump_t dump = {0}; + int rc; + + query.id = 1; + query.use_random_mac = 1; + + rc = create_tapv2(&query); + assert_int_equal(rc, SCVPP_OK); + + rc = interface_dump_iface(&dump, "tap1"); + assert_int_equal(rc, SCVPP_OK); +} + +static int teardown_tapv2(void **state) +{ + UNUSED(state); + return delete_tapv2("tap1"); +} + +static void test_dump_iface_all(void **state) +{ + UNUSED(state); + struct elt *stack = NULL; + sw_interface_dump_t *dump; + bool exist = false; + + stack = interface_dump_all(); + assert_non_null(stack); + foreach_stack_elt(stack) { + dump = (sw_interface_dump_t *) data; + if (!strncmp((char*) dump->interface_name, "tap0", VPP_INTFC_NAME_LEN)) + exist = true; + free(dump); + } + assert_true(exist); +} + +static void test_dump_iface_exist(void **state) +{ + UNUSED(state); + vapi_payload_sw_interface_details details = {0}; + int rc; + + rc = interface_dump_iface(&details, "local0"); + assert_int_equal(rc, SCVPP_OK); + + assert_string_equal(details.interface_name, "local0"); +} + +static void test_dump_iface_unexist(void **state) +{ + UNUSED(state); + vapi_payload_sw_interface_details details = {0}; + int rc; + + rc = interface_dump_iface(&details, "unexisting"); + assert_int_equal(rc, -SCVPP_NOT_FOUND); +} + +static void test_get_interface_name(void **state) +{ + UNUSED(state); + char interface_name[VPP_INTFC_NAME_LEN]; + uint32_t tap0_if_index; + int rc; + + rc = get_interface_id("tap0", &tap0_if_index); + assert_int_equal(rc, SCVPP_OK); + + rc = get_interface_name(interface_name, tap0_if_index); + assert_int_equal(rc, SCVPP_OK); + + assert_string_equal(interface_name, "tap0"); +} + +const struct CMUnitTest iface_tests[IFACE_TEST_SIZE] = { + cmocka_unit_test_teardown(test_create_tapv2, teardown_tapv2), + cmocka_unit_test(test_enable_disable), + cmocka_unit_test(test_dump_iface_all), + cmocka_unit_test(test_dump_iface_exist), + cmocka_unit_test(test_dump_iface_unexist), + cmocka_unit_test(test_get_interface_name), +}; diff --git a/src/scvpp/tests/scvpp_ip_test.c b/src/scvpp/tests/scvpp_ip_test.c new file mode 100644 index 0000000..5e28123 --- /dev/null +++ b/src/scvpp/tests/scvpp_ip_test.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2019 Cisco + * + * 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 <unistd.h> +#include <setjmp.h> +#include <stdarg.h> +#include <cmocka.h> + +#include "scvpp_test.h" + +#include <scvpp/ip.h> +#include <scvpp/interface.h> +#include <scvpp/comm.h> + +static void test_add_remove_ipv4(void **state) +{ + UNUSED(state); + const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144"; + char ip_r[VPP_IP4_ADDRESS_STRING_LEN]; + u8 prefix_q = 24; + u8 prefix_r; + int rc; + + //add ipv4 on tap0 + rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true); + assert_int_equal(rc, SCVPP_OK); + + //dump ipv4 on tap0 and check if it mach + rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false); + assert_int_equal(rc, SCVPP_OK); + assert_string_equal(ip_q, ip_r); + assert_int_equal(prefix_q, prefix_r); + + //remove ipv4 on tap0 + rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, false); + assert_int_equal(rc, SCVPP_OK); + + //dump ipv4 after removal and check if equals 0.0.0.0 + rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false); + assert_int_equal(rc, SCVPP_OK); + assert_string_equal(ip_r, "0.0.0.0"); +} + +static void test_ipv4_add_del_route_no_iface(void **state) +{ + UNUSED(state); + int rc; + char dst_address[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.0"; + uint8_t prefix_len = 24; + char next_hop[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.100"; + uint32_t table_id = 0; + fib_dump_t *dump; + struct elt *stack; + bool route_found = false; + + /* Must fail, can not have both interface and next hop IP null */ + rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, true, + table_id, NULL); + assert_int_equal(rc, -SCVPP_EINVAL); + + rc = ipv46_config_add_del_route(dst_address, prefix_len, next_hop, true, + table_id, NULL); + assert_int_equal(rc, SCVPP_OK); + + /* Dump all FIB routes and check if we find ours */ + stack = ipv4_fib_dump_all(); + assert_non_null(stack); + foreach_stack_elt(stack) { + dump = (fib_dump_t *) data; + + if (strncmp(sc_ntoa(dump->address), dst_address, + VPP_IP4_ADDRESS_STRING_LEN) == 0 && + dump->address_length == prefix_len) { + route_found = true; + assert_int_equal(dump->table_id, table_id); + assert_int_equal(dump->count, 1); + assert_string_equal(sc_ntoa(dump->path[0].next_hop), next_hop); + } + free(dump); + } + assert_true(route_found); + + /* Delete previously set route */ + rc = ipv46_config_add_del_route(dst_address, prefix_len, next_hop, false, + table_id, NULL); + assert_int_equal(rc, SCVPP_OK); + + /* Check our route has been deleted */ + route_found = false; + stack = ipv4_fib_dump_all(); + assert_non_null(stack); + foreach_stack_elt(stack) { + dump = (fib_dump_t *) data; + if (strncmp(sc_ntoa(dump->address), dst_address, + VPP_IP4_ADDRESS_STRING_LEN) == 0 && + dump->address_length == prefix_len) { + route_found = true; + } + free(dump); + } + assert_false(route_found); +} + +static void test_ipv4_add_del_route_no_next_hop_ip(void **state) +{ + UNUSED(state); + int rc; + char dst_address[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.0"; + uint8_t prefix_len = 24; + char interface[VPP_IP4_ADDRESS_STRING_LEN] = "tap0"; + uint32_t table_id = 0; + uint32_t sw_if_index; + fib_dump_t *dump; + struct elt *stack; + bool route_found = false; + + //Add a new route + rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, true, + table_id, interface); + assert_int_equal(rc, SCVPP_OK); + + //Dump all FIB routes and check we find ours + stack = ipv4_fib_dump_all(); + assert_non_null(stack); + + rc = get_interface_id(interface, &sw_if_index); + assert_int_equal(rc, SCVPP_OK); + + foreach_stack_elt(stack) { + dump = (fib_dump_t *) data; + + if (strncmp(sc_ntoa(dump->address), dst_address, + VPP_IP4_ADDRESS_STRING_LEN) == 0 && + dump->address_length == prefix_len) { + route_found = true; + assert_int_equal(dump->table_id, table_id); + assert_int_equal(dump->count, 1); + assert_int_equal(dump->path[0].sw_if_index, sw_if_index); + } + free(dump); + } + assert_true(route_found); + + //Delete route + rc = ipv46_config_add_del_route(dst_address, prefix_len, NULL, false, + table_id, interface); + assert_int_equal(rc, SCVPP_OK); + + //Check our route has been deleted + route_found = false; + stack = ipv4_fib_dump_all(); + assert_non_null(stack); + + foreach_stack_elt(stack) { + dump = (fib_dump_t *) data; + if (strncmp(sc_ntoa(dump->address), dst_address, + VPP_IP4_ADDRESS_STRING_LEN) == 0 && + dump->address_length == prefix_len) { + route_found = true; + } + free(dump); + } + assert_false(route_found); +} + + +const struct CMUnitTest ip_tests[IP_TEST_SIZE] = { + cmocka_unit_test(test_add_remove_ipv4), + cmocka_unit_test(test_ipv4_add_del_route_no_next_hop_ip), + cmocka_unit_test(test_ipv4_add_del_route_no_iface), +}; diff --git a/src/scvpp/tests/scvpp_nat_test.c b/src/scvpp/tests/scvpp_nat_test.c index fae9615..044102e 100644 --- a/src/scvpp/tests/scvpp_nat_test.c +++ b/src/scvpp/tests/scvpp_nat_test.c @@ -20,36 +20,37 @@ #include <setjmp.h> #include <cmocka.h> -#include "scvpp_nat_test.h" -#include "sc_vpp_comm.h" -#include "sc_vpp_nat.h" +#include "scvpp_test.h" -void test_nat44_static_mapping(__attribute__((unused)) void **state) +#include <scvpp/comm.h> +#include <scvpp/nat.h> + + +void test_nat44_static_mapping(void **state) { + UNUSED(state); nat44_add_del_static_mapping_t map = {0}; nat44_static_mapping_details_t dump = {0}; u8 empty_ip[4] = {0}; + int rc; /*Configure the static mapping Alternative to this CLI command: nat44 add static mapping local 172.168.0.1 external 172.168.8.5 */ - sc_aton("172.168.0.1", map.local_ip_address, sizeof(map.local_ip_address)); - sc_aton("172.168.8.5", map.external_ip_address, sizeof(map.external_ip_address)); - map.addr_only = 1; - map.external_sw_if_index = ~0; - map.is_add = 1; - nat44_add_del_static_mapping(&map); + rc = nat44_add_del_static_mapping(&map); + assert_int_equal(rc, SCVPP_OK); - nat44_static_mapping_dump(&dump); + rc = nat44_static_mapping_dump(&dump); + assert_int_equal(rc, SCVPP_OK); assert_int_equal(dump.addr_only, map.addr_only); @@ -62,11 +63,13 @@ void test_nat44_static_mapping(__attribute__((unused)) void **state) /* Remove previous config*/ map.is_add = 0; - nat44_add_del_static_mapping(&map); + rc = nat44_add_del_static_mapping(&map); + assert_int_equal(rc, SCVPP_OK); memset(&dump, 0, sizeof(dump)); - nat44_static_mapping_dump(&dump); + rc = nat44_static_mapping_dump(&dump); + assert_int_equal(rc, SCVPP_OK); assert_int_equal(dump.addr_only, 0); @@ -77,14 +80,16 @@ void test_nat44_static_mapping(__attribute__((unused)) void **state) sizeof(dump.external_ip_address)); } -void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state) +void test_nat44_static_mapping_with_ports(void **state) { + UNUSED(state); nat44_add_del_static_mapping_t map = {0}; nat44_static_mapping_details_t dump = {0}; nat44_add_del_address_range_t range = {0}; u8 empty_ip[4] = {0}; const u16 lport = 77; const u16 eport = 88; + int rc; /*Configure address pool Alternative to this CLI: @@ -98,7 +103,8 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state) range.is_add = 1; - nat44_add_del_addr_range(&range); + rc = nat44_add_del_addr_range(&range); + assert_int_equal(rc, SCVPP_OK); /*Configure NAT with ports Alternative to this CLI: @@ -122,9 +128,11 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state) map.is_add = 1; - nat44_add_del_static_mapping(&map); + rc = nat44_add_del_static_mapping(&map); + assert_int_equal(rc, SCVPP_OK); - nat44_static_mapping_dump(&dump); + rc = nat44_static_mapping_dump(&dump); + assert_int_equal(rc, SCVPP_OK); assert_int_equal(dump.addr_only, map.addr_only); @@ -142,11 +150,13 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state) map.is_add = 0; - nat44_add_del_static_mapping(&map); + rc = nat44_add_del_static_mapping(&map); + assert_int_equal(rc, SCVPP_OK); memset(&dump, 0, sizeof(dump)); - nat44_static_mapping_dump(&dump); + rc = nat44_static_mapping_dump(&dump); + assert_int_equal(rc, SCVPP_OK); assert_int_equal(dump.addr_only, 0); @@ -162,7 +172,8 @@ void test_nat44_static_mapping_with_ports(__attribute__((unused)) void **state) range.is_add = 0; - nat44_add_del_addr_range(&range); + rc = nat44_add_del_addr_range(&range); + assert_int_equal(rc, SCVPP_OK); } const struct CMUnitTest nat_tests[] = { diff --git a/src/scvpp/tests/scvpp_test.c b/src/scvpp/tests/scvpp_test.c index cc23e43..f6e99a0 100644 --- a/src/scvpp/tests/scvpp_test.c +++ b/src/scvpp/tests/scvpp_test.c @@ -14,89 +14,19 @@ */ #include <stdlib.h> -#include <stdio.h> #include <unistd.h> +#include <stdio.h> #include <setjmp.h> -#include <cmocka.h> - -#include "sc_vpp_comm.h" -#include "sc_vpp_interface.h" -#include "sc_vpp_ip.h" -#include "sc_vpp_v3po.h" -#include "scvpp_nat_test.h" - -//TODO Check with future function get_interface_state -static void test_enable_disable(void **state) -{ - int rc; - - rc = interface_enable("tap0", 1); - assert_int_equal(rc, 0); - - rc = interface_enable("tap0", 0); - assert_int_equal(rc, 0); -} - -//TODO would need to make sure tap0 is index 1 -//TODO delete eventually because get_interface_id will not be extern -static void test_name2index(void **state) -{ - int rc; - const char iface_name[] = "tap0"; - sw_interface_details_query_t query = {0}; - sw_interface_details_query_set_name(&query, iface_name); - - rc = get_interface_id(&query); - assert_int_equal(rc, 1); - - assert_string_equal(iface_name, query.sw_interface_details.interface_name); - assert_int_equal(query.sw_interface_details.sw_if_index, 1); -} - -static void test_add_ipv4(void **state) -{ - const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144"; - char ip_r[VPP_IP4_ADDRESS_STRING_LEN]; - u8 prefix_q = 24; - u8 prefix_r; - int rc; - - //add ipv4 on tap0 - rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true); - assert_int_equal(rc, 0); - - rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false); - assert_int_equal(rc, 0); - - assert_string_equal(ip_q, ip_r); - assert_int_equal(prefix_q, prefix_r); -} - -static void test_remove_ipv4(void **state) -{ - const char ip_q[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.144"; - char ip_r[VPP_IP4_ADDRESS_STRING_LEN]; - u8 prefix_q = 24; - u8 prefix_r; - int rc; - - //add ipv4 on tap0 - rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, true); - assert_int_equal(rc, 0); - //remove ipv4 on tap0 - rc = ipv46_config_add_remove("tap0", ip_q, prefix_q, false, false); - assert_int_equal(rc, 0); - - //dump ipv4 - rc = ipv46_address_dump("tap0", ip_r, &prefix_r, false); - assert_int_equal(rc, 0); +#include <scvpp/comm.h> +#include <scvpp/v3po.h> - assert_string_equal(ip_r, "0.0.0.0"); -} +#include "scvpp_test.h" +/* test "AAA.BBB.CCC.DDD" -> {A, B, C, D} */ static void test_sc_ntoa(void **state) { + UNUSED(state); u8 buf[4] = {192, 168, 100, 44}; char *res; @@ -104,52 +34,76 @@ static void test_sc_ntoa(void **state) assert_string_equal(res, "192.168.100.44"); } -static void test_create_tapv2(void **state) +/* test {A, B, C, D} -> "AAA.BBB.CCC.DDD" */ +static void test_sc_aton(void **state) { - tapv2_create_t query = {0}; + UNUSED(state); + char ip[VPP_IP4_ADDRESS_STRING_LEN] = "192.168.100.44"; + uint8_t buf[4]; int rc; - query.id = 1; - query.use_random_mac = 1; - - rc = create_tapv2(&query); + rc = sc_aton(ip, buf, VPP_IP4_ADDRESS_LEN); assert_int_equal(rc, 0); - //TODO dump_tav2 and compare values - - rc = delete_tapv2("tap1"); - assert_int_equal(rc, 0); + assert_int_equal(buf[0], 192); + assert_int_equal(buf[1], 168); + assert_int_equal(buf[2], 100); + assert_int_equal(buf[3], 44); } -int main() +static int setup(void **state) { + UNUSED(state); tapv2_create_t query = {0}; - const struct CMUnitTest tests[] = { - cmocka_unit_test_setup_teardown(test_enable_disable, NULL, NULL), - cmocka_unit_test_setup_teardown(test_name2index, NULL, NULL), - cmocka_unit_test_setup_teardown(test_add_ipv4, NULL, NULL), - cmocka_unit_test_setup_teardown(test_remove_ipv4, NULL, NULL), - cmocka_unit_test_setup_teardown(test_sc_ntoa, NULL, NULL), - cmocka_unit_test_setup_teardown(test_create_tapv2, NULL, NULL), - }; - if (sc_connect_vpp() != 0) + if (sc_connect_vpp() != 0) { fprintf(stderr, "Error connecting to VPP\n"); + return -1; + } /* Create interface tap0 to test several functions */ query.id = 0; query.use_random_mac = 1; - if (create_tapv2(&query) != 0) + if (create_tapv2(&query) != 0) { fprintf(stderr, "Error creating tap0\n"); + return -1; + } - cmocka_run_group_tests(tests, NULL, NULL); - - print_message("\nNAT Tests\n"); - cmocka_run_group_tests(nat_tests, NULL, NULL); + return 0; +} +static int teardown(void **state) +{ + UNUSED(state); /* Delete tap0 */ - if (delete_tapv2("tap0") != 0) + if (delete_tapv2("tap0") != 0) { fprintf(stderr, "Failed deleting tap0\n"); + return -1; + } + + sc_disconnect_vpp(); + + return 0; +} + +/* return code for scvpp-test binary is the number of failed test */ +int main() +{ + int rc = 0; + + const struct CMUnitTest common_tests[] = { + cmocka_unit_test(test_sc_ntoa), + cmocka_unit_test(test_sc_aton), + }; + + print_message("Common tests\n"); + rc |= cmocka_run_group_tests(common_tests, NULL, NULL); + print_message("Interface tests\n"); + rc |= cmocka_run_group_tests(iface_tests, setup, teardown); + print_message("IP tests\n"); + rc |= cmocka_run_group_tests(ip_tests, setup, teardown); + print_message("NAT tests\n"); + rc |= cmocka_run_group_tests(nat_tests, setup, teardown); - return sc_disconnect_vpp(); + return rc; } diff --git a/src/scvpp/tests/scvpp_nat_test.h b/src/scvpp/tests/scvpp_test.h index 8a22f87..28bd514 100644 --- a/src/scvpp/tests/scvpp_nat_test.h +++ b/src/scvpp/tests/scvpp_test.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 PANTHEON.tech. + * Copyright (c) 2019 Cisco * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +14,18 @@ * limitations under the License. */ -/* inclusion guard */ -#ifndef __SCVPP_NAT_TEST_H__ -#define __SCVPP_NAT_TEST_H__ +#ifndef __SCVPP_TEST_H +#define __SCVPP_TEST_H__ + +#include <cmocka.h> + +#define IFACE_TEST_SIZE 6 +extern const struct CMUnitTest iface_tests[IFACE_TEST_SIZE]; + +#define IP_TEST_SIZE 3 +extern const struct CMUnitTest ip_tests[IP_TEST_SIZE]; #define NAT_TEST_SIZE 2 extern const struct CMUnitTest nat_tests[NAT_TEST_SIZE]; -#endif /* __SCVPP_NAT_TEST_H__ */ +#endif /* __SCVPP_TEST_H__ */ |