summaryrefslogtreecommitdiffstats
path: root/hicn-plugin/src/faces/app
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-plugin/src/faces/app')
-rwxr-xr-xhicn-plugin/src/faces/app/address_mgr.c243
-rwxr-xr-xhicn-plugin/src/faces/app/address_mgr.h76
-rwxr-xr-xhicn-plugin/src/faces/app/face_app_cli.c203
-rwxr-xr-xhicn-plugin/src/faces/app/face_cons.c126
-rwxr-xr-xhicn-plugin/src/faces/app/face_cons.h75
-rwxr-xr-xhicn-plugin/src/faces/app/face_prod.c375
-rwxr-xr-xhicn-plugin/src/faces/app/face_prod.h113
-rwxr-xr-xhicn-plugin/src/faces/app/face_prod_node.c341
8 files changed, 1552 insertions, 0 deletions
diff --git a/hicn-plugin/src/faces/app/address_mgr.c b/hicn-plugin/src/faces/app/address_mgr.c
new file mode 100755
index 000000000..76a7e0f6d
--- /dev/null
+++ b/hicn-plugin/src/faces/app/address_mgr.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2017-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.
+ */
+
+/*
+ * Copyright (c) 2017-2019 by cisco systems inc. All rights reserved.
+ *
+ */
+
+#include <dlfcn.h>
+
+#include <vlib/vlib.h>
+#include <vnet/ip/ip6_packet.h>
+#include <vnet/ip/ip4.h> //ip4_add_del_ip_address
+#include <vnet/ip/ip6.h> //ip6_add_del_ip_address
+#include <vnet/fib/fib_types.h> //FIB_PROTOCOL_IP4/6, FIB_NODE_INDEX_INVALID
+#include <vnet/fib/fib_entry.h> //FIB_SOURCE_PLUGIN_HI
+#include <vnet/fib/fib_table.h>
+#include <vppinfra/format.h>
+#include <vnet/interface.h> //appif_flags
+#include <vnet/interface_funcs.h> //vnet_sw_interface_set_flags
+
+#include "address_mgr.h"
+#include "../../hicn.h"
+#include "../../infra.h"
+#include "../../error.h"
+#include "../face.h"
+#include "../ip/face_ip.h"
+#include "../../strategy_dpo_ctx.h"
+#include "../../route.h"
+
+typedef struct address_mgr_main_s
+{
+ ip4_address_t next_ip4_local_addr;
+ ip6_address_t next_ip6_local_addr;
+} address_mgr_main_t;
+
+address_mgr_main_t address_mgr_main;
+
+static void
+increment_v4_address (ip4_address_t * a, u32 val)
+{
+ u32 v;
+
+ v = clib_net_to_host_u32 (a->as_u32) + val;
+ a->as_u32 = clib_host_to_net_u32 (v);
+}
+
+static void
+increment_v6_address (ip6_address_t * a, u64 val)
+{
+ u64 v;
+
+ v = clib_net_to_host_u64 (a->as_u64[1]) + val;
+ a->as_u64[1] = clib_host_to_net_u64 (v);
+}
+
+void
+get_two_ip4_addresses (ip4_address_t * appif_addr, ip4_address_t * nh_addr)
+{
+ /* We want two consecutives address that fall into a /31 mask */
+ if (address_mgr_main.next_ip4_local_addr.as_u8[3] & 0x01)
+ increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1);
+
+ *appif_addr = address_mgr_main.next_ip4_local_addr;
+ increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1);
+ *nh_addr = address_mgr_main.next_ip4_local_addr;
+ fib_prefix_t fib_pfx;
+ fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID;
+ u32 fib_index;
+
+ fib_pfx.fp_proto = FIB_PROTOCOL_IP4;
+ fib_pfx.fp_len = ADDR_MGR_IP4_LEN;
+ /* At this point the face exists in the face table */
+ do
+ {
+ /* Check if the route already exist in the fib */
+ fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, appif_addr->as_u8);
+ fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto,
+ HICN_FIB_TABLE,
+ FIB_SOURCE_PLUGIN_HI);
+ fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx);
+ fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PLUGIN_HI);
+ if (fib_entry_index != FIB_NODE_INDEX_INVALID)
+ {
+ fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, nh_addr->as_u8);
+ fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto,
+ HICN_FIB_TABLE,
+ FIB_SOURCE_PLUGIN_HI);
+ fib_entry_index =
+ fib_table_lookup_exact_match (fib_index, &fib_pfx);
+ fib_table_unlock (fib_index, fib_pfx.fp_proto,
+ FIB_SOURCE_PLUGIN_HI);
+ }
+ if (fib_entry_index != FIB_NODE_INDEX_INVALID)
+ {
+ increment_v4_address (appif_addr, 2);
+ increment_v4_address (nh_addr, 2);
+ }
+ }
+ while (fib_entry_index != FIB_NODE_INDEX_INVALID);
+
+ address_mgr_main.next_ip4_local_addr = *nh_addr;
+ increment_v4_address (&(address_mgr_main.next_ip4_local_addr), 1);
+}
+
+void
+get_two_ip6_addresses (ip6_address_t * appif_addr, ip6_address_t * nh_addr)
+{
+
+ /* We want two consecutives address that fall into a /127 mask */
+ if (address_mgr_main.next_ip6_local_addr.as_u8[15] & 0x01)
+ increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1);
+
+ *appif_addr = address_mgr_main.next_ip6_local_addr;
+ increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1);
+ *nh_addr = address_mgr_main.next_ip6_local_addr;
+
+
+ fib_prefix_t fib_pfx;
+ fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID;
+ u32 fib_index;
+
+ fib_pfx.fp_proto = FIB_PROTOCOL_IP6;
+ fib_pfx.fp_len = ADDR_MGR_IP6_LEN;
+ /* At this point the face exists in the face table */
+ do
+ {
+ /* Check if the route already exist in the fib */
+ fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 1, appif_addr->as_u8);
+ fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto,
+ HICN_FIB_TABLE,
+ FIB_SOURCE_PLUGIN_HI);
+ fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx);
+ fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PLUGIN_HI);
+ if (fib_entry_index != FIB_NODE_INDEX_INVALID)
+ {
+ fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, nh_addr->as_u8);
+ fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto,
+ HICN_FIB_TABLE,
+ FIB_SOURCE_PLUGIN_HI);
+ fib_entry_index =
+ fib_table_lookup_exact_match (fib_index, &fib_pfx);
+ fib_table_unlock (fib_index, fib_pfx.fp_proto,
+ FIB_SOURCE_PLUGIN_HI);
+ }
+ if (fib_entry_index != FIB_NODE_INDEX_INVALID)
+ {
+ increment_v6_address (appif_addr, 2);
+ increment_v6_address (nh_addr, 2);
+ }
+ }
+ while (fib_entry_index != FIB_NODE_INDEX_INVALID);
+
+ address_mgr_main.next_ip6_local_addr = *nh_addr;
+ increment_v6_address (&(address_mgr_main.next_ip6_local_addr), 1);
+}
+
+ip4_address_t
+get_ip4_address ()
+{
+ ip4_address_t *prefix = &address_mgr_main.next_ip4_local_addr;
+ fib_prefix_t fib_pfx;
+ fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID;
+ u32 fib_index;
+
+ fib_pfx.fp_proto = FIB_PROTOCOL_IP4;
+ fib_pfx.fp_len = ADDR_MGR_IP4_LEN;
+ /* At this point the face exists in the face table */
+ do
+ {
+ /* Check if the route already exist in the fib */
+ fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 0, prefix->as_u8);
+ fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto,
+ HICN_FIB_TABLE,
+ FIB_SOURCE_PLUGIN_HI);
+ fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx);
+ fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PLUGIN_HI);
+ increment_v4_address (prefix, 1);
+ }
+ while (fib_entry_index != FIB_NODE_INDEX_INVALID);
+
+ return fib_pfx.fp_addr.ip4;
+}
+
+ip6_address_t
+get_ip6_address ()
+{
+ ip6_address_t *prefix = &address_mgr_main.next_ip6_local_addr;
+ fib_prefix_t fib_pfx;
+ fib_node_index_t fib_entry_index = FIB_NODE_INDEX_INVALID;
+ u32 fib_index;
+
+ fib_pfx.fp_proto = FIB_PROTOCOL_IP6;
+ fib_pfx.fp_len = ADDR_MGR_IP6_LEN;
+ /* At this point the face exists in the face table */
+ do
+ {
+ /* Check if the route already exist in the fib */
+ fib_pfx.fp_addr = to_ip46 ( /* is_v6 */ 1, prefix->as_u8);
+ fib_index = fib_table_find_or_create_and_lock (fib_pfx.fp_proto,
+ HICN_FIB_TABLE,
+ FIB_SOURCE_PLUGIN_HI);
+ fib_entry_index = fib_table_lookup_exact_match (fib_index, &fib_pfx);
+ fib_table_unlock (fib_index, fib_pfx.fp_proto, FIB_SOURCE_PLUGIN_HI);
+ increment_v6_address (prefix, 1);
+ }
+ while (fib_entry_index != FIB_NODE_INDEX_INVALID);
+
+ return fib_pfx.fp_addr.ip6;
+}
+
+void
+address_mgr_init ()
+{
+
+ address_mgr_main.next_ip4_local_addr.as_u8[0] = 169;
+ address_mgr_main.next_ip4_local_addr.as_u8[1] = 254;
+ address_mgr_main.next_ip4_local_addr.as_u8[2] = 1;
+ address_mgr_main.next_ip4_local_addr.as_u8[3] = 1;
+
+ ip6_address_set_zero (&address_mgr_main.next_ip6_local_addr);
+ address_mgr_main.next_ip6_local_addr.as_u16[0] =
+ clib_host_to_net_u16 (0xfc00);
+ address_mgr_main.next_ip6_local_addr.as_u8[15] = 1;
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables: eval: (c-set-style "gnu") End:
+ */
diff --git a/hicn-plugin/src/faces/app/address_mgr.h b/hicn-plugin/src/faces/app/address_mgr.h
new file mode 100755
index 000000000..99450dcdd
--- /dev/null
+++ b/hicn-plugin/src/faces/app/address_mgr.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017-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 _ADDRESS_MGR_H_
+#define _ADDRESS_MGR_H_
+
+/**
+ * @file
+ *
+ * @brief Address manager.
+ *
+ * Address manager that maintains a pool of ip4 and ip6 addresses to assign to
+ * an interface.
+ */
+
+#define ADDR_MGR_IP4_LEN 32
+#define ADDR_MGR_IP4_CONS_LEN 31
+#define ADDR_MGR_IP6_LEN 128
+#define ADDR_MGR_IP6_CONS_LEN 127
+
+/**
+ * @brief Get two consecutive IP v4 addresses from the same /31 subnet
+ *
+ * @param addr1 first ip address with the least significant bit set to 0
+ * @param addr2 second ip address with the least significant bit set to 1
+ */
+void get_two_ip4_addresses (ip4_address_t * addr1, ip4_address_t * addr2);
+
+/**
+ * @brief Get two consecutive IP v6 addresses from the same /126 subnet
+ *
+ * @param addr1 first ip address with the least significant bit set to 0
+ * @param addr2 second ip address with the least significant bit set to 1
+ */
+void get_two_ip6_addresses (ip6_address_t * addr1, ip6_address_t * addr2);
+
+/**
+ * @brief Get one IP v4 address
+ *
+ * @return ip address
+ */
+ip4_address_t get_ip4_address (void);
+
+/**
+ * @brief Get one IP v6 address
+ *
+ * @return ip address
+ */
+ip6_address_t get_ip6_address (void);
+
+/**
+ * @brief Init the address manager
+ */
+void address_mgr_init (void);
+
+#endif /* _ADDRESS_MGR_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/faces/app/face_app_cli.c b/hicn-plugin/src/faces/app/face_app_cli.c
new file mode 100755
index 000000000..d55e990de
--- /dev/null
+++ b/hicn-plugin/src/faces/app/face_app_cli.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2017-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 <vnet/vnet.h>
+#include <vnet/dpo/dpo.h>
+#include <vlib/vlib.h>
+#include <vnet/ip/ip6_packet.h>
+
+#include "../ip/face_ip.h"
+#include "../ip/dpo_ip.h"
+#include "../face.h"
+#include "face_prod.h"
+#include "face_cons.h"
+
+#define HICN_FACE_NONE 0
+#define HICN_FACE_DELETE 1
+#define HICN_FACE_ADD 2
+
+static clib_error_t *
+hicn_face_app_cli_set_command_fn (vlib_main_t * vm,
+ unformat_input_t * main_input,
+ vlib_cli_command_t * cmd)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ ip46_address_t prefix;
+ hicn_face_id_t face_id = HICN_FACE_NULL;
+ u32 cs_reserved = HICN_PARAM_FACE_DFT_CS_RESERVED;
+ int ret = HICN_ERROR_NONE;
+ int sw_if;
+ int face_op = HICN_FACE_NONE;
+ int prod = 0;
+ int len;
+
+ /* Get a line of input. */
+ unformat_input_t _line_input, *line_input = &_line_input;
+ if (!unformat_user (main_input, unformat_line_input, line_input))
+ {
+ return (0);
+ }
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "del"))
+ {
+ face_op = HICN_FACE_DELETE;
+ }
+ else if (face_op == HICN_FACE_DELETE
+ && unformat (line_input, "id %d", &face_id))
+ ;
+ else if (unformat (line_input, "add"))
+ {
+ face_op = HICN_FACE_ADD;
+ }
+ else if (face_op == HICN_FACE_ADD)
+ {
+ if (unformat (line_input, "intfc %U",
+ unformat_vnet_sw_interface, vnm, &sw_if))
+ ;
+ else
+ if (unformat
+ (line_input, "prod prefix %U/%d", unformat_ip46_address,
+ &prefix, IP46_TYPE_ANY, &len))
+ {
+ prod = 1;
+ }
+ else if (prod && unformat (line_input, "cs_size %d", &cs_reserved))
+ ;
+ else if (unformat (line_input, "cons"))
+ ;
+ else
+ {
+ return clib_error_return (0, "%s '%U'",
+ get_error_string
+ (HICN_ERROR_CLI_INVAL),
+ format_unformat_error, line_input);
+ }
+ }
+ else
+ {
+ return clib_error_return (0, "%s '%U'",
+ get_error_string (HICN_ERROR_CLI_INVAL),
+ format_unformat_error, line_input);
+ }
+ }
+
+ if (face_id != HICN_FACE_NULL)
+ {
+
+ if (!hicn_dpoi_idx_is_valid (face_id))
+ {
+ return clib_error_return (0, "%s, face_id %d not valid",
+ get_error_string (ret), face_id);
+ }
+ }
+
+ int rv;
+ switch (face_op)
+ {
+ case HICN_FACE_ADD:
+ {
+ ip46_address_t prod_addr;
+ ip4_address_t cons_addr4;
+ ip6_address_t cons_addr6;
+
+ hicn_prefix_t name_prefix = {
+ .name = prefix,
+ .len = len,
+ };
+ if (prod)
+ {
+ rv =
+ hicn_face_prod_add (&name_prefix, sw_if, &cs_reserved,
+ &prod_addr, &face_id);
+ if (rv == HICN_ERROR_NONE)
+ {
+ u8 *sbuf = NULL;
+ sbuf =
+ format (sbuf, "Face id: %d, producer address %U", face_id,
+ format_ip46_address, &prod_addr,
+ 0 /*IP46_ANY_TYPE */ );
+ vlib_cli_output (vm, "%s", sbuf);
+ }
+ else
+ {
+ return clib_error_return (0, get_error_string (rv));
+ }
+ }
+ else
+ {
+ rv =
+ hicn_face_cons_add (&cons_addr4, &cons_addr6, sw_if, &face_id);
+ if (rv == HICN_ERROR_NONE)
+ {
+ u8 *sbuf = NULL;
+ sbuf =
+ format (sbuf, "Face id: %d, consumer addresses v4 %U v6 %U",
+ face_id, format_ip4_address, &cons_addr4,
+ format_ip6_address, &cons_addr6);
+ vlib_cli_output (vm, "%s", sbuf);
+ }
+ else
+ {
+ return clib_error_return (0, get_error_string (rv));
+ }
+ }
+ break;
+ }
+ case HICN_FACE_DELETE:
+ {
+ hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
+
+ if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS)
+ rv = hicn_face_cons_del (face_id);
+ else
+ rv = hicn_face_prod_del (face_id);
+ if (rv == HICN_ERROR_NONE)
+ {
+ vlib_cli_output (vm, "Face %d deleted", face_id);
+ }
+ else
+ {
+ return clib_error_return (0, get_error_string (rv));
+ }
+ break;
+ }
+ default:
+ return clib_error_return (0, "Operation (%d) not implemented", face_op);
+ break;
+ }
+ return (rv == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n",
+ get_error_string
+ (rv));
+}
+
+/* cli declaration for 'cfg face' */
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (hicn_face_app_cli_set_command, static) =
+{
+ .path = "hicn face app",
+ .short_help = "hicn face app {add intfc <sw_if> { prod prefix <hicn_prefix> cs_size <size_in_packets>} {cons} | {del <face_id>}",
+ .function = hicn_face_app_cli_set_command_fn,
+};
+/* *INDENT-ON* */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/faces/app/face_cons.c b/hicn-plugin/src/faces/app/face_cons.c
new file mode 100755
index 000000000..8278b6ab3
--- /dev/null
+++ b/hicn-plugin/src/faces/app/face_cons.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017-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 <vnet/ip/ip6_packet.h>
+#include <vlib/vlib.h>
+#include <vnet/vnet.h>
+
+#include "face_cons.h"
+#include "address_mgr.h"
+#include "../../infra.h"
+
+int
+hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6,
+ u32 swif, hicn_face_id_t * faceid)
+{
+ /* Create the corresponding appif if */
+ /* Retrieve a valid local ip address to assign to the appif */
+ /* Set the ip address and create the face in the face db */
+
+ vlib_main_t *vm = vlib_get_main ();
+ vnet_main_t *vnm = vnet_get_main ();
+
+ hicn_main_t *hm = &hicn_main;
+
+ ip46_address_t if_ip;
+ ip46_address_reset (&if_ip);
+ nh_addr4->as_u32 = 0;
+ nh_addr6->as_u64[0] = 0;
+ nh_addr6->as_u64[1] = 0;
+ u32 if_flags = 0;
+
+ if (!hm->is_enabled)
+ {
+ return HICN_ERROR_FWD_NOT_ENABLED;
+ }
+ if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
+ vnet_sw_interface_set_flags (vnm, swif, if_flags);
+
+ get_two_ip4_addresses (&(if_ip.ip4), nh_addr4);
+ ip4_add_del_interface_address (vm,
+ swif,
+ &(if_ip.ip4),
+ ADDR_MGR_IP4_CONS_LEN, 0 /* is_del */ );
+
+ ip46_address_t nh_addr = to_ip46 (0, (u8 *) nh_addr4);
+
+ hicn_iface_ip_add (&if_ip, &nh_addr, swif, faceid);
+
+ hicn_face_t *face = hicn_dpoi_get_from_idx (*faceid);
+ face->shared.flags |= HICN_FACE_FLAGS_APPFACE_CONS;
+
+ get_two_ip6_addresses (&(if_ip.ip6), nh_addr6);
+ ip6_add_del_interface_address (vm,
+ swif,
+ &(if_ip.ip6),
+ ADDR_MGR_IP6_CONS_LEN, 0 /* is_del */ );
+
+ hicn_iface_ip_add (&if_ip, (ip46_address_t *) nh_addr6, swif, faceid);
+
+ face = hicn_dpoi_get_from_idx (*faceid);
+ face->shared.flags |= HICN_FACE_FLAGS_APPFACE_CONS;
+
+ return vnet_feature_enable_disable ("ip6-unicast",
+ "hicn-iface-ip6-input", swif, 1, 0,
+ 0) ==
+ 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE;
+}
+
+int
+hicn_face_cons_del (hicn_face_id_t face_id)
+{
+ hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
+
+ if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS)
+ {
+ int ret = hicn_face_ip_del (face_id);
+
+ return ret ==
+ HICN_ERROR_NONE
+ ? (vnet_feature_enable_disable
+ ("ip6-unicast", "hicn-iface-ip6-input", face->shared.sw_if, 0,
+ 0, 0) == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE) : ret;
+ }
+ else
+ {
+ return HICN_ERROR_APPFACE_NOT_FOUND;
+ }
+}
+
+u8 *
+format_hicn_face_cons (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (index_t index) = va_arg (*args, index_t);
+ CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
+
+ s = format (s, " (consumer face)");
+
+ return s;
+}
+
+/* *INDENT-OFF* */
+VNET_FEATURE_INIT(hicn_cons_app, static)=
+{
+ .arc_name = "ip6-unicast",
+ .node_name = "hicn-iface-ip6-input",
+ .runs_before = VNET_FEATURES("ip6-inacl"),
+};
+/* *INDENT-ON* */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables: eval: (c-set-style "gnu") End:
+ */
diff --git a/hicn-plugin/src/faces/app/face_cons.h b/hicn-plugin/src/faces/app/face_cons.h
new file mode 100755
index 000000000..067b45a1f
--- /dev/null
+++ b/hicn-plugin/src/faces/app/face_cons.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017-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 _FACE_CONSUMER_H_
+#define _FACE_CONSUMER_H_
+
+#include <vnet/vnet.h>
+#include "../face.h"
+
+/**
+ * @file
+ *
+ * @brief Consumer application face.
+ *
+ * A consumer application face is built upon an ip face and identify a local
+ * consumer application (co-located with the forwarder) that acts as a
+ * consumer. The interface used by the consumer application face is
+ * assumed to be reserved only for hICN traffic (e.g., dedicated memif that
+ * connects the applictation to the forwarder). Only one application face can be
+ * assigned to an interface.
+ *
+ * In the vlib graph a consumer application face directly connect the
+ * device-input node to the hicn-vface-ip node.
+ */
+
+/**
+ * @brief Add a new consumer application face
+ *
+ * The method creates the internal ip face and set the ip address to the interface.
+ * @param nh_addr4 ipv4 address to assign to interface used by the application to
+ * send interest to the consumer face
+ * @param nh_addr6 ipv6 address to assign to interface used by the application to
+ * send interest to the consumer face
+ * @param swif interface associated to the face
+ */
+int
+hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6,
+ u32 swif, hicn_face_id_t * faceid);
+
+/**
+ * @brief Delete an existing consumer application face
+ *
+ * @param face_id Id of the consumer application face
+ */
+int hicn_face_cons_del (hicn_face_id_t face_id);
+
+/**
+ * @brief Format an application consumer face
+ *
+ * @param s Pointer to a previous string. If null it will be initialize
+ * @param args Array storing input values. Expected u32 face_id and u32 indent
+ * @return String with the formatted face
+ */
+u8 *format_hicn_face_cons (u8 * s, va_list * args);
+
+
+#endif /* _FACE_CONSUMER_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables: eval: (c-set-style "gnu") End:
+ */
diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c
new file mode 100755
index 000000000..d06fe2ff3
--- /dev/null
+++ b/hicn-plugin/src/faces/app/face_prod.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2017-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 <vnet/ip/ip6_packet.h>
+#include <vlib/vlib.h>
+#include <vnet/vnet.h>
+
+#include "face_prod.h"
+#include "address_mgr.h"
+#include "../../infra.h"
+#include "../../route.h"
+#include "../../cache_policies/cs_lru.h"
+
+hicn_face_prod_state_t *face_state_vec;
+
+/* used to check if an interface is already in the vector */
+u32 *face_state_pool;
+
+static int
+hicn_app_state_create (u32 swif, hicn_prefix_t * prefix)
+{
+ /* Make sure that the pool is not empty */
+ pool_validate_index (face_state_pool, 0);
+
+ u32 *swif_app;
+ u8 found = 0;
+ /* *INDENT-OFF* */
+ pool_foreach (swif_app, face_state_pool,{
+ if (*swif_app == swif)
+ {
+ found = 1;
+ }
+ }
+ );
+ /* *INDENT-ON* */
+
+
+ if (found)
+ return HICN_ERROR_APPFACE_ALREADY_ENABLED;
+
+
+ /* Create the appif and store in the vector */
+ vec_validate (face_state_vec, swif);
+ clib_memcpy (&(face_state_vec[swif].prefix), prefix,
+ sizeof (hicn_prefix_t));
+
+ /* Set as busy the element in the vector */
+ pool_get (face_state_pool, swif_app);
+ *swif_app = swif;
+
+ int ret = HICN_ERROR_NONE;
+ if (ip46_address_is_ip4 (&(prefix->name)))
+ {
+ ret =
+ vnet_feature_enable_disable ("ip4-unicast", "hicn-face-prod-input",
+ swif, 1, 0, 0);
+ }
+ else
+ {
+ ret =
+ vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input",
+ swif, 1, 0, 0);
+ }
+
+ return ret == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE;
+}
+
+static int
+hicn_app_state_del (u32 swif)
+{
+ /* Make sure that the pool is not empty */
+ pool_validate_index (face_state_pool, 0);
+
+ u32 *temp;
+ u32 *swif_app = NULL;
+ u8 found = 0;
+ ip46_address_t *prefix_addr;
+ /* *INDENT-OFF* */
+ pool_foreach (temp, face_state_pool,{
+ if (*temp == swif)
+ {
+ found = 1;
+ swif_app = temp;
+ }
+ }
+ );
+ /* *INDENT-ON* */
+
+ prefix_addr = &(face_state_vec[swif].prefix.name);
+ if (!found)
+ return HICN_ERROR_APPFACE_NOT_FOUND;
+
+ int ret = HICN_ERROR_NONE;
+ if (ip46_address_is_ip4 (prefix_addr))
+ {
+ ret =
+ vnet_feature_enable_disable ("ip4-unicast", "hicn-face-prod-input",
+ swif, 0, 0, 0);
+ }
+ else
+ {
+ ret =
+ vnet_feature_enable_disable ("ip6-unicast", "hicn-face-prod-input",
+ swif, 0, 0, 0);
+ }
+
+ pool_put (face_state_pool, swif_app);
+ memset (&face_state_vec[swif], 0, sizeof (hicn_face_prod_state_t));
+
+ return ret == 0 ? HICN_ERROR_NONE : HICN_ERROR_APPFACE_FEATURE;
+}
+
+int
+hicn_face_prod_add (hicn_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
+ ip46_address_t * prod_addr, hicn_face_id_t * faceid)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ vnet_main_t *vnm = vnet_get_main ();
+
+ hicn_main_t *hm = &hicn_main;
+
+ ip46_address_t app_ip;
+ u32 if_flags = 0;
+
+ if (!hm->is_enabled)
+ {
+ return HICN_ERROR_FWD_NOT_ENABLED;
+ }
+ int ret = HICN_ERROR_NONE;
+ hicn_face_t *face = NULL;
+
+ if_flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
+ vnet_sw_interface_set_flags (vnm, sw_if, if_flags);
+
+ if (ip46_address_is_zero (&prefix->name))
+ {
+ return HICN_ERROR_APPFACE_PROD_PREFIX_NULL;
+ }
+ /*
+ * Check if a producer face is already existing for the same prefix
+ * and sw_if
+ */
+ if (ip46_address_is_ip4 (&prefix->name))
+ {
+ face =
+ hicn_face_ip4_get (&(prefix->name.ip4), sw_if,
+ &hicn_face_ip_remote_hashtb);
+ }
+ else
+ {
+ face =
+ hicn_face_ip6_get (&(prefix->name.ip6), sw_if,
+ &hicn_face_ip_remote_hashtb);
+ if (face != NULL)
+ return HICN_ERROR_FACE_ALREADY_CREATED;
+ }
+
+ if (face != NULL)
+ {
+ if (!(face->shared.flags & HICN_FACE_FLAGS_DELETED))
+ return HICN_ERROR_FACE_ALREADY_CREATED;
+
+ /*
+ * Something went worng, a consumer face exists for the
+ * producer's prefix.
+ */
+ /* It should never happens, this is a safety check. */
+ if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_CONS)
+ return HICN_ERROR_FACE_ALREADY_CREATED;
+
+ /* If the face exists but is marked as deleted, undelete it */
+ if (face->shared.flags & HICN_FACE_FLAGS_DELETED)
+ {
+ /*
+ * remove the deleted flag and retrieve the face
+ * local addr
+ */
+ face->shared.flags &= HICN_FACE_FLAGS_DELETED;
+ hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
+ app_ip = prod_face->ip_face.local_addr;
+ }
+ }
+ else
+ {
+ /* Otherwise create the face */
+ if (ip46_address_is_ip4 (&prefix->name))
+ {
+ /*
+ * Otherwise retrieve an ip address to assign as a
+ * local ip addr.
+ */
+ ip4_address_t app_ip4 = get_ip4_address ();
+ ip4_add_del_interface_address (vm,
+ sw_if,
+ &app_ip4,
+ ADDR_MGR_IP4_CONS_LEN,
+ 0 /* is_del */ );
+ app_ip = to_ip46 ( /* isv6 */ 0, app_ip4.as_u8);
+ }
+ else
+ {
+ ip6_address_t app_ip6 = get_ip6_address ();
+ ip6_add_del_interface_address (vm,
+ sw_if,
+ &app_ip6,
+ ADDR_MGR_IP6_CONS_LEN,
+ 0 /* is_del */ );
+ app_ip = to_ip46 ( /* isv6 */ 1, app_ip6.as_u8);
+ }
+
+ /*
+ * Special case: the nh_addr in the face is the appif ip
+ * address
+ */
+ ret = hicn_face_ip_add (&app_ip, &(prefix->name), sw_if, faceid);
+
+ face = hicn_dpoi_get_from_idx (*faceid);
+
+ face->shared.flags |= HICN_FACE_FLAGS_APPFACE_PROD;
+
+ hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
+
+ /*
+ * For the moment we keep them here although it would be good
+ * to create a different face for appface
+ */
+ prod_face->policy_vft.hicn_cs_insert = hicn_cs_lru.hicn_cs_insert;
+ prod_face->policy_vft.hicn_cs_update = hicn_cs_lru.hicn_cs_update;
+ prod_face->policy_vft.hicn_cs_dequeue = hicn_cs_lru.hicn_cs_dequeue;
+ prod_face->policy_vft.hicn_cs_delete_get =
+ hicn_cs_lru.hicn_cs_delete_get;
+ prod_face->policy_vft.hicn_cs_trim = hicn_cs_lru.hicn_cs_trim;
+
+ }
+
+ if (ret == HICN_ERROR_NONE
+ && hicn_face_prod_set_lru_max (*faceid, cs_reserved) == HICN_ERROR_NONE)
+ {
+ hicn_app_state_create (sw_if, prefix);
+ ret = hicn_route_add (faceid, 1, &(prefix->name), prefix->len);
+ }
+
+ *prod_addr = app_ip;
+
+ /* Cleanup in case of something went wrong. */
+ if (ret)
+ {
+ hicn_app_state_del (sw_if);
+
+ if (*faceid != HICN_FACE_NULL)
+ hicn_face_ip_del (*faceid);
+ }
+ return ret;
+}
+
+int
+hicn_face_prod_del (hicn_face_id_t face_id)
+{
+ hicn_face_t *face = hicn_dpoi_get_from_idx (face_id);
+
+ if (face->shared.flags & HICN_FACE_FLAGS_APPFACE_PROD)
+ {
+ hicn_face_prod_t *prod_face = (hicn_face_prod_t *) face->data;
+ /* Free the CS reserved for the face */
+ hicn_main.pitcs.pcs_app_max += prod_face->policy.max;
+ hicn_main.pitcs.pcs_app_count -= prod_face->policy.max;
+ prod_face->policy.max = 0;
+
+ /* Remove the face from the fib */
+ hicn_route_del_nhop (&(face_state_vec[face->shared.sw_if].prefix.name),
+ (face_state_vec[face->shared.sw_if].prefix.len),
+ face_id);
+
+ int ret = hicn_face_ip_del (face_id);
+ return ret ==
+ HICN_ERROR_NONE ? hicn_app_state_del (face->shared.sw_if) : ret;
+ }
+ else
+ {
+ return HICN_ERROR_APPFACE_NOT_FOUND;
+ }
+}
+
+int
+hicn_face_prod_set_lru_max (hicn_face_id_t face_id, u32 * requested_size)
+{
+ int ret = HICN_ERROR_NONE;
+ vlib_main_t *vm = vlib_get_main ();
+ hicn_face_t *face;
+ hicn_face_prod_t *face_prod;
+
+ if (!hicn_infra_fwdr_initialized)
+ {
+ ret = HICN_ERROR_FWD_NOT_ENABLED;
+ vlib_cli_output (vm, "hicn: %s\n", get_error_string (ret));
+ return ret;
+ }
+ face = hicn_dpoi_get_from_idx (face_id);
+ face_prod = (hicn_face_prod_t *) face->data;
+
+ if (face == NULL)
+ return HICN_ERROR_FACE_NOT_FOUND;
+
+ if (*requested_size > HICN_PARAM_FACE_MAX_CS_RESERVED)
+ *requested_size = HICN_PARAM_FACE_MAX_CS_RESERVED;
+
+ uint32_t available =
+ hicn_main.pitcs.pcs_app_max - hicn_main.pitcs.pcs_app_count;
+
+ if (*requested_size > available)
+ *requested_size = available;
+
+ face_prod->policy.max = *requested_size;
+ face_prod->policy.count = 0;
+ face_prod->policy.head = face_prod->policy.tail = 0;
+
+ hicn_main.pitcs.pcs_app_count += *requested_size;
+
+ return ret;
+}
+
+u8 *
+format_hicn_face_prod (u8 * s, va_list * args)
+{
+ index_t index = va_arg (*args, index_t);
+ CLIB_UNUSED (u32 indent) = va_arg (*args, u32);
+ hicn_face_t *face;
+ hicn_face_prod_t *prod_face;
+
+ face = hicn_dpoi_get_from_idx (index);
+ prod_face = (hicn_face_prod_t *) face->data;
+
+ s =
+ format (s, " (producer face: CS size %d, data cached %d)",
+ prod_face->policy.max, prod_face->policy.count);
+
+ return s;
+}
+
+/* *INDENT-OFF* */
+VNET_FEATURE_INIT(hicn_prod_app_input_ip6, static)=
+{
+ .arc_name = "ip6-unicast",
+ .node_name = "hicn-face-prod-input",
+ .runs_before = VNET_FEATURES("ip6-inacl"),
+};
+/* *INDENT-ON* */
+
+/* *INDENT-OFF* */
+VNET_FEATURE_INIT(hicn_prod_app_input_ip4, static)=
+{
+ .arc_name = "ip4-unicast",
+ .node_name = "hicn-face-prod-input",
+ .runs_before = VNET_FEATURES("ip4-inacl"),
+};
+/* *INDENT-ON* */
+
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables: eval: (c-set-style "gnu") End:
+ */
diff --git a/hicn-plugin/src/faces/app/face_prod.h b/hicn-plugin/src/faces/app/face_prod.h
new file mode 100755
index 000000000..89b74680b
--- /dev/null
+++ b/hicn-plugin/src/faces/app/face_prod.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017-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 _FACE_PRODUCER_H_
+#define _FACE_PRODUCER_H_
+
+#include "../../cache_policies/cs_policy.h"
+#include "../ip/face_ip.h"
+
+/**
+ * @file
+ *
+ * @brief Producer application face.
+ *
+ * A producer application face is built upon an ip face and identify a local
+ * producer application (co-located with the forwarder) that acts as a producer. In the
+ * current design an application face is either a face towards a consumer face
+ * or towards a producer. The interface used by the producer application face is
+ * assumed to be reserved only for hICN traffic (e.g., dedicated memif that
+ * connects the applictation to the forwarder). Only one application face can be
+ * assigned to an interface.
+ *
+ * To each producer application face it is assigned a portion of the CS. Every
+ * data arriving to a producer application will be stored in the portion of the
+ * CS assigned to the face. The eviction policy is defined in the
+ * face. Available eviction faces are list in the /cache_policy folder.
+ *
+ * In the vlib graph a producer application face is directly connected to the
+ * device-input node (with the node hicn-face-prod-input) and passes every packet to
+ * the hicn-face-ip node.
+ */
+
+/**
+ * @brief Producer application face state that refer to the hICN producer socket
+ * created by the application.
+ *
+ */
+typedef struct
+{
+ hicn_prefix_t prefix;
+} hicn_face_prod_state_t;
+
+extern hicn_face_prod_state_t *face_state_vec;
+
+typedef struct __attribute__ ((packed)) hicn_face_prod_t_
+{
+ hicn_face_ip_t ip_face;
+
+ hicn_cs_policy_t policy;
+ hicn_cs_policy_vft_t policy_vft;
+
+} hicn_face_prod_t;
+
+/**
+ * @brief Add a new producer application face
+ *
+ * The method creates the internal ip face and the state specific to the
+ * producer application face. This method setups a route in the FIB for the
+ * producer's prefix.
+ * @param prefix hicn prefix name assigned to the producer face
+ * @param len length of the prefix
+ * @param swif interface associated to the face
+ * @param cs_reserved return the amount of cs assigned to the face
+ * @param prod_addr address to assign to interface used by the appliction to
+ * send data to the producer face
+ */
+int
+hicn_face_prod_add (hicn_prefix_t * prefix, u32 swif, u32 * cs_reserved,
+ ip46_address_t * prod_addr, hicn_face_id_t * faceid);
+
+/**
+ * @brief Delete an existing application face
+ *
+ * @param faceid id of the face to remove
+ */
+int hicn_face_prod_del (hicn_face_id_t faceid);
+
+/**
+ * @brief Set lru queue size for an app face
+ *
+ * @param face_id Id of the producer application face
+ */
+int hicn_face_prod_set_lru_max (hicn_face_id_t face_id, u32 * requested_size);
+
+/**
+ * @brief Format an application producer face
+ *
+ * @param s Pointer to a previous string. If null it will be initialize
+ * @param args Array storing input values. Expected u32 face_id and u32 indent
+ * @return String with the formatted face
+ */
+u8 *format_hicn_face_prod (u8 * s, va_list * args);
+
+
+#endif /* _FACE_PROD_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables: eval: (c-set-style "gnu") End:
+ */
diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c
new file mode 100755
index 000000000..2e746a703
--- /dev/null
+++ b/hicn-plugin/src/faces/app/face_prod_node.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2017-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.
+ */
+
+/**
+ * @file
+ *
+ * @brief Application interface node
+ *
+ * This node runs after the device-input node and perfoms some safety checks in
+ * order to avoid unespected interest and data (i.e., hICN packets whose name do
+ * not contain the prefix associated to the application face)
+ */
+
+#include "face_prod.h"
+#include "../../hicn_api.h"
+#include "../../mgmt.h"
+
+#define foreach_face_prod_input_error \
+ _(NOT_SOCK_PREFIX, "name not in the socket prefix")
+
+typedef enum
+{
+#define _(f,s) FACE_PROD_INPUT_ERROR_##f,
+ foreach_face_prod_input_error
+#undef _
+ FACE_PROD_INPUT_N_ERROR,
+} face_prod_input_error_t;
+
+static __clib_unused char *face_prod_input_error_strings[] = {
+#define _(n,s) s,
+ foreach_face_prod_input_error
+#undef _
+};
+
+/* Node context data */
+typedef struct hicn_face_prod_runtime_s
+{
+ int id;
+} hicn_face_prod_runtime_t;
+
+typedef struct
+{
+ u32 next_index;
+ u32 sw_if_index;
+} hicn_face_prod_input_trace_t;
+
+typedef enum
+{
+ HICN_FACE_PROD_NEXT_DATA_IP4,
+ HICN_FACE_PROD_NEXT_DATA_IP6,
+ HICN_FACE_PROD_NEXT_ERROR_DROP,
+ HICN_FACE_PROD_N_NEXT,
+} hicn_face_prod_next_t;
+
+vlib_node_registration_t hicn_face_prod_input_node;
+
+static __clib_unused u8 *
+format_face_prod_input_trace (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ hicn_face_prod_input_trace_t *t =
+ va_arg (*args, hicn_face_prod_input_trace_t *);
+ CLIB_UNUSED (u32 indent) = format_get_indent (s);
+
+ s = format (s, "prod-face: sw_if_index %d next-index %d",
+ t->sw_if_index, t->next_index);
+ return s;
+}
+
+static_always_inline int
+match_ip4_name (u32 * name, hicn_prefix_t * prefix)
+{
+ u32 xor = 0;
+
+ xor = *name & prefix->name.ip4.data_u32;
+
+ return xor == prefix->name.ip4.data_u32;
+}
+
+static_always_inline int
+match_ip6_name (u32x4 * name, hicn_prefix_t * prefix)
+{
+ union
+ {
+ u32x4 as_u32x4;
+ u64 as_u64[2];
+ u32 as_u32[4];
+ } xor_sum __attribute__ ((aligned (sizeof (u32x4))));
+
+#ifdef CLIB_HAVE_VEC128
+ if (U32X4_ALIGNED (name))
+ { //SSE can't handle unaligned data
+ xor_sum.as_u32x4 = *((u32x4 *) name) &
+ UNION_CAST (prefix->name.ip6.as_u64[0], u32x4);
+ }
+ else
+#endif /* CLIB_HAVE_VEC128 */
+ {
+ xor_sum.as_u64[0] = ((u64 *) name)[0] & prefix->name.ip6.as_u64[0];
+ xor_sum.as_u64[1] = ((u64 *) name)[1] & prefix->name.ip6.as_u64[1];
+ }
+
+ return (xor_sum.as_u64[0] == prefix->name.ip6.as_u64[0]) &&
+ (xor_sum.as_u64[1] == prefix->name.ip6.as_u64[1]);
+}
+
+static_always_inline u32
+hicn_face_prod_next_from_data_hdr (vlib_node_runtime_t * node,
+ vlib_buffer_t * b, hicn_prefix_t * prefix)
+{
+ u8 *ptr = vlib_buffer_get_current (b);
+ u8 v = *ptr & 0xf0;
+ int match_res = 1;
+
+ if (PREDICT_TRUE (v == 0x40 && ip46_address_is_ip4 (&prefix->name)))
+ {
+ match_res = match_ip4_name ((u32 *) & (ptr[12]), prefix);
+ }
+ else if (PREDICT_TRUE (v == 0x60 && !ip46_address_is_ip4 (&prefix->name)))
+ {
+ match_res = match_ip6_name ((u32x4 *) & (ptr[8]), prefix);
+ }
+
+ b->error = 0*(1-match_res) + match_res*(node->errors[FACE_PROD_INPUT_ERROR_NOT_SOCK_PREFIX]);
+
+ return match_res ? HICN_FACE_PROD_NEXT_DATA_IP4 + (v ==
+ 0x60) :
+ HICN_FACE_PROD_NEXT_ERROR_DROP;
+}
+
+static_always_inline void
+hicn_face_prod_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node,
+ u32 swif, vlib_buffer_t * b, u32 next)
+{
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ hicn_face_prod_input_trace_t *t =
+ vlib_add_trace (vm, node, b, sizeof (*t));
+ t->next_index = next;
+ t->sw_if_index = swif;
+ }
+}
+
+static uword
+hicn_face_prod_input_node_fn (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ u32 n_left_from, *from, *to_next;
+ hicn_face_prod_next_t next_index;
+ vl_api_hicn_api_node_stats_get_reply_t stats = { 0 };
+
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+ next_index = node->cached_next_index;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ while (n_left_from >= 8 && n_left_to_next >= 4)
+ {
+ vlib_buffer_t *b0, *b1, *b2, *b3;
+ u32 bi0, bi1, bi2, bi3;
+ hicn_face_prod_state_t *prod_face0 = NULL;
+ hicn_face_prod_state_t *prod_face1 = NULL;
+ hicn_face_prod_state_t *prod_face2 = NULL;
+ hicn_face_prod_state_t *prod_face3 = NULL;
+ u32 next0, next1, next2, next3;
+
+ {
+ vlib_buffer_t *b4, *b5, *b6, *b7;
+ b4 = vlib_get_buffer (vm, from[4]);
+ b5 = vlib_get_buffer (vm, from[5]);
+ b6 = vlib_get_buffer (vm, from[6]);
+ b7 = vlib_get_buffer (vm, from[7]);
+ CLIB_PREFETCH (b4, CLIB_CACHE_LINE_BYTES, STORE);
+ CLIB_PREFETCH (b5, CLIB_CACHE_LINE_BYTES, STORE);
+ CLIB_PREFETCH (b6, CLIB_CACHE_LINE_BYTES, STORE);
+ CLIB_PREFETCH (b7, CLIB_CACHE_LINE_BYTES, STORE);
+ }
+
+ bi0 = from[0];
+ bi1 = from[1];
+ bi2 = from[2];
+ bi3 = from[3];
+
+ from += 4;
+ n_left_from -= 4;
+ to_next[0] = bi0;
+ to_next[1] = bi1;
+ to_next[2] = bi2;
+ to_next[3] = bi3;
+
+ to_next += 4;
+ n_left_to_next -= 4;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
+ b2 = vlib_get_buffer (vm, bi2);
+ b3 = vlib_get_buffer (vm, bi3);
+
+ prod_face0 =
+ &face_state_vec[vnet_buffer (b0)->sw_if_index[VLIB_RX]];
+ prod_face1 =
+ &face_state_vec[vnet_buffer (b1)->sw_if_index[VLIB_RX]];
+ prod_face2 =
+ &face_state_vec[vnet_buffer (b2)->sw_if_index[VLIB_RX]];
+ prod_face3 =
+ &face_state_vec[vnet_buffer (b3)->sw_if_index[VLIB_RX]];
+
+ next0 =
+ hicn_face_prod_next_from_data_hdr (node, b0, &prod_face0->prefix);
+ next1 =
+ hicn_face_prod_next_from_data_hdr (node, b1, &prod_face1->prefix);
+ next2 =
+ hicn_face_prod_next_from_data_hdr (node, b2, &prod_face2->prefix);
+ next3 =
+ hicn_face_prod_next_from_data_hdr (node, b3, &prod_face3->prefix);
+ stats.pkts_data_count += 4;
+
+ /* trace */
+ hicn_face_prod_trace_buffer (vm, node,
+ vnet_buffer (b0)->sw_if_index[VLIB_RX],
+ b0, next0);
+ hicn_face_prod_trace_buffer (vm, node,
+ vnet_buffer (b1)->sw_if_index[VLIB_RX],
+ b1, next1);
+ hicn_face_prod_trace_buffer (vm, node,
+ vnet_buffer (b2)->sw_if_index[VLIB_RX],
+ b2, next2);
+ hicn_face_prod_trace_buffer (vm, node,
+ vnet_buffer (b3)->sw_if_index[VLIB_RX],
+ b3, next3);
+
+ /* enqueue */
+ vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, bi2, bi3,
+ next0, next1, next2, next3);
+
+ stats.pkts_processed += 4;
+
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ vlib_buffer_t *b0;
+ u32 bi0, swif;
+ hicn_face_prod_state_t *prod_face = NULL;
+ u32 next0;
+
+ if (n_left_from > 1)
+ {
+ vlib_buffer_t *b1;
+ b1 = vlib_get_buffer (vm, from[1]);
+ CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE);
+ }
+
+ bi0 = from[0];
+ from += 1;
+ n_left_from -= 1;
+ to_next[0] = bi0;
+ to_next += 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ swif = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ prod_face = &face_state_vec[swif];
+
+ next0 =
+ hicn_face_prod_next_from_data_hdr (node, b0, &prod_face->prefix);
+ stats.pkts_data_count++;
+
+ /* trace */
+ hicn_face_prod_trace_buffer (vm, node,
+ vnet_buffer (b0)->sw_if_index[VLIB_RX],
+ b0, next0);
+
+ /* enqueue */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+
+ stats.pkts_processed += 1;
+
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_node_increment_counter (vm, node->node_index,
+ HICNFWD_ERROR_PROCESSED, stats.pkts_processed);
+ vlib_node_increment_counter (vm, node->node_index,
+ HICNFWD_ERROR_INTERESTS,
+ stats.pkts_interest_count);
+ vlib_node_increment_counter (vm, node->node_index, HICNFWD_ERROR_DATAS,
+ stats.pkts_data_count);
+
+ return (frame->n_vectors);
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE(hicn_face_prod_input_node) =
+{
+ .function = hicn_face_prod_input_node_fn,
+ .name = "hicn-face-prod-input",
+ .vector_size = sizeof(u32),
+ .format_trace = format_face_prod_input_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(face_prod_input_error_strings),
+ .error_strings = face_prod_input_error_strings,
+ .n_next_nodes = HICN_FACE_PROD_N_NEXT,
+ .next_nodes =
+ {
+ [HICN_FACE_PROD_NEXT_DATA_IP4] = "hicn-face-ip4-input",
+ [HICN_FACE_PROD_NEXT_DATA_IP6] = "hicn-face-ip6-input",
+ [HICN_FACE_PROD_NEXT_ERROR_DROP] = "error-drop",
+ },
+};
+/* *INDENT-ON* */
+
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables: eval: (c-set-style "gnu") End:
+ */