aboutsummaryrefslogtreecommitdiffstats
path: root/utils/sysrepo-plugins/hicn-plugin/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sysrepo-plugins/hicn-plugin/plugin')
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.c123
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/hicn_plugin.h25
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.c53
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/hicn_vpp_comm.h119
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.c597
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/ietf/ietf_interface.h25
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.c1323
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h90
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c21
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h31
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/yang/controler_rpcs_instances.xml76
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/yang/model/hicn.yang536
-rw-r--r--utils/sysrepo-plugins/hicn-plugin/plugin/yang/startup.xml11
13 files changed, 3030 insertions, 0 deletions
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 <inttypes.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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 <sysrepo.h>
+#include <sysrepo/plugins.h> //for HICN_LOG_DBG
+#include <sysrepo/values.h>
+#include <vapi/vapi.h>
+
+#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 <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <sysrepo.h>
+#include <sysrepo/plugins.h>
+#include <sysrepo/values.h>
+#include <sysrepo/xpath.h>
+#include <vnet/interface.h>
+#include <vnet/vnet.h>
+#include <vnet/ip/ip.h>
+#include <vapi/interface.api.vapi.h>
+
+#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 <stdio.h>
+#include <malloc.h>
+#include <sysrepo/xpath.h>
+#include <inttypes.h>
+/* Hicn headers */
+
+#include <vapi/hicn.api.vapi.h>
+#include <hicn/api/ip_address.h>
+#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<NLOCKS; i++)
+ Ticket_init(i,LOCK_INIT);
+
+ //Initializing the buffer
+ rc=init_buffer();
+ if(rc!= SR_ERR_OK){
+ SRP_LOG_DBG_MSG("Problem in initializing the buffers\n"); goto error;
+ }
+
+
+
+ // node state subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:node-params-get", hicn_node_params_get_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription stat-get\n");
+ goto error;
+ }
+
+
+ // node state subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:node-stat-get", hicn_node_stat_get_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription stat-get\n");
+ goto error;
+ }
+
+ // strategies subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:strategy-get", hicn_strategy_get_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription strategy-get\n");
+ goto error;
+ }
+
+ rc = sr_rpc_subscribe(session, "/hicn:strategies-get",
+ hicn_strategies_get_cb, session, SR_SUBSCR_CTX_REUSE, subscription); if (rc
+ != SR_ERR_OK) { SRP_LOG_DBG_MSG("Problem in subscription strategies-get\n"); goto error;
+ }
+
+ // route subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:route-get", hicn_route_get_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription route-get\n");
+ goto error;
+ }
+
+ rc = sr_rpc_subscribe(session, "/hicn:route-del", hicn_route_del_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription route-del\n");
+ goto error;
+ }
+
+
+ // route nhops subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:route-nhops-add",
+ hicn_route_nhops_add_cb, session, SR_SUBSCR_CTX_REUSE, subscription); if (rc
+ != SR_ERR_OK) { SRP_LOG_DBG_MSG("Problem in subscription route-get\n"); goto error;
+ }
+
+ rc = sr_rpc_subscribe(session, "/hicn:route-nhops-del",
+ hicn_route_nhops_del_cb, session, SR_SUBSCR_CTX_REUSE, subscription); if (rc
+ != SR_ERR_OK) { SRP_LOG_DBG_MSG("Problem in subscription route-nhops-del\n"); goto
+ error;
+ }
+
+
+ // face ip subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:face-ip-params-get",
+ hicn_face_ip_params_get_cb, session, SR_SUBSCR_CTX_REUSE, subscription); if
+ (rc != SR_ERR_OK) { SRP_LOG_DBG_MSG("Problem in subscription face-ip-params-get\n");
+ goto error;
+ }
+
+
+ rc = sr_rpc_subscribe(session, "/hicn:face-ip-add", hicn_face_ip_add_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription face-ip-add\n");
+ goto error;
+ }
+
+ rc = sr_rpc_subscribe(session, "/hicn:face-ip-del", hicn_face_ip_del_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription face-ip-del\n");
+ goto error;
+ }
+
+ // punting subscriptions
+
+ rc = sr_rpc_subscribe(session, "/hicn:punting-add", hicn_punting_add_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription); if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription punting-add\n");
+ goto error;
+ }
+
+ rc = sr_rpc_subscribe(session, "/hicn:punting-del", hicn_punting_del_cb,
+ session, SR_SUBSCR_CTX_REUSE, subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription punting-del\n");
+ goto error;
+ }
+
+ rc = sr_subtree_change_subscribe(
+ session, "/hicn:hicn-conf", hicn_node_params_set_cb, g_vapi_ctx_instance,
+ 100, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, subscription);
+ if (SR_ERR_OK != rc) {
+ SRP_LOG_DBG_MSG("Problem in subscription /hicn:hicn-conf\n");
+ goto error;
+ }
+
+ // subscribe as hicn state data provider
+ rc = sr_dp_get_items_subscribe(session, "/hicn:hicn-state/states",
+ hicn_state_states_cb, NULL, SR_SUBSCR_CTX_REUSE,
+ subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription /hicn:hicn-state/states\n");
+ goto error;
+ }
+
+
+
+ rc = sr_dp_get_items_subscribe(session, "/hicn:hicn-state/strategy",
+ hicn_state_strategy_cb, NULL, SR_SUBSCR_CTX_REUSE,
+ subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription /hicn:hicn-state/strategy\n");
+ goto error;
+ }
+
+
+
+ rc = sr_dp_get_items_subscribe(session, "/hicn:hicn-state/strategies",
+ hicn_state_strategies_cb, NULL, SR_SUBSCR_CTX_REUSE,
+ subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription /hicn:hicn-state/strategies\n");
+ goto error;
+ }
+
+
+ rc = sr_dp_get_items_subscribe(session, "/hicn:hicn-state/route",
+ hicn_state_route_cb, NULL, SR_SUBSCR_CTX_REUSE,
+ subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription /hicn:hicn-state/route\n");
+ goto error;
+ }
+
+
+ rc = sr_dp_get_items_subscribe(session, "/hicn:hicn-state/face-ip-params",
+ hicn_state_face_ip_params_cb, NULL, SR_SUBSCR_CTX_REUSE,
+ subscription);
+ if (rc != SR_ERR_OK) {
+ SRP_LOG_DBG_MSG("Problem in subscription /hicn:hicn-state/face-ip-params\n");
+ goto error;
+ }
+
+
+ SRP_LOG_INF_MSG("hicn plugin initialized successfully.");
+ return SR_ERR_OK;
+
+error:
+ SRP_LOG_ERR_MSG("Error by initialization of the hicn plugin.");
+ sr_plugin_cleanup_cb(session, &g_vapi_ctx_instance);
+ return rc;
+} \ No newline at end of file
diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h b/utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h
new file mode 100644
index 000000000..1f5acabc5
--- /dev/null
+++ b/utils/sysrepo-plugins/hicn-plugin/plugin/model/hicn_model.h
@@ -0,0 +1,90 @@
+/*
+ * 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 __IETF_HICN_H__
+#define __IETF_HICN_H__
+
+#include "../hicn_vpp_comm.h"
+
+
+#define MEM_ALIGN 4096
+
+// Number of locks is equal to number of nodes in hicn-state
+// It is a coarse grain approach later can be changed to fine grained
+// better to initialize the lock by 0
+#define NLOCKS 5
+#define LOCK_INIT 0
+
+
+enum locks_name {lstate, lstrategy, lstrategies, lroute, lface_ip_params};
+
+#define NSTATE_LEAVES 15
+#define NSTRATEGY_LEAVES 1
+#define NSTRATEGIES_LEAVES 2
+#define NROUTE_LEAVES 2
+#define NFACE_IP_PARAMS_LEAVES 3
+
+
+typedef struct __attribute__ ((__packed__)) {
+
+ uint64_t pkts_processed;
+ uint64_t pkts_interest_count;
+ uint64_t pkts_data_count;
+ uint64_t pkts_from_cache_count;
+ uint64_t pkts_no_pit_count;
+ uint64_t pit_expired_count;
+ uint64_t cs_expired_count;
+ uint64_t cs_lru_count;
+ uint64_t pkts_drop_no_buf;
+ uint64_t interests_aggregated;
+ uint64_t interests_retx;
+ uint64_t interests_hash_collision;
+ uint64_t pit_entries_count;
+ uint64_t cs_entries_count;
+ uint64_t cs_entries_ntw_count;
+ int32_t retval;
+
+} hicn_state_t;
+
+typedef struct __attribute__ ((__packed__)) {
+ uint8_t description[200];
+ int32_t retval;
+} hicn_strategy_t;
+
+
+typedef struct __attribute__ ((__packed__)) {
+
+ uint8_t n_strategies;
+ uint32_t strategy_id[256];
+ int32_t retval;
+} hicn_strategies_t;
+
+typedef struct __attribute__ ((__packed__)) {
+ uint16_t faceids[1000];
+ uint32_t strategy_id;
+ int32_t retval;
+} hicn_route_t;
+
+typedef struct __attribute__ ((__packed__)) {
+ uint64_t nh_addr[2];
+ uint32_t swif;
+ uint32_t flags;
+ int32_t retval;
+} hicn_face_ip_params_t;
+
+int hicn_subscribe_events(sr_session_ctx_t *session,
+ sr_subscription_ctx_t **subscription);
+
+#endif /* __IETF_HICN_H__ */ \ No newline at end of file
diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c b/utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c
new file mode 100644
index 000000000..d870adf75
--- /dev/null
+++ b/utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.c
@@ -0,0 +1,21 @@
+#include"tlock.h"
+
+
+void Ticket_init ( int Lock_Number , long int init ){
+
+//__atomic_store( &En[Lock_Number] , &init , __ATOMIC_SEQ_CST );
+//__atomic_store( &De[Lock_Number] , &init , __ATOMIC_SEQ_CST );
+En[Lock_Number]=init;
+De[Lock_Number]=init;
+}
+
+void Ticket_Lock(int Lock_Number ){
+
+ int my_ticket = __sync_fetch_and_add(&En[Lock_Number] , 1 );
+ while ( my_ticket != De[ Lock_Number ] ) {};
+
+}
+
+void Ticket_Unlock(int Lock_Number ){
+De[Lock_Number]++;
+}
diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h b/utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h
new file mode 100644
index 000000000..36698115a
--- /dev/null
+++ b/utils/sysrepo-plugins/hicn-plugin/plugin/model/tlock.h
@@ -0,0 +1,31 @@
+/*
+ * 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 __TLOCK_H__
+#define __TLOCK_H__
+
+
+// limit on the number of locks: it shoud be matched with the number of hicn-state leaves
+#define MAX_LOCK_SIZE 5
+
+volatile long int En[MAX_LOCK_SIZE] , De[MAX_LOCK_SIZE] ; // For Ticket Algorithm
+
+
+void Ticket_init ( int Lock_Number , long int init );
+void Ticket_Lock(int Lock_Number );
+void Ticket_Unlock(int Lock_Number );
+
+#endif /* __IETF_HICN_H__ */ \ No newline at end of file
diff --git a/utils/sysrepo-plugins/hicn-plugin/plugin/yang/controler_rpcs_instances.xml b/utils/sysrepo-plugins/hicn-plugin/plugin/yang/controler_rpcs_instances.xml
new file mode 100644
index 000000000..f497f0193
--- /dev/null
+++ b/utils/sysrepo-plugins/hicn-plugin/plugin/yang/controler_rpcs_instances.xml
@@ -0,0 +1,76 @@
+<node-params-get xmlns="urn:sysrepo:hicn"/>
+
+<node-stat-get xmlns="urn:sysrepo:hicn"/>
+
+<strategy-get xmlns="urn:sysrepo:hicn">
+ <strategy_id>0</strategy_id>
+</strategy-get>
+
+<strategies-get xmlns="urn:sysrepo:hicn"/>
+
+
+<route-get xmlns="urn:sysrepo:hicn">
+ <ip4>192.168.1.1</ip4>
+ <ip6>-1</ip6>
+ <len>24</len>
+</route-get>
+
+<route-del xmlns="urn:sysrepo:hicn">
+ <ip4>192.168.1.1</ip4>
+ <ip6>-1</ip6>
+ <len>30</len>
+</route-del>
+
+<route-nhops-add xmlns="urn:sysrepo:hicn">
+ <ip4>192.168.1.1</ip4>
+ <ip6>-1</ip6>
+ <len>24</len>
+ <face_ids0>0</face_ids0>
+ <face_ids1>0</face_ids1>
+ <face_ids2>0</face_ids2>
+ <face_ids3>0</face_ids3>
+ <face_ids4>0</face_ids4>
+ <face_ids5>0</face_ids5>
+ <face_ids6>0</face_ids6>
+ <n_faces>1</n_faces>
+</route-nhops-add>
+
+<route-nhops-del xmlns="urn:sysrepo:hicn">
+ <ip4>192.168.1.1</ip4>
+ <ip6>-1</ip6>
+ <len>24</len>
+ <faceid>0</faceid>
+</route-nhops-del>
+
+
+<face-ip-params-get xmlns="urn:sysrepo:hicn">
+ <faceid>10</faceid>
+</face-ip-params-get>
+
+<face-ip-add xmlns="urn:sysrepo:hicn">
+ <lip4>192.168.1.10</lip4>
+ <lip6>-1</lip6>
+ <rip4>192.168.1.1</rip4>
+ <rip6>-1</rip6>
+ <swif>0</swif>
+</face-ip-add>
+
+
+<face-ip-del xmlns="urn:sysrepo:hicn">
+ <faceid>0</faceid>
+</face-ip-del>
+
+<punting-add xmlns="urn:sysrepo:hicn">
+ <ip4>192.168.0.1</ip4>
+ <ip6>-1</ip6>
+ <len>24</len>
+ <swif>0</swif>
+</punting-add>
+
+
+<punting-del xmlns="urn:sysrepo:hicn">
+ <ip4>192.168.0.1</ip4>
+ <ip6>-1</ip6>
+ <len>24</len>
+ <swif>0</swif>
+</punting-del> \ 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 @@
+<hicn-conf xmlns="urn:sysrepo:hicn">
+<params>
+ <enable_disable>false</enable_disable>
+ <pit_max_size>-1</pit_max_size>
+ <cs_max_size>-1</cs_max_size>
+ <cs_reserved_app>-1</cs_reserved_app>
+ <pit_dflt_lifetime_sec>-1</pit_dflt_lifetime_sec>
+ <pit_max_lifetime_sec>-1</pit_max_lifetime_sec>
+ <pit_min_lifetime_sec>-1</pit_min_lifetime_sec>
+</params>
+</hicn-conf> \ No newline at end of file