From c405a5bb3a2299c34f11431be477a228715e66fa Mon Sep 17 00:00:00 2001 From: Masoud Hemmatpour Date: Fri, 8 Mar 2019 13:40:22 +0100 Subject: [HICN-90] adding hicn-light to sysrepo-plugins Change-Id: Icd92adb21661d33b0cd40ea8c3dd748f0fa97aaf Signed-off-by: Masoud Hemmatpour Signed-off-by: Luca Muscariello Signed-off-by: Masoud Hemmatpour --- .../hicn-plugin/plugin/hicn_plugin.c | 123 ++ .../hicn-plugin/plugin/hicn_plugin.h | 25 + .../hicn-plugin/plugin/hicn_vpp_comm.c | 53 + .../hicn-plugin/plugin/hicn_vpp_comm.h | 119 ++ .../hicn-plugin/plugin/ietf/ietf_interface.c | 597 +++++++++ .../hicn-plugin/plugin/ietf/ietf_interface.h | 25 + .../hicn-plugin/plugin/model/hicn_model.c | 1323 ++++++++++++++++++++ .../hicn-plugin/plugin/model/hicn_model.h | 90 ++ .../hicn-plugin/plugin/model/tlock.c | 21 + .../hicn-plugin/plugin/model/tlock.h | 31 + .../plugin/yang/controler_rpcs_instances.xml | 76 ++ .../hicn-plugin/plugin/yang/model/hicn.yang | 536 ++++++++ .../hicn-plugin/plugin/yang/startup.xml | 11 + 13 files changed, 3030 insertions(+) create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/yang/controler_rpcs_instances.xml create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/yang/model/hicn.yang create mode 100644 utils/sysrepo-plugins/hicn-plugin/plugin/yang/startup.xml (limited to 'utils/sysrepo-plugins/hicn-plugin/plugin') diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c new file mode 100644 index 000000000..262e98553 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2019 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 +#include +#include +#include +#include + +#include "hicn_plugin.h" +#include "model/hicn_model.h" +#include "ietf/ietf_interface.h" + + +sr_subscription_ctx_t *subscription = NULL; +volatile int exit_application = 0; + +int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) { + HICN_INVOKE_BEGIN; + sr_subscription_ctx_t *subscription = NULL; + int rc = SR_ERR_OK; + rc = hicn_connect_vpp(); + if (SR_ERR_OK != rc) { + HICN_LOG_ERR("vpp connect error , with return %d.", rc); + return SR_ERR_INTERNAL; + } + + // HICN subscribe + hicn_subscribe_events(session, &subscription); + + // IETF subscribe + ietf_subscribe_events(session, &subscription); + + + /* set subscription as our private context */ + *private_ctx = subscription; + HICN_INVOKE_END; + return SR_ERR_OK; +} + +void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx) { + HICN_INVOKE_BEGIN; + + /* subscription was set as our private context */ + sr_unsubscribe(session, private_ctx); + HICN_LOG_DBG_MSG("hicn pligin unload plugin ok."); + hicn_disconnect_vpp(); + HICN_LOG_DBG_MSG("hicn plugin disconnect vpp ok."); + HICN_INVOKE_END; +} + +static void sigint_handler(int signum) { exit_application = 1; } +int subscribe_all_module_events(sr_session_ctx_t *session) { + sr_plugin_init_cb(session, (void **)&subscription); + return 0; +} + +int main(int argc, char **argv) { + sr_conn_ctx_t *connection = NULL; + sr_session_ctx_t *session = NULL; + int rc = SR_ERR_OK; + /* connect to vpp */ + rc = hicn_connect_vpp(); + if (-1 == rc) { + fprintf(stderr, "vpp connect error"); + return -1; + } + + /* connect to sysrepo */ + rc = sr_connect("cpe_application", SR_CONN_DEFAULT, &connection); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_connect: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* start session */ + rc = sr_session_start(connection, SR_DS_STARTUP, SR_SESS_DEFAULT, &session); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by sr_session_start: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* subscribe all module events */ + rc = subscribe_all_module_events(session); + if (SR_ERR_OK != rc) { + fprintf(stderr, "Error by subscribe module events: %s\n", sr_strerror(rc)); + goto cleanup; + } + + /* loop until ctrl-c is pressed / SIGINT is received */ + signal(SIGINT, sigint_handler); + signal(SIGPIPE, SIG_IGN); + + while (!exit_application) { + sleep(2); + } + + printf("Application exit requested, exiting.\n"); + +cleanup: + if (NULL != subscription) { + sr_unsubscribe(session, subscription); + } + if (NULL != session) { + sr_session_stop(session); + } + if (NULL != connection) { + sr_disconnect(connection); + } + hicn_disconnect_vpp(); + return rc; +} \ No newline at end of file diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h new file mode 100644 index 000000000..4e48c8c29 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019 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 __HICN_PLUGIN_H__ +#define __HICN_PLUGIN_H__ + +#include "hicn_vpp_comm.h" + +// functions that sysrepo-plugin need +int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx); +void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx); + +#endif //__HICN_PLUGIN_H__ \ No newline at end of file diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c new file mode 100644 index 000000000..2add127f2 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019 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 "hicn_vpp_comm.h" + + + + +#define APP_NAME "hicn_plugin" +#define MAX_OUTSTANDING_REQUESTS 4 +#define RESPONSE_QUEUE_SIZE 2 +vapi_ctx_t g_vapi_ctx_instance=NULL; +DEFINE_VAPI_MSG_IDS_HICN_API_JSON; + +int hicn_connect_vpp() { + HICN_INVOKE_BEGIN; + if (g_vapi_ctx_instance == NULL) { + vapi_error_e rv = vapi_ctx_alloc(&g_vapi_ctx_instance); + rv = vapi_connect(g_vapi_ctx_instance, APP_NAME, NULL, + MAX_OUTSTANDING_REQUESTS, RESPONSE_QUEUE_SIZE, + VAPI_MODE_BLOCKING, true); + if (rv != VAPI_OK) { + HICN_LOG_ERR("*connect %s faild,with return %d", APP_NAME, rv); + vapi_ctx_free(g_vapi_ctx_instance); + return -1; + } + HICN_LOG_DBG("*connected %s ok", APP_NAME); + } else { + HICN_LOG_DBG("connection %s keeping", APP_NAME); + } + HICN_INVOKE_END; + return 0; +} + +int hicn_disconnect_vpp() { + if (NULL != g_vapi_ctx_instance) { + vapi_disconnect(g_vapi_ctx_instance); + vapi_ctx_free(g_vapi_ctx_instance); + g_vapi_ctx_instance = NULL; + } + return 0; +} \ No newline at end of file diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h new file mode 100644 index 000000000..aff8e2ea1 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2019 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 __HICN_VPP_COMMM_H__ +#define __HICN_VPP_COMMM_H__ +#include +#include //for HICN_LOG_DBG +#include +#include + +#ifndef HICN_THIS_FUNC +#ifdef __FUNCTION__ +#define HICN_THIS_FUNC __FUNCTION__ +#else +#define HICN_THIS_FUNC __func__ +#endif +#endif + +#ifndef _NOLOG +#define HICN_LOG_DBG SRP_LOG_DBG +#define HICN_LOG_ERR SRP_LOG_ERR +#define HICN_LOG_DBG_MSG SRP_LOG_DBG_MSG +#define HICN_LOG_ERR_MSG SRP_LOG_ERR_MSG +#else +#define HICN_LOG_DBG // printf +#define HICN_LOG_DBG // SRP_LOG_DBG +#define HICN_LOG_ERR // SRP_LOG_ERR +#define HICN_LOG_DBG_MSG // SRP_LOG_DBG_MSG +#define HICN_LOG_ERR_MSG // SRP_LOG_ERR_MSG +#endif + +//DEFINE_VAPI_MSG_IDS_VPE_API_JSON + +DEFINE_VAPI_MSG_IDS_HICN_API_JSON; +// ctx vpp connect +extern vapi_ctx_t g_vapi_ctx_instance; + +//Here it is the definition + +#define VPP_INTFC_NAME_LEN 64 +#define VPP_MAC_ADDRESS_LEN 8 +#define VPP_IP6_ADDRESS_LEN 16 +#define HICN_INVOKE_BEGIN HICN_LOG_DBG("inovke %s bein.", HICN_THIS_FUNC); +#define HICN_INVOKE_END \ + HICN_LOG_DBG("inovke %s end,with return OK.", HICN_THIS_FUNC); +#define HICN_INVOKE_ENDX(...) \ + HICN_LOG_DBG("inovke %s end,with %s.", HICN_THIS_FUNC, ##__VA_ARGS__) + +#define ARG_CHECK(retval, arg) \ + do { \ + if (NULL == (arg)) { \ + HICN_LOG_ERR_MSG(#arg ":NULL pointer passed."); \ + return (retval); \ + } \ + } while (0) + + + +#define ARG_CHECK2(retval, arg1, arg2) \ + ARG_CHECK(retval, arg1); \ + ARG_CHECK(retval, arg2) + +#define ARG_CHECK5(retval, arg1, arg2, arg3, arg4, arg5) \ + ARG_CHECK(retval, arg1); \ + ARG_CHECK(retval, arg2); \ + ARG_CHECK(retval, arg3); \ + ARG_CHECK(retval, arg4); \ + ARG_CHECK(retval, arg5) + + + +/** + * when use tihs must fist DEFINE_VAPI_MSG_IDS_VXLAN_API_JSON + */ +#define HICN_VPP_VAPI_RECV \ + do { \ + size_t size; \ + int recv_vapimsgid = -1; \ + vapi_recv(g_vapi_ctx_instance, (void *)&resp, &size, 0, 0); \ + recv_vapimsgid = vapi_lookup_vapi_msg_id_t( \ + g_vapi_ctx_instance, ntohs(resp->header._vl_msg_id)); \ + if (recv_vapimsgid <= vapi_msg_id_get_next_index_reply || \ + recv_vapimsgid >= vapi_get_message_count()) { \ + HICN_LOG_DBG("***recv error msgid[%d] not in [0-%d) ,try again!***\n", \ + recv_vapimsgid, vapi_get_message_count()); \ + } else { \ + HICN_LOG_DBG("recv msgid [%d]\n", recv_vapimsgid); \ + break; \ + } \ + } while (1); + +#define HICN_REGISTER_RPC_EVT_HANDLER(rpc_evt_handle) \ + do { \ + sr_error_t rc = rpc_evt_handle(session, &subscription); \ + if (SR_ERR_OK != rc) { \ + HICN_LOG_ERR("load plugin failed: %s", sr_strerror(rc)); \ + sr_unsubscribe(session, subscription); \ + HICN_INVOKE_ENDX(sr_strerror(rc)); \ + return rc; \ + } \ + } while (0); + + +int hicn_connect_vpp(); +int hicn_disconnect_vpp(); + +#endif //__HICN_VPP_COMMM_H__ \ No newline at end of file diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c b/utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c new file mode 100644 index 000000000..f02605895 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c @@ -0,0 +1,597 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ietf_interface.h" +#include "../hicn_vpp_comm.h" + + + +DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON; + +typedef struct hicn_interface_ +{ + 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; +} hicnIntfc; + +typedef struct _ietf_sw_interface_dump_ctx +{ + u8 last_called; + int num_ifs; + int capacity; + hicnIntfc * intfcArray; +} ietf_sw_interface_dump_ctx; + +static i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down); +static i32 ietf_interface_name2index(const char *name, u32* if_index); +static i32 ietf_interface_add_del_addr(u32 sw_if_index, u8 is_add, u8 is_ipv6, + u8 del_all, u8 address_length, + u8 address[VPP_IP6_ADDRESS_LEN]); +static int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx); +static int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx); + +/** + * @brief Helper function for converting netmask into prefix length. + */ +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; +} + +/** + * @brief Helper function for converting IPv4/IPv6 address string into binary representation. + */ +static int +ip_addr_str_to_binary(const char *ip_address_str, uint8_t *ip_address_bin, bool is_ipv6) +{ + struct in6_addr addr6 = { 0, }; + struct in_addr addr4 = { 0, }; + int ret = 0; + + if (is_ipv6) { + ret = inet_pton(AF_INET6, ip_address_str, &(addr6)); + if (1 == ret) + { + memcpy(ip_address_bin, &addr6, sizeof(addr6)); + } + } else { + ret = inet_pton(AF_INET, ip_address_str, &(addr4)); + if (1 == ret) + { + memcpy(ip_address_bin, &addr4, sizeof(addr4)); + } + } + + return ret; +} + +/** + * @brief Enable or disable given interface. + */ +static int +interface_enable_disable(const char *if_name, bool enable) +{ + uint32_t if_index = ~0; + int rc = 0; + + SRP_LOG_DBG("%s interface '%s'", enable ? "Enabling" : "Disabling", if_name); + + /* get interface index */ + rc = ietf_interface_name2index(if_name, &if_index); + if (0 != rc) { + SRP_LOG_ERR("Invalid interface name: %s", if_name); + return SR_ERR_INVAL_ARG; + } + + /* enable/disable interface */ + rc = ietf_setInterfaceFlags(if_index, (uint8_t)enable); + if (0 != rc) { + SRP_LOG_ERR("Error by processing of the sw_interface_set_flags request, rc=%d", rc); + return SR_ERR_OPERATION_FAILED; + } else { + return SR_ERR_OK; + } +} + +/** + * @brief Callback to be called by any config change of "/ietf-interfaces:interfaces/interface/enabled" leaf. + */ +static int +ietf_interface_enable_disable_cb(sr_session_ctx_t *session, const char *xpath, sr_notif_event_t event, void *private_ctx) +{ + char *if_name = NULL; + sr_change_iter_t *iter = NULL; + sr_change_oper_t op = SR_OP_CREATED; + sr_val_t *old_val = NULL; + sr_val_t *new_val = NULL; + sr_xpath_ctx_t xpath_ctx = { 0, }; + int rc = SR_ERR_OK, op_rc = SR_ERR_OK; + + /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */ + 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) { + 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)))) { + + 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); + switch (op) { + case SR_OP_CREATED: + case SR_OP_MODIFIED: + op_rc = interface_enable_disable(if_name, new_val->data.bool_val); + break; + case SR_OP_DELETED: + op_rc = interface_enable_disable(if_name, false /* !enable */); + break; + default: + break; + } + sr_xpath_recover(&xpath_ctx); + if (SR_ERR_INVAL_ARG == op_rc) { + sr_set_error(session, "Invalid interface name.", new_val ? new_val->xpath : old_val->xpath); + } + sr_free_val(old_val); + sr_free_val(new_val); + } + sr_free_change_iter(iter); + + return op_rc; +} + +/** + * @brief Add or remove IPv4/IPv6 address to/from an interface. + */ +static int +interface_ipv46_config_add_remove(const char *if_name, uint8_t *addr, uint8_t prefix, bool is_ipv6, bool add) +{ + uint32_t if_index = ~0; + int rc = 0; + + SRP_LOG_DBG("%s IP config on interface '%s'.", add ? "Adding" : "Removing", if_name); + + /* get interface index */ + rc = ietf_interface_name2index(if_name, &if_index); + if (0 != rc) { + SRP_LOG_ERR("Invalid interface name: %s", if_name); + return SR_ERR_INVAL_ARG; + } + + /* add del addr */ + rc = ietf_interface_add_del_addr(if_index, (uint8_t)add, (uint8_t)is_ipv6, 0, prefix, addr); + if (0 != rc) { + SRP_LOG_ERR("Error by processing of the sw_interface_set_flags request, rc=%d", rc); + return SR_ERR_OPERATION_FAILED; + } else { + return SR_ERR_OK; + } +} +int ietf_initSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx) +{ + if(dctx == NULL) + return -1; + + dctx->intfcArray = NULL; + dctx->last_called = false; + dctx->capacity = 0; + dctx->num_ifs = 0; + return 0; +} +int ietf_freeSwInterfaceDumpCTX(ietf_sw_interface_dump_ctx * dctx) +{ + if(dctx == NULL) + return -1; + + if(dctx->intfcArray != NULL) + { + free(dctx->intfcArray); + } + + return ietf_initSwInterfaceDumpCTX(dctx); +} +vapi_error_e +ietf_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) +{ + ietf_sw_interface_dump_ctx *dctx = callback_ctx; + if (is_last) + { + dctx->last_called = true; + } + else + { + if(dctx->capacity == 0 && dctx->intfcArray == NULL) + { + dctx->capacity = 10; + dctx->intfcArray = (hicnIntfc*)malloc( sizeof(hicnIntfc)*dctx->capacity ); + } + if(dctx->num_ifs >= dctx->capacity-1) + { + + dctx->capacity += 10; + dctx->intfcArray = (hicnIntfc*)realloc(dctx->intfcArray, sizeof(hicnIntfc)*dctx->capacity ); + } + + hicnIntfc * thisIntfc = &dctx->intfcArray[dctx->num_ifs]; + + thisIntfc->sw_if_index = reply->sw_if_index; + memcpy(thisIntfc->interface_name, reply->interface_name, VPP_INTFC_NAME_LEN); + thisIntfc->l2_address_length = reply->l2_address_length; + memcpy(thisIntfc->l2_address, reply->l2_address, reply->l2_address_length ); + //thisIntfc->link_speed = reply->link_speed; +#define ONE_MEGABIT (uint64_t)1000000 + switch (reply->link_speed << VNET_HW_INTERFACE_FLAG_SPEED_SHIFT) + { + default: + thisIntfc->link_speed = 0; + break; + } + + thisIntfc->link_mtu = reply->link_mtu; + thisIntfc->admin_up_down = reply->admin_up_down; + thisIntfc->link_up_down = reply->link_up_down; + + dctx->num_ifs += 1; + } + return VAPI_OK; +} + +static i32 ietf_interface_name2index(const char *name, u32* if_index) +{ + ARG_CHECK2(-1, name, if_index); + + i32 ret = -1; + ietf_sw_interface_dump_ctx dctx = {false, 0, 0, 0}; + vapi_msg_sw_interface_dump *dump; + vapi_error_e rv; + dctx.last_called = false; + + dump = vapi_alloc_sw_interface_dump(g_vapi_ctx_instance); + dump->payload.name_filter_valid = true; + memcpy(dump->payload.name_filter, name, sizeof(dump->payload.name_filter)); + + while (VAPI_EAGAIN == (rv = vapi_sw_interface_dump(g_vapi_ctx_instance, dump, ietf_sw_interface_dump_cb, &dctx))) + ; + + int i = 0; + for (; i < dctx.num_ifs; ++i) + { + if (strcmp(dctx.intfcArray[i].interface_name, name) == 0) + { + *if_index = dctx.intfcArray[i].sw_if_index; + ret = 0; + break; + } + } + ietf_freeSwInterfaceDumpCTX(&dctx); + + return ret; +} + +i32 ietf_interface_add_del_addr( u32 sw_if_index, u8 is_add, u8 is_ipv6, u8 del_all, + u8 address_length, u8 address[VPP_IP6_ADDRESS_LEN] ) +{ + i32 ret = -1; + vapi_msg_sw_interface_add_del_address *msg = vapi_alloc_sw_interface_add_del_address(g_vapi_ctx_instance); + msg->payload.sw_if_index = sw_if_index; + msg->payload.is_add = is_add; + msg->payload.is_ipv6 = is_ipv6; + msg->payload.del_all = del_all; + msg->payload.address_length = address_length; + memcpy(msg->payload.address, address, VPP_IP6_ADDRESS_LEN); + vapi_msg_sw_interface_add_del_address_hton (msg); + + vapi_send (g_vapi_ctx_instance, msg); + + vapi_msg_sw_interface_add_del_address_reply *resp; + + HICN_VPP_VAPI_RECV; + + vapi_msg_sw_interface_add_del_address_reply_hton(resp); + ret = resp->payload.retval; + vapi_msg_free (g_vapi_ctx_instance, resp); + return ret; +} + +i32 ietf_setInterfaceFlags(u32 sw_if_index, u8 admin_up_down) +{ + i32 ret = -1; + vapi_msg_sw_interface_set_flags *msg = vapi_alloc_sw_interface_set_flags(g_vapi_ctx_instance); + msg->payload.sw_if_index = sw_if_index; + msg->payload.admin_up_down = admin_up_down; + vapi_msg_sw_interface_set_flags_hton (msg); + + vapi_send (g_vapi_ctx_instance, msg); + + vapi_msg_sw_interface_set_flags_reply *resp; + + HICN_VPP_VAPI_RECV; + + vapi_msg_sw_interface_set_flags_reply_ntoh(resp); + ret = resp->payload.retval; + vapi_msg_free (g_vapi_ctx_instance, resp); + return ret; +} + + +/** + * @brief Modify existing IPv4/IPv6 config on an interface. + */ +static int +interface_ipv46_config_modify(sr_session_ctx_t *session, const char *if_name, + sr_val_t *old_val, sr_val_t *new_val, bool is_ipv6) +{ + sr_xpath_ctx_t xpath_ctx = { 0, }; + char *addr_str = NULL; + uint8_t addr[16] = { 0, }; + uint8_t prefix = 0; + int rc = SR_ERR_OK; + + SRP_LOG_DBG("Updating IP config on interface '%s'.", if_name); + + /* get old config to be deleted */ + if (SR_UINT8_T == old_val->type) { + prefix = old_val->data.uint8_val; + } else if (SR_STRING_T == old_val->type) { + prefix = netmask_to_prefix(old_val->data.string_val); + } else { + return SR_ERR_INVAL_ARG; + } + addr_str = sr_xpath_key_value((char*)old_val->xpath, "address", "ip", &xpath_ctx); + ip_addr_str_to_binary(addr_str, addr, is_ipv6); + sr_xpath_recover(&xpath_ctx); + + /* delete old IP config */ + rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, false /* remove */); + if (SR_ERR_OK != rc) { + SRP_LOG_ERR("Unable to remove old IP address config, rc=%d", rc); + return rc; + } + + /* update the config with the new value */ + if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) { + prefix = new_val->data.uint8_val; + } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) { + prefix = netmask_to_prefix(new_val->data.string_val); + } + + /* set new IP config */ + rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, true /* add */); + if (SR_ERR_OK != rc) { + SRP_LOG_ERR("Unable to remove old IP address config, rc=%d", rc); + return rc; + } + + return rc; +} + +/** + * @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 +ietf_interface_ipv46_address_change_cb(sr_session_ctx_t *session, const char *xpath, sr_notif_event_t event, void *private_ctx) +{ + sr_change_iter_t *iter = NULL; + sr_change_oper_t op = SR_OP_CREATED; + sr_val_t *old_val = NULL; + sr_val_t *new_val = NULL; + sr_xpath_ctx_t xpath_ctx = { 0, }; + bool is_ipv6 = false, has_addr = false, has_prefix = false; + uint8_t addr[16] = { 0, }; + uint8_t prefix = 0; + char *node_name = NULL, *if_name = NULL; + int rc = SR_ERR_OK, op_rc = SR_ERR_OK; + + /* no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, SR_EV_ABORT */ + if (SR_EV_APPLY == event) { + return SR_ERR_OK; + } + SRP_LOG_DBG("'%s' modified, event=%d", xpath, event); + + /* check whether we are handling ipv4 or ipv6 config */ + node_name = sr_xpath_node_idx((char*)xpath, 2, &xpath_ctx); + if (NULL != node_name && 0 == strcmp(node_name, "ipv6")) { + is_ipv6 = true; + } + sr_xpath_recover(&xpath_ctx); + + /* get changes iterator */ + rc = sr_get_changes_iter(session, xpath, &iter); + if (SR_ERR_OK != rc) { + 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)))) { + + 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)); + sr_xpath_recover(&xpath_ctx); + + switch (op) { + case SR_OP_CREATED: + if (SR_LIST_T == new_val->type) { + /* create on list item - reset state vars */ + has_addr = has_prefix = false; + } else { + if (sr_xpath_node_name_eq(new_val->xpath, "ip")) { + ip_addr_str_to_binary(new_val->data.string_val, addr, is_ipv6); + has_addr = true; + } else if (sr_xpath_node_name_eq(new_val->xpath, "prefix-length")) { + prefix = new_val->data.uint8_val; + has_prefix = true; + } else if (sr_xpath_node_name_eq(new_val->xpath, "netmask")) { + prefix = netmask_to_prefix(new_val->data.string_val); + has_prefix = true; + } + if (has_addr && has_prefix) { + op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, true /* add */); + } + } + break; + case SR_OP_MODIFIED: + op_rc = interface_ipv46_config_modify(session, if_name, old_val, new_val, is_ipv6); + break; + case SR_OP_DELETED: + if (SR_LIST_T == old_val->type) { + /* delete on list item - reset state vars */ + has_addr = has_prefix = false; + } else { + if (sr_xpath_node_name_eq(old_val->xpath, "ip")) { + ip_addr_str_to_binary(old_val->data.string_val, addr, is_ipv6); + has_addr = true; + } else if (sr_xpath_node_name_eq(old_val->xpath, "prefix-length")) { + prefix = old_val->data.uint8_val; + has_prefix = true; + } else if (sr_xpath_node_name_eq(old_val->xpath, "netmask")) { + prefix = netmask_to_prefix(old_val->data.string_val); + has_prefix = true; + } + if (has_addr && has_prefix) { + op_rc = interface_ipv46_config_add_remove(if_name, addr, prefix, is_ipv6, false /* !add */); + } + } + break; + default: + break; + } + if (SR_ERR_INVAL_ARG == op_rc) { + sr_set_error(session, "Invalid interface name.", new_val ? new_val->xpath : old_val->xpath); + } + free(if_name); + sr_free_val(old_val); + sr_free_val(new_val); + } + sr_free_change_iter(iter); + + return op_rc; +} + +/** + * @brief Callback to be called by any config change under "/ietf-interfaces:interfaces-state/interface" path. + * Does not provide any functionality, needed just to cover not supported config leaves. + */ +static int +ietf_interface_change_cb(sr_session_ctx_t *session, const char *xpath, sr_notif_event_t event, void *private_ctx) +{ + SRP_LOG_DBG("'%s' modified, event=%d", xpath, event); + + return SR_ERR_OK; +} + + +int ietf_subscribe_events(sr_session_ctx_t *session, + sr_subscription_ctx_t **subscription){ + + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Subscriging ietf."); + + // + rc = sr_subtree_change_subscribe(session, "/ietf-interfaces:interfaces/interface", ietf_interface_change_cb, + NULL, + 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, subscription); + + if (rc != SR_ERR_OK) { + SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces/interface\n"); + goto error; + } + + rc = sr_subtree_change_subscribe(session, "/ietf-interfaces:interfaces/interface/enabled", ietf_interface_enable_disable_cb, + NULL, + 100, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, subscription); + if (rc != SR_ERR_OK) { + SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces/interface/enabled\n"); + goto error; + } + + rc = sr_subtree_change_subscribe(session, "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", ietf_interface_ipv46_address_change_cb, + NULL, + 99, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, subscription); + + if (rc != SR_ERR_OK) { + SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address\n"); + goto error; + } + + rc = sr_subtree_change_subscribe(session, "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", ietf_interface_ipv46_address_change_cb, + NULL, + 98, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, subscription); + + if (rc != SR_ERR_OK) { + SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address\n"); + goto error; + } + + /* rc = sr_dp_get_items_subscribe(session, "/ietf-interfaces:interfaces-state", ietf_interface_state_cb, + NULL, SR_SUBSCR_CTX_REUSE, + subscription); + if (rc != SR_ERR_OK) { + SRP_LOG_DBG_MSG("Problem in subscription /ietf-interfaces:interfaces-state\n"); + goto error; + }*/ + + + SRP_LOG_INF_MSG("ietf initialized successfully."); + return SR_ERR_OK; + + error: + SRP_LOG_ERR_MSG("Error by initialization of the ietf."); + return rc; +} diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h b/utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h new file mode 100644 index 000000000..dec789853 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h @@ -0,0 +1,25 @@ +/* + * 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" + +int ietf_subscribe_events(sr_session_ctx_t *session, + sr_subscription_ctx_t **subscription); + + +#endif /* __IETF_INTERFACE_H__ */ diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c b/utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c new file mode 100644 index 000000000..340d403fb --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c @@ -0,0 +1,1323 @@ +/* + * Copyright (c) 2019 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 +#include +#include +#include +/* Hicn headers */ + +#include +#include +#include "../hicn_plugin.h" +#include "../hicn_vpp_comm.h" +#include "hicn_model.h" +#include "tlock.h" + + +//vapi_ctx_t g_vapi_ctx_instance=NULL; + +// Shared local variables between state and RPCs + +volatile hicn_state_t * hicn_state = NULL; +volatile hicn_strategy_t * hicn_strategy = NULL; +volatile hicn_strategies_t * hicn_strategies =NULL; +volatile hicn_route_t * hicn_route = NULL; +volatile hicn_face_ip_params_t * hicn_face_ip_params = NULL; + +static int init_buffer(void){ + + hicn_state = memalign(MEM_ALIGN, sizeof(hicn_state_t) ); + memset((hicn_state_t *)hicn_state, 0 , sizeof(hicn_state_t) ); + hicn_strategy = memalign(MEM_ALIGN, sizeof(hicn_strategy_t) ); + memset((hicn_strategy_t *) hicn_strategy, 0 , sizeof(hicn_strategy_t) ); + hicn_strategies = memalign(MEM_ALIGN, sizeof(hicn_strategies_t) ); + memset((hicn_strategies_t *) hicn_strategies, 0 , sizeof(hicn_strategies_t) ); + hicn_route = memalign(MEM_ALIGN, sizeof(hicn_route_t) ); + memset((hicn_route_t *) hicn_route, 0 , sizeof(hicn_route_t) ); + hicn_face_ip_params = memalign(MEM_ALIGN, sizeof(hicn_face_ip_params_t) ); + memset((hicn_face_ip_params_t *) hicn_face_ip_params, 0 , sizeof(hicn_face_ip_params_t) ); + int retval=-1; + ARG_CHECK5(retval, hicn_state, hicn_strategy, hicn_strategies, hicn_route, hicn_face_ip_params); + retval=0; + return retval; +} + + static inline void state_update(sr_val_t * vals ){ + sr_val_set_xpath(&vals[0], "/hicn:hicn-state/states/pkts_processed"); + vals[0].type = SR_UINT64_T; + vals[0].data.uint64_val = hicn_state->pkts_processed; + + sr_val_set_xpath(&vals[1], "/hicn:hicn-state/states/pkts_interest_count"); + vals[1].type = SR_UINT64_T; + vals[1].data.uint64_val = hicn_state->pkts_interest_count; + + sr_val_set_xpath(&vals[2], "/hicn:hicn-state/states/pkts_data_count"); + vals[2].type = SR_UINT64_T; + vals[2].data.uint64_val = hicn_state->pkts_data_count; + + sr_val_set_xpath(&vals[3], "/hicn:hicn-state/states/pkts_from_cache_count"); + vals[3].type = SR_UINT64_T; + vals[3].data.uint64_val = hicn_state->pkts_from_cache_count; + + sr_val_set_xpath(&vals[4], "/hicn:hicn-state/states/pkts_no_pit_count"); + vals[4].type = SR_UINT64_T; + vals[4].data.uint64_val = hicn_state->pkts_no_pit_count; + + sr_val_set_xpath(&vals[5], "/hicn:hicn-state/states/pit_expired_count"); + vals[5].type = SR_UINT64_T; + vals[5].data.uint64_val = hicn_state->pit_expired_count; + + sr_val_set_xpath(&vals[6], "/hicn:hicn-state/states/cs_expired_count"); + vals[6].type = SR_UINT64_T; + vals[6].data.uint64_val = hicn_state->cs_expired_count; + + sr_val_set_xpath(&vals[7], "/hicn:hicn-state/states/cs_lru_count"); + vals[7].type = SR_UINT64_T; + vals[7].data.uint64_val = hicn_state->cs_lru_count; + + sr_val_set_xpath(&vals[8], "/hicn:hicn-state/states/pkts_drop_no_buf"); + vals[8].type = SR_UINT64_T; + vals[8].data.uint64_val = hicn_state->pkts_drop_no_buf; + + sr_val_set_xpath(&vals[9], "/hicn:hicn-state/states/interests_aggregated"); + vals[9].type = SR_UINT64_T; + vals[9].data.uint64_val = hicn_state->interests_aggregated; + + sr_val_set_xpath(&vals[10], "/hicn:hicn-state/states/interests_retx"); + vals[10].type = SR_UINT64_T; + vals[10].data.uint64_val = hicn_state->interests_retx; + + sr_val_set_xpath(&vals[11], + "/hicn:hicn-state/states/interests_hash_collision"); + vals[11].type = SR_UINT64_T; + vals[11].data.uint64_val = hicn_state->interests_hash_collision; + + sr_val_set_xpath(&vals[12], "/hicn:hicn-state/states/pit_entries_count"); + vals[12].type = SR_UINT64_T; + vals[12].data.uint64_val = hicn_state->pit_entries_count; + + sr_val_set_xpath(&vals[13], "/hicn:hicn-state/states/cs_entries_count"); + vals[13].type = SR_UINT64_T; + vals[13].data.uint64_val = hicn_state->cs_entries_count; + + sr_val_set_xpath(&vals[14], "/hicn:hicn-state/states/cs_entries_ntw_count"); + vals[14].type = SR_UINT64_T; + vals[14].data.uint64_val = hicn_state->cs_entries_ntw_count; +} + + +static inline void strategy_update(sr_val_t * vals ){ + sr_val_set_xpath(&vals[0], "/hicn:hicn-state/strategy/description"); + vals[0].type = SR_UINT8_T; + vals[0].data.uint8_val = hicn_strategy->description[0]; +} + +static inline void strategies_update(sr_val_t * vals ){ + sr_val_set_xpath(&vals[0], "/hicn:hicn-state/strategies/n_strategies"); + vals[0].type = SR_UINT8_T; + vals[0].data.uint8_val = hicn_strategies->n_strategies; + + sr_val_set_xpath(&vals[1], "/hicn:hicn-state/strategies/strategy_id"); + vals[1].type = SR_UINT32_T; + vals[1].data.uint32_val = hicn_strategies->strategy_id[0]; + +} + +static inline void route_update(sr_val_t * vals ){ + sr_val_set_xpath(&vals[0], "/hicn:hicn-state/route/faceids"); + vals[0].type = SR_UINT16_T; + vals[0].data.uint16_val = hicn_route->faceids[0]; + + sr_val_set_xpath(&vals[1], "/hicn:hicn-state/route/strategy_id"); + vals[1].type = SR_UINT32_T; + vals[1].data.uint32_val = hicn_route->strategy_id; +} + +static inline void face_ip_params_update(sr_val_t * vals ){ + sr_val_set_xpath(&vals[0], "/hicn:hicn-state/face-ip-params/nh_addr"); + vals[0].type = SR_UINT64_T; + vals[0].data.uint64_val = hicn_face_ip_params->nh_addr[0]; + + sr_val_set_xpath(&vals[1], "/hicn:hicn-state/face-ip-params/swif"); + vals[1].type = SR_UINT32_T; + vals[1].data.uint32_val = hicn_face_ip_params->swif; + + sr_val_set_xpath(&vals[2], "/hicn:hicn-state/face-ip-params/flags"); + vals[2].type = SR_UINT32_T; + vals[2].data.uint32_val = hicn_face_ip_params->flags; +} + + +static int hicn_state_states_cb(const char *xpath, sr_val_t **values, + size_t *values_cnt, uint64_t request_id, + const char *original_xpath, void *private_ctx) { + sr_val_t *vals; + int rc; + enum locks_name state; + state=lstate; + SRP_LOG_DBG("Requesting state data for '%s'", xpath); + + if (!sr_xpath_node_name_eq(xpath, "states")) { + *values = NULL; + *values_cnt = 0; + return SR_ERR_OK; + } + + rc = sr_new_values(NSTATE_LEAVES, &vals); + if (SR_ERR_OK != rc) { + return rc; + } + + SRP_LOG_DBG("Requesting state data for '%s'", xpath); + Ticket_Lock(state); + state_update(vals); + Ticket_Unlock(state); + + *values = vals; + *values_cnt = NSTATE_LEAVES; +/* + pthread_t state_tid; + rc = pthread_create((pthread_t *)&state_tid, NULL, state_thread, NULL); + if (rc != 0) { + SRP_LOG_DBG_MSG("Error making hicn state thread"); + return SR_ERR_OPERATION_FAILED; + } +*/ + return SR_ERR_OK; +} + +static int hicn_state_strategy_cb(const char *xpath, sr_val_t **values, + size_t *values_cnt, uint64_t request_id, + const char *original_xpath, void *private_ctx) { + sr_val_t *vals; + int rc; + enum locks_name strategy; + strategy=lstrategy; + + if (!sr_xpath_node_name_eq(xpath, "strategy")) { + *values = NULL; + *values_cnt = 0; + return SR_ERR_OK; + } + + + rc = sr_new_values(NSTRATEGY_LEAVES, &vals); + if (SR_ERR_OK != rc) { + return rc; + } + + SRP_LOG_DBG("Requesting state data for '%s'", xpath); + Ticket_Lock(strategy); + strategy_update(vals); + Ticket_Unlock(strategy); + + *values = vals; + *values_cnt = NSTRATEGY_LEAVES; + return SR_ERR_OK; + + } + +static int hicn_state_strategies_cb(const char *xpath, sr_val_t **values, + size_t *values_cnt, uint64_t request_id, + const char *original_xpath, void *private_ctx) { + sr_val_t *vals; + int rc; + enum locks_name strategies; + strategies=lstrategies; + + + + if (! sr_xpath_node_name_eq(xpath, "strategies")) { + SRP_LOG_DBG_MSG("Requesting state is not for strategies"); + *values = NULL; + *values_cnt = 0; + return SR_ERR_OK; + } + + + rc = sr_new_values(NSTRATEGIES_LEAVES, &vals); + if (SR_ERR_OK != rc) { + return rc; + } + + SRP_LOG_DBG("Requesting state data for '%s'", xpath); + Ticket_Lock(strategies); + strategies_update(vals); + Ticket_Unlock(strategies); + + *values = vals; + *values_cnt = NSTRATEGIES_LEAVES; + return SR_ERR_OK; + + } + + +static int hicn_state_route_cb(const char *xpath, sr_val_t **values, + size_t *values_cnt, uint64_t request_id, + const char *original_xpath, void *private_ctx) { + sr_val_t *vals; + int rc; + enum locks_name route; + route=lroute; + + + if (! sr_xpath_node_name_eq(xpath, "route")) { + SRP_LOG_DBG_MSG("Requesting state is not for route"); + *values = NULL; + *values_cnt = 0; + return SR_ERR_OK; + } + + rc = sr_new_values(NROUTE_LEAVES, &vals); + if (SR_ERR_OK != rc) { + return rc; + } + + SRP_LOG_DBG("Requesting state data for '%s'", xpath); + Ticket_Lock(route); + route_update(vals); + Ticket_Unlock(route); + + *values = vals; + *values_cnt = NROUTE_LEAVES; + return SR_ERR_OK; + + } + + + static int hicn_state_face_ip_params_cb(const char *xpath, sr_val_t **values, + size_t *values_cnt, uint64_t request_id, + const char *original_xpath, void *private_ctx) { + sr_val_t *vals; + int rc; + enum locks_name face_ip_params; + face_ip_params=lface_ip_params; + + + + if (! sr_xpath_node_name_eq(xpath, "face-ip-params")) { + SRP_LOG_DBG_MSG("Requesting state is not for face-ip-params"); + *values = NULL; + *values_cnt = 0; + return SR_ERR_OK; + } + + rc = sr_new_values(NFACE_IP_PARAMS_LEAVES, &vals); + if (SR_ERR_OK != rc) { + return rc; + } + + SRP_LOG_DBG("Requesting state data for '%s'", xpath); + Ticket_Lock(face_ip_params); + face_ip_params_update(vals); + Ticket_Unlock(face_ip_params); + + *values = vals; + *values_cnt = NFACE_IP_PARAMS_LEAVES; + return SR_ERR_OK; + + } + + +static int params_send(vapi_msg_hicn_api_node_params_set *msg, + vapi_msg_hicn_api_node_params_set_reply *resp) { + vapi_msg_hicn_api_node_params_set_hton(msg); + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + HICN_VPP_VAPI_RECV; + SRP_LOG_DBG_MSG("state data are updated successfully"); + return SR_ERR_OK; +} + +/** + * @brief Callback to be called by any config change of "/hicn:/" leaf. + */ +static int hicn_node_params_set_cb(sr_session_ctx_t *session, const char *xpath, + sr_notif_event_t event, void *private_ctx) { + sr_change_iter_t *iter = NULL; + sr_change_oper_t op = SR_OP_CREATED; + sr_val_t *old_val = NULL; + sr_val_t *new_val = NULL; + sr_xpath_ctx_t xpath_ctx = { + 0, + }; + int rc = SR_ERR_OK, op_rc = SR_ERR_OK; + // no-op for apply, we only care about SR_EV_ENABLED, SR_EV_VERIFY, + // SR_EV_ABORT + if (SR_EV_APPLY == event) { + return SR_ERR_OK; + } + + // get changes iterator + rc = sr_get_changes_iter(session, xpath, &iter); + if (SR_ERR_OK != rc) { + SRP_LOG_ERR("Unable to retrieve change iterator: %s", sr_strerror(rc)); + return rc; + } + + vapi_msg_hicn_api_node_params_set *msg; + vapi_msg_hicn_api_node_params_set_reply *resp = NULL; + msg = vapi_alloc_hicn_api_node_params_set(g_vapi_ctx_instance); + // 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)))) { + if (!strcmp(new_val->xpath, "/hicn:hicn-conf/params/enable_disable")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.bool_val); + msg->payload.enable_disable = new_val->data.bool_val; + } else if (!strcmp(new_val->xpath, "/hicn:hicn-conf/params/pit_max_size")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.int32_val); + msg->payload.pit_max_size = new_val->data.int32_val; + } else if (!strcmp(new_val->xpath, "/hicn:hicn-conf/params/cs_max_size")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.int32_val); + msg->payload.cs_max_size = new_val->data.int32_val; + } else if (!strcmp(new_val->xpath, + "/hicn:hicn-conf/params/cs_reserved_app")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.int32_val); + msg->payload.cs_reserved_app = new_val->data.int32_val; + } else if (!strcmp(new_val->xpath, + "/hicn:hicn-conf/params/pit_dflt_lifetime_sec")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.decimal64_val); + msg->payload.pit_dflt_lifetime_sec = new_val->data.decimal64_val; + } else if (!strcmp(new_val->xpath, + "/hicn:hicn-conf/params/pit_min_lifetime_sec")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.decimal64_val); + msg->payload.pit_min_lifetime_sec = new_val->data.decimal64_val; + } else if (!strcmp(new_val->xpath, + "/hicn:hicn-conf/params/pit_max_lifetime_sec")) { + SRP_LOG_DBG("A change detected in '%s', op=%d", + new_val ? new_val->xpath : old_val->xpath, + new_val->data.decimal64_val); + msg->payload.pit_max_lifetime_sec = new_val->data.decimal64_val; + } + + switch (op) { + case SR_OP_CREATED: + case SR_OP_MODIFIED: + op_rc = SR_ERR_OK; // OK + break; + case SR_OP_DELETED: + op_rc = SR_ERR_OPERATION_FAILED; // ERROR + break; + default: + break; + } + sr_xpath_recover(&xpath_ctx); + if (SR_ERR_INVAL_ARG == op_rc) { + sr_set_error(session, "You are not allowed to change the schema.", + new_val ? new_val->xpath : old_val->xpath); + } + sr_free_val(old_val); + sr_free_val(new_val); + } + + params_send(msg, resp); + + sr_free_change_iter(iter); + SRP_LOG_DBG_MSG("Configuration applied successfully"); + return SR_ERR_OK; +} + +/** + * @brief API to get hicn param in vpp. + */ +static int hicn_node_params_get_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn node parameter received successfully"); + vapi_msg_hicn_api_node_params_get *msg; + vapi_msg_hicn_api_node_params_get_reply *resp; + + msg = vapi_alloc_hicn_api_node_params_get(g_vapi_ctx_instance); + vapi_msg_hicn_api_node_params_get_hton(msg); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_node_params_get_reply_ntoh(resp); + + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + SRP_LOG_DBG("Pit Max entries: %d",resp->payload.pit_max_size); + return SR_ERR_OK; + } + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to get hicn stat in vpp. + */ +static int hicn_node_stat_get_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn status received successfully"); + vapi_msg_hicn_api_node_stats_get *msg; + vapi_msg_hicn_api_node_stats_get_reply *resp; + enum locks_name state; + state=lstate; + + //vapi_msg_id_hicn_api_node_stats_get=103; + msg = vapi_alloc_hicn_api_node_stats_get(g_vapi_ctx_instance); + vapi_msg_hicn_api_node_stats_get_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + vapi_msg_hicn_api_node_stats_get_reply_ntoh(resp); + + if(resp->payload.retval){ + SRP_LOG_DBG_MSG("Error updating state"); + return SR_ERR_OPERATION_FAILED; + } + Ticket_Lock(state); + // hicn_state = (hicn_state_t *) resp->payload; + hicn_state->pkts_processed = resp->payload.pkts_processed; + hicn_state->pkts_interest_count = resp->payload.pkts_interest_count; + hicn_state->pkts_data_count = resp->payload.pkts_data_count; + hicn_state->pkts_from_cache_count = resp->payload.pkts_from_cache_count; + hicn_state->pkts_no_pit_count = resp->payload.pkts_no_pit_count; + hicn_state->pit_expired_count = resp->payload.pit_expired_count; + hicn_state->cs_expired_count = resp->payload.cs_expired_count; + hicn_state->cs_lru_count = resp->payload.cs_lru_count; + hicn_state->pkts_drop_no_buf = resp->payload.pkts_drop_no_buf; + hicn_state->interests_aggregated = resp->payload.interests_aggregated; + hicn_state->interests_retx = resp->payload.interests_retx; + // hicn_state->interests_hash_collision = resp->payload.interests_hash_collision; + hicn_state->pit_entries_count = resp->payload.pit_entries_count; + hicn_state->cs_entries_count = resp->payload.cs_entries_count; + hicn_state->cs_entries_ntw_count = resp->payload.cs_entries_ntw_count; + Ticket_Unlock(state); + + return SR_ERR_OK; + +} + +/** + * @brief API to get hicn strategy in vpp. + */ +static int hicn_strategy_get_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn strategy receive successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_strategy_get *msg; + vapi_msg_hicn_api_strategy_get_reply *resp; + + msg = vapi_alloc_hicn_api_strategy_get(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + msg->payload.strategy_id = input[0].data.uint32_val; + + vapi_msg_hicn_api_strategy_get_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_strategy_get_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to get hicn strategies in vpp. + */ +static int hicn_strategies_get_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn strategies received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_strategies_get *msg; + vapi_msg_hicn_api_strategies_get_reply *resp; + + msg = vapi_alloc_hicn_api_strategies_get(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + vapi_msg_hicn_api_strategies_get_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_strategies_get_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to get hicn route in vpp. + */ +static int hicn_route_get_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn route receive successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_route_get *msg; + vapi_msg_hicn_api_route_get_reply *resp; + + msg = vapi_alloc_hicn_api_route_get(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.prefix[0],temp,4); + + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.prefix[0],temp,8); + memcpy(&msg->payload.prefix[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + + + msg->payload.len = input[2].data.uint8_val; + + vapi_msg_hicn_api_route_get_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_route_get_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to add hicn route nhops in vpp. + */ +static int hicn_route_nhops_add_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn route nhops add received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_route_nhops_add *msg; + vapi_msg_hicn_api_route_nhops_add_reply *resp; + + msg = vapi_alloc_hicn_api_route_nhops_add(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + vapi_msg_hicn_api_route_nhops_add_hton(msg); + + + + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.prefix[0],temp,4); + + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.prefix[0],temp,8); + memcpy(&msg->payload.prefix[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + + + + + msg->payload.len = input[2].data.uint8_val; + msg->payload.face_ids[0] = input[3].data.uint32_val; + msg->payload.face_ids[1] = input[4].data.uint32_val; + msg->payload.face_ids[2] = input[5].data.uint32_val; + msg->payload.face_ids[3] = input[6].data.uint32_val; + msg->payload.face_ids[4] = input[7].data.uint32_val; + msg->payload.face_ids[5] = input[8].data.uint32_val; + msg->payload.face_ids[6] = input[9].data.uint32_val; + msg->payload.n_faces = input[10].data.uint8_val; + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)){ + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_route_nhops_add_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to del hicn route in vpp. + */ +static int hicn_route_del_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn route del received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_route_del *msg; + vapi_msg_hicn_api_route_del_reply *resp; + + msg = vapi_alloc_hicn_api_route_del(g_vapi_ctx_instance); + + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.prefix[0],temp,4); + + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.prefix[0],temp,8); + memcpy(&msg->payload.prefix[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + + msg->payload.len = input[2].data.uint8_val; + + vapi_msg_hicn_api_route_del_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_route_del_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to get face ip params in hicn in vpp. + */ +static int hicn_face_ip_params_get_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn face ip params get received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_face_ip_params_get *msg; + vapi_msg_hicn_api_face_ip_params_get_reply *resp; + + msg = vapi_alloc_hicn_api_face_ip_params_get(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + msg->payload.faceid = input[0].data.uint16_val; + + vapi_msg_hicn_api_face_ip_params_get_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_face_ip_params_get_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to get face ip params in hicn in vpp. + */ +static int hicn_punting_add_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn punting add received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_punting_add *msg; + vapi_msg_hicn_api_punting_add_reply *resp; + + msg = vapi_alloc_hicn_api_punting_add(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.prefix[0],temp,4); + + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.prefix[0],temp,8); + memcpy(&msg->payload.prefix[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + msg->payload.len = input[2].data.uint8_val; + msg->payload.swif = input[3].data.uint32_val; + + + vapi_msg_hicn_api_punting_add_hton(msg); + + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_punting_add_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to del hicn route nhops in vpp. + */ +static int hicn_route_nhops_del_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn route nhop del received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_route_nhop_del *msg; + vapi_msg_hicn_api_route_nhop_del_reply *resp; + + msg = vapi_alloc_hicn_api_route_nhop_del(g_vapi_ctx_instance); + vapi_msg_hicn_api_route_nhop_del_hton(msg); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.prefix[0],temp,4); + + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.prefix[0],temp,8); + memcpy(&msg->payload.prefix[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + + msg->payload.len = input[2].data.uint8_val; + msg->payload.faceid = input[3].data.uint16_val; + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_route_nhop_del_reply_ntoh(resp); + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to del hicn punting in vpp. + */ +static int hicn_punting_del_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn punting del received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_punting_del *msg; + vapi_msg_hicn_api_punting_del_reply *resp; + + msg = vapi_alloc_hicn_api_punting_del(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + + + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.prefix[0],temp,4); + + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.prefix[0],temp,8); + memcpy(&msg->payload.prefix[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + + + + + + + msg->payload.len = input[2].data.uint8_val; + msg->payload.swif = input[3].data.uint32_val; + + vapi_msg_hicn_api_punting_del_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_punting_del_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to del hicn face ip in vpp. + */ +static int hicn_face_ip_del_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn face ip del received successfully"); + // allocate memory msg and resp + vapi_msg_hicn_api_face_ip_del *msg; + vapi_msg_hicn_api_face_ip_del_reply *resp; + + msg = vapi_alloc_hicn_api_face_ip_del(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + msg->payload.faceid = input[0].data.uint16_val; + + vapi_msg_hicn_api_face_ip_del_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_face_ip_del_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG_MSG("Successfully Done"); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief API to del hicn face ip in vpp. + */ +static int hicn_face_ip_add_cb(const char *xpath, const sr_val_t *input, + const size_t input_cnt, sr_val_t **output, + size_t *output_cnt, void *private_ctx) { + + SRP_LOG_DBG_MSG("hicn face ip add received successfully"); + + // allocate memory msg and resp + vapi_msg_hicn_api_face_ip_add *msg; + vapi_msg_hicn_api_face_ip_add_reply *resp; + + msg = vapi_alloc_hicn_api_face_ip_add(g_vapi_ctx_instance); + SRP_LOG_DBG("msg id:%d",msg->header._vl_msg_id); + if(strcmp(input[0].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[0].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *) &sa.sin_addr.s_addr; + memcpy(&msg->payload.local_addr[0],temp,4); + + }else if(strcmp(input[1].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[1].data.string_val, dst); + unsigned char * temp = (unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.local_addr[0],temp,8); + memcpy(&msg->payload.local_addr[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + if(strcmp(input[2].data.string_val,"-1")){ + + struct sockaddr_in sa; + // store this IP address in sa: + inet_pton(AF_INET, input[2].data.string_val, &(sa.sin_addr)); + unsigned char * temp = (unsigned char *)&sa.sin_addr.s_addr; + memcpy(&msg->payload.remote_addr[0],temp,4); + + + }else if(strcmp(input[3].data.string_val,"-1")){ + + void *dst = malloc(sizeof(struct in6_addr)); + inet_pton(AF_INET6, input[3].data.string_val, dst); + unsigned char * temp =(unsigned char *) ((struct in6_addr *)dst)->s6_addr; + memcpy(&msg->payload.remote_addr[0],temp,8); + memcpy(&msg->payload.remote_addr[1],temp+8,8); + + }else{ + SRP_LOG_DBG_MSG("Invalid local IP address"); + return SR_ERR_OPERATION_FAILED; + } + + msg->payload.swif = input[4].data.uint32_val; // This is the idx number of interface + + vapi_msg_hicn_api_face_ip_add_hton(msg); + + if (VAPI_OK != vapi_send(g_vapi_ctx_instance, msg)) { + SRP_LOG_DBG_MSG("Sending msg to VPP failed"); + return SR_ERR_OPERATION_FAILED; + } + + HICN_VPP_VAPI_RECV; + + vapi_msg_hicn_api_face_ip_add_reply_ntoh(resp); + + if(!resp->payload.retval){ + SRP_LOG_DBG("Successfully Done return faceid: %d",resp->payload.faceid); + return SR_ERR_OK; + } + + SRP_LOG_DBG_MSG("Operation Failed"); + return SR_ERR_OPERATION_FAILED; +} + +/** + * @brief Helper function for subscribing all hicn APIs. + */ +int hicn_subscribe_events(sr_session_ctx_t *session, + sr_subscription_ctx_t **subscription) { + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Subscriging hicn."); + + + //Initializing the locks + for (int i=0; i + + + + + 0 + + + + + + + 192.168.1.1 + -1 + 24 + + + + 192.168.1.1 + -1 + 30 + + + + 192.168.1.1 + -1 + 24 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + + + + 192.168.1.1 + -1 + 24 + 0 + + + + + 10 + + + + 192.168.1.10 + -1 + 192.168.1.1 + -1 + 0 + + + + + 0 + + + + 192.168.0.1 + -1 + 24 + 0 + + + + + 192.168.0.1 + -1 + 24 + 0 + \ No newline at end of file diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/yang/model/hicn.yang b/utils/sysrepo-plugins/hicn-plugin/plugin/yang/model/hicn.yang new file mode 100644 index 000000000..eddf31c98 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/yang/model/hicn.yang @@ -0,0 +1,536 @@ +module hicn { +namespace "urn:sysrepo:hicn"; +prefix hcn; + +revision 2019-02-06 { + description "Initial revision."; +} + +/* new data types and grouping definition to forward the remote request toward hicn controler--to-->hicn */ + +typedef float { + type decimal64 { + fraction-digits 2; + } +} + + +grouping params { + +leaf enable_disable { + description "Enable / disable ICN forwarder in VPP."; + type boolean; + default false; + } + +leaf pit_max_size { + description "PIT maximum size, otherwise -1 to assign default value."; + type int32; + default -1; + } + +leaf cs_max_size { + description "CS maximum size, otherwise -1 to assign default value."; + type int32; + default -1; + } + +leaf cs_reserved_app { + description "Portion of CS reserved to application, otherwise -1 to assign default value."; + type int32; + default -1; + } + +leaf pit_dflt_lifetime_sec { + description "Default PIT entry lifetime, otherwise -1 to assign default value."; + type float; + default -1; + } + +leaf pit_max_lifetime_sec { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value."; + type float; + default -1; + } + +leaf pit_min_lifetime_sec { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type float; + default -1; + } +} + +grouping face_ip_add { + +leaf lip4 { + description "IP version 4 local address."; + type string; + } + +leaf lip6 { + description "IP version 6 local address."; + type string; + } + +leaf rip4 { + description "IP version 4 local address."; + type string; + } + +leaf rip6 { + description "IP version 6 local address."; + type string; + } + +leaf swif { + description "Interface Index."; + type uint32; + } +} + +grouping route_nhops_add { + +leaf ip4 { + description "ip4 to be added to the FIB."; + type string; + } + +leaf ip6 { + description "ip6 to be added to the FIB."; + type string; + } + +leaf len { + description "Length of the prefix."; + type uint8; + } + +leaf face_ids0 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf face_ids1 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf face_ids2 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf face_ids3 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf face_ids4 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf face_ids5 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf face_ids6 { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint32; + } + +leaf n_faces { + description "Number of face to add."; + type uint8; + } +} + + +grouping route_nhops_del { + +leaf ip4 { + description "ip4 to be added to the FIB."; + type string; + } + +leaf ip6 { + description "ip6 to be added to the FIB."; + type string; + } + +leaf len { + description "Length of the prefix."; + type uint8; + } + +leaf faceid { + description "A Face ID to the next hop forwarder for the specified prefix."; + type uint16; + } + +} + +grouping route_del { + +leaf ip4 { + description "ip4 to be added to the FIB."; + type string; + } + +leaf ip6 { + description "ip6 to be added to the FIB."; + type string; + } + +leaf len { + description "Length of the prefix."; + type uint8; + } +} + + +grouping route_get { + + +leaf ip4 { + description "ip4 to be added to the FIB."; + type string; + } + +leaf ip6 { + description "ip6 to be added to the FIB."; + type string; + } + +leaf len { + description "Length of the prefix."; + type uint8; + } +} + +grouping punting_add { + +leaf ip4 { + description "ip4 to be added to the FIB."; + type string; + } + +leaf ip6 { + description "ip6 to be added to the FIB."; + type string; + } + +leaf len { + description "Length of the prefix."; + type uint8; + } + +leaf swif { + description "Interface id."; + type uint32; + } +} + +grouping register_prod_app { + +leaf-list prefix { + description "prefix to be matched to the FIB."; + type uint64; + } + +leaf len { + description "Length of the prefix."; + type uint8; + } + +leaf swif { + description "Interface id."; + type uint32; + } + +leaf cs_reserved { + description "CS memory reserved -- in number of packets."; + type uint32; + } + +} + +/* new data types and grouping definition to backward the remote response hicn--to-->controler */ + + +grouping states-reply { + + leaf pkts_processed { + description "ICN packets processed."; + type uint64; + } + + leaf pkts_interest_count { + description "PIT maximum size, otherwise -1 to assign default value."; + type uint64; + } + + leaf pkts_data_count { + description "CS maximum size, otherwise -1 to assign default value."; + type uint64; + } + + leaf pkts_from_cache_count { + description "Portion of CS reserved to application, otherwise -1 to assign default value."; + type uint64; + } + + leaf pkts_no_pit_count { + description "Default PIT entry lifetime, otherwise -1 to assign default value."; + type uint64; + } + + leaf pit_expired_count { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value."; + type uint64; + } + + leaf cs_expired_count { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf cs_lru_count { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf pkts_drop_no_buf { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf interests_aggregated { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf interests_retx { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf interests_hash_collision { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf pit_entries_count { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf cs_entries_count { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + + leaf cs_entries_ntw_count { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint64; + } + +} + + + +grouping strategy-reply { + + leaf description { + description "Enable / disable ICN forwarder in VPP."; + type uint8; + } +} + +grouping route-reply { + + leaf faceids { + description "Enable / disable ICN forwarder in VPP."; + type uint16; + + } + + leaf strategy_id { + description "compile-time plugin features."; + type uint32; + } +} + +grouping strategies-reply { + leaf n_strategies { + description "Enable / disable ICN forwarder in VPP."; + type uint8; + } + leaf strategy_id { + description "Enable / disable ICN forwarder in VPP."; + type uint32; + } + +} + +grouping face-ip-params-reply { + + leaf nh_addr { + description "Enable / disable ICN forwarder in VPP."; + type uint64; + } + + leaf swif { + description "compile-time plugin features."; + type uint32; + } + + leaf flags { + description "compile-time plugin features."; + type uint32; + } + +} + + +/* Hicn configuration */ + +container hicn-conf { + config true; + description "config data container for the hicn-vpp."; + + container params{ + uses params; + } +} + + +/* Hicn operational data */ + +container hicn-state { + config false; + description "operational data container for the hicn."; + + container states{ + uses states-reply; + } + container strategy{ + uses strategy-reply; + } + container route{ + uses route-reply; + } + container strategies{ + uses strategies-reply; + } + container face-ip-params{ + uses face-ip-params-reply; + } + +} + +/* RPC Definitions */ + + +rpc node-params-set { + description "Operation to set hicn params in vpp."; + input { + uses params; + } +} + +rpc node-params-get { + description "Operation to get hicn parameter in vpp."; +} + + +rpc node-stat-get { + description "Operation to get hicn status in vpp."; +} + + +rpc strategy-get { + description "Operation to get hicn strategy."; + input { + leaf strategy_id { + description "Upper bound on PIT entry lifetime, otherwise -1 to assign default value ."; + type uint32; + } + } +} + +rpc strategies-get { + description "Operation to get hicn strategies."; +} + +rpc route-get { + description "Operation to get hicn route."; + input { + uses route_get; + } +} + +rpc route-del { + description "Operation to del hicn route."; + input { + uses route_del; + } +} + +rpc route-nhops-add { + description "Operation to add hicn route nhops."; + input { + uses route_nhops_add; + } +} + +rpc route-nhops-del { + description "Operation to add hicn face ip punt."; + input { + uses route_nhops_del; + } +} + +rpc face-ip-params-get { + description "Operation to del hicn route."; + input { + leaf faceid { + description "Face to be retrieved ."; + type uint16; + } + } +} + +rpc face-ip-add { + description "Operation to add hicn face ip."; + input { + uses face_ip_add; + } +} + +rpc face-ip-del { + description "Operation to del hicn face ip."; + input { + leaf faceid { + description "Face to be deleted ."; + type uint16; + } + } +} + +rpc punting-add { + description "Operation to add hicn punt."; + input { + uses punting_add; + } +} + +rpc punting-del { + description "Operation to del hicn punt."; + input { + uses punting_add; /* It uses the same payload as the add*/ + } +} + +} diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/yang/startup.xml b/utils/sysrepo-plugins/hicn-plugin/plugin/yang/startup.xml new file mode 100644 index 000000000..f88e13ea2 --- /dev/null +++ b/utils/sysrepo-plugins/hicn-plugin/plugin/yang/startup.xml @@ -0,0 +1,11 @@ + + + false + -1 + -1 + -1 + -1 + -1 + -1 + + \ No newline at end of file -- cgit 1.2.3-korg