aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlberto Compagno <acompagn+fdio@cisco.com>2020-04-22 18:29:52 +0200
committerAlberto Compagno <acompagn+fdio@cisco.com>2020-05-04 11:32:01 +0200
commitc1b56d5861829a23289f42cecd716e681b520cf0 (patch)
tree05a78211549d5581c4f50f6e9647467cbebe548a
parent0c7f490009e8633e015b5cba48b78cc243254953 (diff)
[HICN-602] Added bidirectional udp tunnels
- Implemented a udp decapsulation node - Added a hash table to identify the incoming udp tunnel when an interest or data packets are received - Added udp punting through udp_register_dst_port Signed-off-by: Alberto Compagno <acompagn+fdio@cisco.com> Change-Id: Iffea4d81c5ea8ce8ccbbfd749113f06a698a2afe
-rw-r--r--hicn-plugin/src/CMakeLists.txt8
-rw-r--r--hicn-plugin/src/error.h4
-rw-r--r--hicn-plugin/src/faces/app/face_cons.c8
-rw-r--r--hicn-plugin/src/faces/app/face_prod.c11
-rw-r--r--hicn-plugin/src/faces/dpo_face.h32
-rw-r--r--hicn-plugin/src/faces/face.c24
-rw-r--r--hicn-plugin/src/faces/face.h9
-rw-r--r--hicn-plugin/src/faces/face_node.c19
-rw-r--r--hicn-plugin/src/faces/iface_node.c44
-rw-r--r--hicn-plugin/src/hicn.api37
-rw-r--r--hicn-plugin/src/hicn.c4
-rw-r--r--hicn-plugin/src/hicn.h2
-rw-r--r--hicn-plugin/src/hicn_api.c55
-rw-r--r--hicn-plugin/src/hicn_api.h3
-rw-r--r--hicn-plugin/src/hicn_api_test.c100
-rw-r--r--hicn-plugin/src/infra.h3
-rw-r--r--hicn-plugin/src/route.c48
-rw-r--r--hicn-plugin/src/route.h3
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_decap.h16
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_decap_node.c629
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_tunnel.c281
-rw-r--r--hicn-plugin/src/udp_tunnels/udp_tunnel.h57
22 files changed, 1343 insertions, 54 deletions
diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt
index 2dcc07ca3..13d3b5c3c 100644
--- a/hicn-plugin/src/CMakeLists.txt
+++ b/hicn-plugin/src/CMakeLists.txt
@@ -97,6 +97,8 @@ set(HICN_PLUGIN_SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack_node.c
${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl_node.c
${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_decap_node.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.c
)
set(HICN_PLUGIN_HEADER_FILES
@@ -140,6 +142,7 @@ set(HICN_PLUGIN_HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/mapme_ack.h
${CMAKE_CURRENT_SOURCE_DIR}/mapme_ctrl.h
${CMAKE_CURRENT_SOURCE_DIR}/mapme_eventmgr.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/udp_tunnels/udp_tunnel.h
)
set(HICN_API_TEST_SOURCE_FILES
@@ -186,6 +189,7 @@ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hicn)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vapi)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/ip)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib)
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp)
# These files are missing from vpp binary distribution
execute_process(
@@ -209,6 +213,10 @@ execute_process(
if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h ]; then
curl https://raw.githubusercontent.com/FDio/vpp/master/src/vnet/fib/fib_entry_track.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/fib/fib_entry_track.h;
fi;
+ if [ ! -e ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h ]; then
+ curl https://raw.githubusercontent.com/FDio/vpp/master/src/vnet/udp/udp_encap.h -o ${CMAKE_CURRENT_BINARY_DIR}/vnet/udp/udp_encap.h;
+ fi;
+
chmod +x ${CMAKE_CURRENT_BINARY_DIR}/vapi_json_parser.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_c_gen.py ${CMAKE_CURRENT_BINARY_DIR}/vapi_cpp_gen.py"
)
diff --git a/hicn-plugin/src/error.h b/hicn-plugin/src/error.h
index 923b25944..d35347779 100644
--- a/hicn-plugin/src/error.h
+++ b/hicn-plugin/src/error.h
@@ -69,7 +69,9 @@
_(APPFACE_PROD_PREFIX_NULL, -176, "Prefix must not be null for producer face") \
_(STRATEGY_NH_NOT_FOUND, -177, "Next hop not found") \
_(MW_STRATEGY_SET, -178, "Error while setting weight for next hop") \
- _(STRATEGY_NOT_FOUND, -179, "Strategy not found")
+ _(STRATEGY_NOT_FOUND, -179, "Strategy not found") \
+ _(UDP_TUNNEL_NOT_FOUND, -180, "Udp tunnel not found") \
+ _(UDP_TUNNEL_SRC_DST_TYPE, -181, "Src and dst addresses have different type (ipv4 and ipv6)")
typedef enum
{
diff --git a/hicn-plugin/src/faces/app/face_cons.c b/hicn-plugin/src/faces/app/face_cons.c
index 3cd3da78c..d44ba1a2b 100644
--- a/hicn-plugin/src/faces/app/face_cons.c
+++ b/hicn-plugin/src/faces/app/face_cons.c
@@ -57,7 +57,9 @@ hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6,
ip46_address_t nh_addr = to_ip46 (0, (u8 *) nh_addr4);
- hicn_iface_add (&nh_addr, swif, faceid1, DPO_PROTO_IP4);
+ index_t adj_index = adj_nbr_find(FIB_PROTOCOL_IP4, VNET_LINK_IP4, &nh_addr, swif);
+
+ hicn_iface_add (&nh_addr, swif, faceid1, DPO_PROTO_IP4, adj_index);
hicn_face_t *face = hicn_dpoi_get_from_idx (*faceid1);
face->flags |= HICN_FACE_FLAGS_APPFACE_CONS;
@@ -68,7 +70,9 @@ hicn_face_cons_add (ip4_address_t * nh_addr4, ip6_address_t * nh_addr6,
&(if_ip.ip6),
ADDR_MGR_IP6_CONS_LEN, 0 /* is_del */ );
- hicn_iface_add ((ip46_address_t *) nh_addr6, swif, faceid2, DPO_PROTO_IP6);
+ adj_index = adj_nbr_find(FIB_PROTOCOL_IP6, VNET_LINK_IP6, &nh_addr, swif);
+
+ hicn_iface_add ((ip46_address_t *) nh_addr6, swif, faceid2, DPO_PROTO_IP6, adj_index);
face = hicn_dpoi_get_from_idx (*faceid2);
face->flags |= HICN_FACE_FLAGS_APPFACE_CONS;
diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c
index c5b9f93dd..645154325 100644
--- a/hicn-plugin/src/faces/app/face_prod.c
+++ b/hicn-plugin/src/faces/app/face_prod.c
@@ -161,12 +161,16 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
{
return HICN_ERROR_APPFACE_PROD_PREFIX_NULL;
}
+
+ u8 isv6 = ip46_address_is_ip4(prod_addr);
+ index_t adj_index = adj_nbr_find(isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4, isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if);
+
/*
* Check if a producer face is already existing for the same prefix
* and sw_if
*/
face = hicn_face_get (&(prefix->fp_addr), sw_if,
- &hicn_face_hashtb);
+ &hicn_face_hashtb, adj_index);
if (face != NULL)
{
@@ -208,6 +212,8 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
&local_app_ip4, 31, 0 /* is_del */ );
local_app_ip = to_ip46 ( /* isv6 */ 0, local_app_ip4.as_u8);
remote_app_ip = to_ip46 ( /* isv6 */ 0, remote_app_ip4.as_u8);
+
+ vnet_build_rewrite_for_sw_interface(vnm, sw_if, VNET_LINK_IP4, &remote_app_ip4);
}
else
{
@@ -279,7 +285,8 @@ hicn_face_prod_add (fib_prefix_t * prefix, u32 sw_if, u32 * cs_reserved,
hicn_app_state_create (sw_if, prefix);
}
- face = hicn_face_get(&local_app_ip, sw_if, &hicn_face_hashtb);//HICN_FACE_FLAGS_APPFACE_PROD);
+ adj_index = adj_nbr_find(isv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4, isv6 ? VNET_LINK_IP6 : VNET_LINK_IP4, prod_addr, sw_if);
+ face = hicn_face_get(&local_app_ip, sw_if, &hicn_face_hashtb, adj_index);//HICN_FACE_FLAGS_APPFACE_PROD);
*faceid = hicn_dpoi_get_index (face);
diff --git a/hicn-plugin/src/faces/dpo_face.h b/hicn-plugin/src/faces/dpo_face.h
index 736c5c926..3bb99ecdb 100644
--- a/hicn-plugin/src/faces/dpo_face.h
+++ b/hicn-plugin/src/faces/dpo_face.h
@@ -135,7 +135,7 @@ always_inline void
hicn_dpo_iface_ip4_add_and_lock (hicn_face_id_t * index,
u8 * hicnb_flags,
const ip4_address_t * nat_addr,
- u32 sw_if, u32 node_index)
+ u32 sw_if, u32 adj_index, u32 node_index)
{
/*All (complete) faces are indexed by remote addess as well */
@@ -144,29 +144,27 @@ hicn_dpo_iface_ip4_add_and_lock (hicn_face_id_t * index,
/* if the face exists, it adds a lock */
hicn_face_t *face =
- hicn_face_get (&ip_address, sw_if, &hicn_face_hashtb);
+ hicn_face_get (&ip_address, sw_if, &hicn_face_hashtb, adj_index);
if (face == NULL)
{
hicn_face_id_t idx;
- hicn_iface_add (&ip_address, sw_if, &idx, DPO_PROTO_IP4);
+ hicn_iface_add (&ip_address, sw_if, &idx, DPO_PROTO_IP4, adj_index);
face = hicn_dpoi_get_from_idx(idx);
- if (nat_addr->as_u32 == 0)
- {
+ face->dpo.dpoi_type = DPO_FIRST;
+ face->dpo.dpoi_proto = DPO_PROTO_IP4;
+ face->dpo.dpoi_index = adj_index;
+ face->dpo.dpoi_next_node = node_index;
+
+ /* if (nat_addr->as_u32 == 0) */
+ /* { */
adj_nbr_walk(face->sw_if,
FIB_PROTOCOL_IP4,
hicn4_iface_adj_walk_cb,
face);
- }
- else
- {
- face->dpo.dpoi_type = DPO_FIRST;
- face->dpo.dpoi_proto = DPO_PROTO_IP4;
- face->dpo.dpoi_index = ~0;
- face->dpo.dpoi_next_node = node_index;
- }
+ /* } */
*hicnb_flags = HICN_BUFFER_FLAGS_DEFAULT;
@@ -226,23 +224,23 @@ always_inline void
hicn_dpo_iface_ip6_add_and_lock (hicn_face_id_t * index,
u8 * hicnb_flags,
const ip6_address_t * nat_addr,
- u32 sw_if, u32 node_index)
+ u32 sw_if, u32 adj_index, u32 node_index)
{
/*All (complete) faces are indexed by remote addess as well */
/* if the face exists, it adds a lock */
hicn_face_t *face =
- hicn_face_get ((ip46_address_t *)nat_addr, sw_if, &hicn_face_hashtb);
+ hicn_face_get ((ip46_address_t *)nat_addr, sw_if, &hicn_face_hashtb, adj_index);
if (face == NULL)
{
hicn_face_id_t idx;
- hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, DPO_PROTO_IP6);
+ hicn_iface_add ((ip46_address_t *) nat_addr, sw_if, &idx, DPO_PROTO_IP6, adj_index);
face = hicn_dpoi_get_from_idx(idx);
face->dpo.dpoi_type = DPO_FIRST;
face->dpo.dpoi_proto = DPO_PROTO_IP6;
- face->dpo.dpoi_index = ~0;
+ face->dpo.dpoi_index = adj_index;
face->dpo.dpoi_next_node = node_index;
//if (ip46_address_is_zero((ip46_address_t *)nat_addr))
diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c
index 652a4a8e2..1abbf8887 100644
--- a/hicn-plugin/src/faces/face.c
+++ b/hicn-plugin/src/faces/face.c
@@ -341,19 +341,19 @@ hicn_iface_to_face(hicn_face_t *face, const dpo_id_t * dpo)
ip46_address_t * nh = &(adj->sub_type.nbr.next_hop);
fib_prefix_t prefix;
- fib_prefix_from_ip46_addr(nh, &prefix);
+ if (!ip46_address_is_zero(nh))
+ {
+ fib_prefix_from_ip46_addr(nh, &prefix);
- u32 fib_index = fib_table_find(prefix.fp_proto, HICN_FIB_TABLE);
+ u32 fib_index = fib_table_find(prefix.fp_proto, HICN_FIB_TABLE);
- face->fib_entry_index = fib_entry_track (fib_index,
- &prefix,
- hicn_face_fib_node_type,
- hicn_dpoi_get_index(face), &face->fib_sibling);
+ face->fib_entry_index = fib_entry_track (fib_index,
+ &prefix,
+ hicn_face_fib_node_type,
+ hicn_dpoi_get_index(face), &face->fib_sibling);
+ }
}
}
-
-
- //adj_child_add(face->dpo.dpoi_index, hicn_face_fib_node_type, hicn_dpoi_get_index(face));
}
/*
@@ -382,16 +382,17 @@ hicn_face_add (const dpo_id_t * dpo_nh, ip46_address_t * nat_address,
face =
hicn_face_get (nat_address, sw_if,
- &hicn_face_hashtb);
+ &hicn_face_hashtb, dpo_nh->dpoi_index);
dpo_id_t temp_dpo = DPO_INVALID;
+ temp_dpo.dpoi_index = dpo_nh->dpoi_index;
hicn_face_key_t key;
hicn_face_get_key (nat_address, sw_if, dpo_nh, &key);
if (face == NULL)
{
- hicn_iface_add (nat_address, sw_if, pfaceid, dpo_nh->dpoi_proto);
+ hicn_iface_add (nat_address, sw_if, pfaceid, dpo_nh->dpoi_proto, dpo_nh->dpoi_index);
face = hicn_dpoi_get_from_idx (*pfaceid);
mhash_set_mem (&hicn_face_hashtb, &key, (uword *) pfaceid,
@@ -411,6 +412,7 @@ hicn_face_add (const dpo_id_t * dpo_nh, ip46_address_t * nat_address,
hicn_iface_to_face(face, dpo_nh);
+ temp_dpo.dpoi_index = ~0;
hicn_face_input_faces_t *in_faces =
hicn_face_get_vec (nat_address, &hicn_face_vec_hashtb);
diff --git a/hicn-plugin/src/faces/face.h b/hicn-plugin/src/faces/face.h
index 54f2eab31..a9a565a5a 100644
--- a/hicn-plugin/src/faces/face.h
+++ b/hicn-plugin/src/faces/face.h
@@ -379,12 +379,14 @@ hicn_face_get_key (const ip46_address_t * addr,
* @result Pointer to the face.
*/
always_inline hicn_face_t *
-hicn_face_get (const ip46_address_t * addr, u32 sw_if, mhash_t * hashtb)
+hicn_face_get (const ip46_address_t * addr, u32 sw_if, mhash_t * hashtb, index_t adj_index)
{
hicn_face_key_t key;
dpo_id_t dpo = DPO_INVALID;
+ dpo.dpoi_index = adj_index;
+
hicn_face_get_key (addr, sw_if, &dpo, &key);
hicn_face_id_t *dpoi_index = (hicn_face_id_t *) mhash_get (hashtb,
@@ -478,7 +480,8 @@ int hicn_face_add (const dpo_id_t * dpo_nh,
*/
always_inline void
hicn_iface_add (ip46_address_t * nat_address, int sw_if,
- hicn_face_id_t * pfaceid, dpo_proto_t proto)
+ hicn_face_id_t * pfaceid, dpo_proto_t proto,
+ u32 adj_index)
{
hicn_face_t *face;
pool_get (hicn_dpoi_face_pool, face);
@@ -489,7 +492,7 @@ hicn_iface_add (ip46_address_t * nat_address, int sw_if,
face->dpo.dpoi_type = DPO_FIRST;
face->dpo.dpoi_proto = DPO_PROTO_NONE;
- face->dpo.dpoi_index = INDEX_INVALID;
+ face->dpo.dpoi_index = adj_index;
face->dpo.dpoi_next_node = 0;
face->pl_id = (u16) 0;
face->flags = HICN_FACE_FLAGS_IFACE;
diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c
index a52967dae..5b42f0dde 100644
--- a/hicn-plugin/src/faces/face_node.c
+++ b/hicn-plugin/src/faces/face_node.c
@@ -18,7 +18,6 @@
#include "face.h"
#include "face_node.h"
#include "dpo_face.h"
-//#include "app/face_prod.h"
#include "../strategy_dpo_manager.h"
#include "face.h"
#include "../cache_policies/cs_lru.h"
@@ -465,12 +464,16 @@ VLIB_REGISTER_NODE(hicn6_face_input_node) =
typedef enum
{
HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY,
+ HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP,
+ HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP,
HICN4_FACE_OUTPUT_N_NEXT,
} hicn4_face_output_next_t;
typedef enum
{
HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY,
+ HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP,
+ HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP,
HICN6_FACE_OUTPUT_N_NEXT,
} hicn6_face_output_next_t;
@@ -563,7 +566,7 @@ hicn_face_rewrite_interest (vlib_main_t * vm, vlib_buffer_t * b0,
ip46_address_reset (&temp_addr);
hicn_type_t type = hicn_get_buffer (b0)->type;
hicn_ops_vft[type.l1]->rewrite_interest (type, &hicn->protocol,
- &face->nat_addr, &temp_addr);
+ &face->nat_addr, &temp_addr);
if (ip46_address_is_ip4(&face->nat_addr))
b0->flags |= VNET_BUFFER_F_OFFLOAD_IP_CKSUM;
@@ -616,7 +619,7 @@ hicn6_face_output_trace_t;
do { \
vlib_buffer_t *b0; \
u32 bi0; \
- u32 next0 = IP_LOOKUP_NEXT_DROP; \
+ u32 next0 = ~0; \
hicn_face_t * face; \
\
/* Prefetch for next iteration. */ \
@@ -678,8 +681,8 @@ hicn6_face_output_trace_t;
do { \
vlib_buffer_t *b0, *b1; \
u32 bi0, bi1; \
- u32 next0 = IP_LOOKUP_NEXT_DROP; \
- u32 next1 = IP_LOOKUP_NEXT_DROP; \
+ u32 next0 = ~0; \
+ u32 next1 = ~0; \
hicn_face_t *face0, *face1; \
\
/* Prefetch for next iteration. */ \
@@ -844,6 +847,8 @@ VLIB_REGISTER_NODE(hicn4_face_output_node) =
.next_nodes =
{
[HICN4_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn4-face-input",
+ [HICN4_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
+ [HICN4_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap"
}
};
/* *INDENT-ON* */
@@ -920,7 +925,9 @@ VLIB_REGISTER_NODE(hicn6_face_output_node) =
/* Reusing the list of nodes from lookup to be compatible with neighbour discovery */
.next_nodes =
{
- [HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn6-face-input"
+ [HICN6_FACE_OUTPUT_NEXT_ECHO_REPLY] = "hicn6-face-input",
+ [HICN6_FACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
+ [HICN6_FACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap"
}
};
/* *INDENT-ON* */
diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c
index fbc573088..d42d0114e 100644
--- a/hicn-plugin/src/faces/iface_node.c
+++ b/hicn-plugin/src/faces/iface_node.c
@@ -135,6 +135,8 @@ typedef struct
typedef enum
{
HICN4_IFACE_OUTPUT_NEXT_LOOKUP,
+ HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP,
+ HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP,
HICN4_IFACE_OUTPUT_N_NEXT,
} hicn4_iface_output_next_t;
@@ -150,6 +152,8 @@ typedef struct
typedef enum
{
HICN6_IFACE_OUTPUT_NEXT_LOOKUP,
+ HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP,
+ HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP,
HICN6_IFACE_OUTPUT_N_NEXT,
} hicn6_iface_output_next_t;
@@ -159,6 +163,9 @@ typedef enum
#define NEXT_DATA_LOOKUP_IP4 HICN4_IFACE_OUTPUT_NEXT_LOOKUP
#define NEXT_DATA_LOOKUP_IP6 HICN6_IFACE_OUTPUT_NEXT_LOOKUP
+#define NEXT_UDP_ENCAP_IP4 HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP
+#define NEXT_UDP_ENCAP_IP6 HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP
+
#define HICN_REWRITE_DATA_IP4 hicn_rewrite_iface_data4
#define HICN_REWRITE_DATA_IP6 hicn_rewrite_iface_data6
@@ -170,7 +177,7 @@ typedef enum
#define iface_input_x1(ipv) \
do { \
vlib_buffer_t *b0; \
- u32 bi0, next0; \
+ u32 bi0, next0, next_iface0; \
IP_HEADER_##ipv * ip_hdr = NULL; \
hicn_buffer_t * hicnb0; \
/* Prefetch for next iteration. */ \
@@ -200,13 +207,20 @@ typedef enum
next0 = is_icmp*NEXT_MAPME_IP##ipv + \
(1-is_icmp)*NEXT_INTEREST_IP##ipv; \
\
+ next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
+ \
+ if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \
+ next_iface0 = NEXT_UDP_ENCAP_IP4; \
+ else if(hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \
+ next_iface0 = NEXT_UDP_ENCAP_IP6; \
\
DPO_ADD_LOCK_IFACE_IP##ipv \
(&(hicnb0->face_id), \
&hicnb0->flags, \
&(ip_hdr->src_address), \
vnet_buffer(b0)->sw_if_index[VLIB_RX], \
- NEXT_DATA_LOOKUP_IP##ipv); \
+ vnet_buffer(b0)->ip.adj_index[VLIB_RX], \
+ next_iface0); \
\
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
(b0->flags & VLIB_BUFFER_IS_TRACED))) \
@@ -239,7 +253,7 @@ typedef enum
#define iface_input_x2(ipv) \
do { \
vlib_buffer_t *b0, *b1; \
- u32 bi0, bi1, next0, next1; \
+ u32 bi0, bi1, next0, next1, next_iface0, next_iface1; \
IP_HEADER_##ipv * ip_hdr0 = NULL; \
IP_HEADER_##ipv * ip_hdr1 = NULL; \
hicn_buffer_t *hicnb0, *hicnb1; \
@@ -281,20 +295,35 @@ typedef enum
next1 = is_icmp1*NEXT_MAPME_IP##ipv + \
(1-is_icmp1)*NEXT_INTEREST_IP##ipv; \
\
+ next_iface0 = NEXT_DATA_LOOKUP_IP##ipv; \
+ \
+ if (hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \
+ next_iface0 = NEXT_UDP_ENCAP_IP4; \
+ else if(hicnb0->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \
+ next_iface0 = NEXT_UDP_ENCAP_IP6; \
\
+ next_iface1 = NEXT_DATA_LOOKUP_IP##ipv; \
+ \
+ if (hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL) \
+ next_iface1 = NEXT_UDP_ENCAP_IP4; \
+ else if(hicnb1->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL) \
+ next_iface1 = NEXT_UDP_ENCAP_IP6; \
+ \
DPO_ADD_LOCK_IFACE_IP##ipv \
(&(hicnb0->face_id), \
&hicnb0->flags, \
&(ip_hdr0->src_address), \
vnet_buffer(b0)->sw_if_index[VLIB_RX], \
- NEXT_DATA_LOOKUP_IP##ipv); \
+ vnet_buffer(b0)->ip.adj_index[VLIB_RX], \
+ next_iface0); \
\
DPO_ADD_LOCK_IFACE_IP##ipv \
(&(hicnb1->face_id), \
&hicnb1->flags, \
&(ip_hdr1->src_address), \
vnet_buffer(b1)->sw_if_index[VLIB_RX], \
- NEXT_DATA_LOOKUP_IP##ipv); \
+ vnet_buffer(b1)->ip.adj_index[VLIB_RX], \
+ next_iface1); \
\
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \
(b0->flags & VLIB_BUFFER_IS_TRACED))) \
@@ -794,6 +823,8 @@ VLIB_REGISTER_NODE (hicn4_iface_output_node) =
.next_nodes =
{
[HICN4_IFACE_OUTPUT_NEXT_LOOKUP] = "ip4-lookup",
+ [HICN4_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
+ [HICN4_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap"
},
};
/* *INDENT-ON* */
@@ -869,6 +900,9 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) =
.next_nodes =
{
[HICN6_IFACE_OUTPUT_NEXT_LOOKUP] = "ip6-lookup",
+ [HICN6_IFACE_OUTPUT_NEXT_UDP4_ENCAP] = "udp4-encap",
+ [HICN6_IFACE_OUTPUT_NEXT_UDP6_ENCAP] = "udp6-encap"
+
},
};
/* *INDENT-ON* */
diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api
index 0f7231327..753491c5f 100644
--- a/hicn-plugin/src/hicn.api
+++ b/hicn-plugin/src/hicn.api
@@ -22,7 +22,6 @@ enum hicn_action_type
HICN_ENABLE,
};
-
typedef hicn_face
{
/* IP local address */
@@ -607,6 +606,42 @@ autoreply define hicn_api_face_cons_del
u32 faceid;
};
+define hicn_api_udp_tunnel_add_del
+{
+ /* Client identifier, set from api_main.my_client_index */
+ u32 client_index;
+
+ /* Arbitrary context, so client can match reply to request */
+ u32 context;
+
+ /* Source address */
+ vl_api_address_t src_addr;
+
+ /* Destination address */
+ vl_api_address_t dst_addr;
+
+ /* Source port */
+ u16 src_port;
+
+ /* Destination port */
+ u16 dst_port;
+
+ /* Add or remove the tunnel*/
+ u8 is_add;
+};
+
+define hicn_api_udp_tunnel_add_del_reply
+{
+ /* From the request */
+ u32 context;
+
+ /* Return value, zero means all OK */
+ i32 retval;
+
+ /* Udp encap index */
+ u32 uei;
+};
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/hicn-plugin/src/hicn.c b/hicn-plugin/src/hicn.c
index e12d6d923..7bcbf5094 100644
--- a/hicn-plugin/src/hicn.c
+++ b/hicn-plugin/src/hicn.c
@@ -25,7 +25,7 @@
#include "error.h"
#include "faces/app/address_mgr.h"
#include "face_db.h"
-//#include "faces/udp/face_udp.h"
+#include "udp_tunnels/udp_tunnel.h"
#include "route.h"
hicn_main_t hicn_main;
@@ -236,6 +236,8 @@ hicn_init (vlib_main_t * vm)
/* Init the route module */
hicn_route_init ();
+ udp_tunnel_init ();
+
return error;
}
diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h
index 9e851ade1..6911cc5a9 100644
--- a/hicn-plugin/src/hicn.h
+++ b/hicn-plugin/src/hicn.h
@@ -59,6 +59,8 @@ typedef u8 weight_t;
/* vlib_buffer cloning utilities impose that current_lentgh is more that 2*CLIB_CACHE_LINE_BYTES. */
/* This flag is used to mark packets whose lenght is less that 2*CLIB_CACHE_LINE_BYTES. */
#define HICN_BUFFER_FLAGS_PKT_LESS_TWO_CL 0x02
+#define HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL 0x04
+#define HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL 0x08
/* The following is stored in the opaque2 field in the vlib_buffer_t */
typedef struct
diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c
index 841f0b604..1aa6178a7 100644
--- a/hicn-plugin/src/hicn_api.c
+++ b/hicn-plugin/src/hicn_api.c
@@ -26,7 +26,7 @@
#include <vnet/ip/ip_format_fns.h>
#include "faces/face.h"
-//#include "faces/udp/face_udp.h"
+#include "udp_tunnels/udp_tunnel.h"
#include "infra.h"
#include "parser.h"
#include "mgmt.h"
@@ -684,6 +684,59 @@ static void vl_api_hicn_api_enable_disable_t_handler
REPLY_MACRO (VL_API_HICN_API_ENABLE_DISABLE_REPLY/* , rmp, mp, rv */ );
}
+/*********************************** UDP TUNNELS ************************************/
+
+static void vl_api_hicn_api_udp_tunnel_add_del_t_handler
+(vl_api_hicn_api_udp_tunnel_add_del_t * mp)
+{
+ vl_api_hicn_api_udp_tunnel_add_del_reply_t *rmp;
+ int rv = HICN_ERROR_NONE;
+
+ hicn_main_t *sm = &hicn_main;
+
+ ip46_address_t src_addr;
+ ip46_address_t dst_addr;
+ u16 src_port;
+ u16 dst_port;
+ index_t uei = ~0;
+
+ ip46_type_t type = ip_address_decode (&mp->src_addr, &src_addr);
+ if (type != ip_address_decode (&mp->dst_addr, &dst_addr))
+ {
+ rv = HICN_ERROR_UDP_TUNNEL_SRC_DST_TYPE;
+ goto done;
+ }
+
+ src_port = clib_net_to_host_u16(mp->src_port);
+ dst_port = clib_net_to_host_u16(mp->dst_port);
+
+ fib_protocol_t proto = ip46_address_is_ip4(&src_addr) ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+
+ index_t fib_index = fib_table_find (proto, HICN_FIB_TABLE);
+
+ if (mp->is_add)
+ {
+ uei = udp_tunnel_add(proto,
+ fib_index, &src_addr, &dst_addr, src_port, dst_port,
+ UDP_ENCAP_FIXUP_NONE);
+ }
+ else
+ {
+ udp_tunnel_del(proto,
+ fib_index, &src_addr, &dst_addr, src_port, dst_port,
+ UDP_ENCAP_FIXUP_NONE);
+ }
+
+
+ done:
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO2 (VL_API_HICN_API_UDP_TUNNEL_ADD_DEL_REPLY, (
+ {
+ rmp->uei = clib_host_to_net_u32(uei);
+ }));
+ /* *INDENT-ON* */
+}
/************************************************************************************/
diff --git a/hicn-plugin/src/hicn_api.h b/hicn-plugin/src/hicn_api.h
index 79b561be4..6eecadf34 100644
--- a/hicn-plugin/src/hicn_api.h
+++ b/hicn-plugin/src/hicn_api.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2019 Cisco and/or its affiliates.
+ * Copyright (c) 2017-2020 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:
@@ -17,6 +17,7 @@
#define __HICN_API_H__
#define HICN_STRATEGY_NULL ~0
+#define HICN_FIB_TABLE 10
/* define message structures */
#define vl_typedefs
diff --git a/hicn-plugin/src/hicn_api_test.c b/hicn-plugin/src/hicn_api_test.c
index 6a1657edd..a09e62c58 100644
--- a/hicn-plugin/src/hicn_api_test.c
+++ b/hicn-plugin/src/hicn_api_test.c
@@ -263,7 +263,8 @@ _(HICN_API_ROUTE_DEL_REPLY, hicn_api_route_del_reply) \
_(HICN_API_ROUTE_NHOP_DEL_REPLY, hicn_api_route_nhop_del_reply) \
_(HICN_API_STRATEGIES_GET_REPLY, hicn_api_strategies_get_reply) \
_(HICN_API_STRATEGY_GET_REPLY, hicn_api_strategy_get_reply) \
-_(HICN_API_ENABLE_DISABLE_REPLY, hicn_api_enable_disable_reply)
+_(HICN_API_ENABLE_DISABLE_REPLY, hicn_api_enable_disable_reply) \
+_(HICN_API_UDP_TUNNEL_ADD_DEL_REPLY, hicn_api_udp_tunnel_add_del_reply)
static int
api_hicn_api_node_params_set (vat_main_t * vam)
@@ -1354,11 +1355,104 @@ static void
fformat (vam->ofp,
"ip4 address %U\n"
- "ip6 address :%U\n"
- "appif id :%d\n",
+ "ip6 address :%U\n",
format_ip46_address, IP46_TYPE_ANY, &src_addr4,
format_ip46_address, IP46_TYPE_ANY, &src_addr6);
}
+
+static int
+api_hicn_api_udp_tunnel_add_del (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_hicn_api_udp_tunnel_add_del_t *mp;
+
+ ip46_address_t src_ip, dst_ip;
+ u32 src_port, dst_port;
+ fib_protocol_t fproto;
+ u8 is_del;
+ int ret;
+
+ is_del = 0;
+ fproto = FIB_PROTOCOL_MAX;
+
+ /* Get a line of input. */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "add"))
+ is_del = 0;
+ else if (unformat (input, "del"))
+ is_del = 1;
+ else if (unformat (input, "%U %U",
+ unformat_ip4_address,
+ &src_ip.ip4, unformat_ip4_address, &dst_ip.ip4))
+ fproto = FIB_PROTOCOL_IP4;
+ else if (unformat (input, "%U %U",
+ unformat_ip6_address,
+ &src_ip.ip6, unformat_ip6_address, &dst_ip.ip6))
+ fproto = FIB_PROTOCOL_IP6;
+ else if (unformat (input, "%d %d", &src_port, &dst_port))
+ ;
+ else
+ {
+ break;
+ }
+ }
+
+
+ if (fproto == FIB_PROTOCOL_MAX)
+ {
+ clib_warning ("Please specify face ID");
+ return 1;
+ }
+
+ /* Construct the API message */
+ M (HICN_API_UDP_TUNNEL_ADD_DEL, mp);
+ ip_address_encode (&src_ip, fproto == FIB_PROTOCOL_IP4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6 ,&mp->src_addr);
+ ip_address_encode (&dst_ip, fproto == FIB_PROTOCOL_IP4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6 ,&mp->dst_addr);
+ mp->src_port = clib_host_to_net_u16(src_port);
+ mp->dst_port = clib_host_to_net_u16(dst_port);
+ mp->is_add = !is_del;
+
+ /* send it... */
+ S (mp);
+
+ /* Wait for a reply... */
+ W (ret);
+
+ return ret;
+}
+
+static void
+vl_api_hicn_api_udp_tunnel_add_del_reply_t_handler
+(vl_api_hicn_api_udp_tunnel_add_del_reply_t * mp)
+{
+ vat_main_t *vam = hicn_test_main.vat_main;
+ i32 retval = ntohl (mp->retval);
+
+ if (vam->async_mode)
+ {
+ vam->async_errors += (retval < 0);
+ return;
+ }
+ vam->retval = retval;
+ vam->result_ready = 1;
+
+ if (vam->retval < 0)
+ {
+ //vpp_api_test infra will also print out string form of error
+ fformat (vam->ofp, " (API call error: %d)\n", vam->retval);
+ return;
+ }
+
+ index_t uei = clib_net_to_host_u32(mp->uei);
+
+ fformat (vam->ofp,
+ "udp-encap %d\n",
+ uei);
+}
+
+
+
#include <hicn/hicn.api_test.c>
/*
diff --git a/hicn-plugin/src/infra.h b/hicn-plugin/src/infra.h
index fa493e7e9..007cf266d 100644
--- a/hicn-plugin/src/infra.h
+++ b/hicn-plugin/src/infra.h
@@ -80,6 +80,9 @@ extern vlib_node_registration_t hicn_interest_hitcs_node;
extern vlib_node_registration_t hicn_pg_interest_node;
extern vlib_node_registration_t hicn_pg_data_node;
extern vlib_node_registration_t hicn_pg_server_node;
+extern vlib_node_registration_t hicn_data_input_ip6_node;
+extern vlib_node_registration_t hicn_data_input_ip4_node;
+
#endif /* // __HICN_INFRA_H__ */
diff --git a/hicn-plugin/src/route.c b/hicn-plugin/src/route.c
index 0cefe6bda..0096edb2b 100644
--- a/hicn-plugin/src/route.c
+++ b/hicn-plugin/src/route.c
@@ -21,6 +21,8 @@
#include <vnet/dpo/dpo.h>
#include <vnet/dpo/drop_dpo.h>
#include <vnet/dpo/load_balance.h>
+#include <vnet/udp/udp.h>
+#include <vnet/udp/udp_encap.h>
#include <vlib/global_funcs.h>
#include "strategy_dpo_ctx.h"
@@ -29,6 +31,8 @@
#include "faces/face.h"
#include "error.h"
#include "strategies/dpo_mw.h"
+#include "infra.h"
+#include "udp_tunnels/udp_tunnel.h"
#define FIB_SOURCE_HICN 0x04 //Right after the FIB_SOURCE_INTERFACE priority
@@ -36,6 +40,9 @@ fib_source_t hicn_fib_src;
fib_node_type_t hicn_fib_node_type;
+ip4_address_t localhost4 = {0};
+ip6_address_t localhost6 = {0};
+
int
hicn_route_get_dpo (const fib_prefix_t * prefix,
const dpo_id_t ** hicn_dpo, u32 * fib_index)
@@ -508,6 +515,25 @@ sync_hicn_fib_entry(hicn_dpo_ctx_t *fib_entry)
sw_if = adj->rewrite_header.sw_if_index;
nh = get_address (&(adj->sub_type.nbr.next_hop), sw_if, fib_entry->proto);
}
+ else if (dpo->dpoi_type == dpo_type_udp_ip4 || dpo->dpoi_type == dpo_type_udp_ip6)
+ {
+ u8 proto = dpo->dpoi_type == dpo_type_udp_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+ nh = calloc (1, sizeof(ip46_address_t));
+ switch (dpo->dpoi_proto)
+ {
+ case FIB_PROTOCOL_IP6:
+ nh = calloc (1, sizeof(ip46_address_t));
+ ip46_address_set_ip6(nh, &localhost6);
+ break;
+ case FIB_PROTOCOL_IP4:
+ nh = calloc (1, sizeof(ip46_address_t));
+ ip46_address_set_ip4(nh, &localhost4);
+ break;
+ default:
+ nh = calloc (1, sizeof(ip46_address_t));
+ }
+ udp_tunnel_add_existing (dpo->dpoi_index, proto);
+ }
else //if (dpo_is_drop(dpo))
{
sw_if = dpo_get_urpf(dpo);
@@ -927,6 +953,8 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION (set_table_interface_add_del);
void
hicn_route_init ()
{
+ vnet_main_t * vnm = vnet_get_main ();
+ vlib_main_t * vm = vlib_get_main ();
hicn_fib_src = fib_source_allocate ("hicn",
FIB_SOURCE_HICN, FIB_SOURCE_BH_API);
@@ -934,6 +962,26 @@ hicn_route_init ()
ip_table_create(FIB_PROTOCOL_IP4, HICN_FIB_TABLE, 1, (const u8 *)"hicn4");
ip_table_create(FIB_PROTOCOL_IP6, HICN_FIB_TABLE, 1, (const u8 *)"hicn6");
+
+ u32 sw_if_index;
+ u8 mac_address[6];
+ u8 is_specified = 0;
+ u32 user_instance = 0;
+
+ vnet_create_loopback_interface (&sw_if_index, mac_address,
+ is_specified, user_instance);
+
+ localhost4.as_u8[0] = 127;
+ localhost4.as_u8[3] = 1;
+ u32 length4 = 32, length6 = 128, is_del = 0, flags = 0;
+
+ localhost6.as_u8[15] = 1;
+
+ ip4_add_del_interface_address (vm, sw_if_index, &localhost4, length4, is_del);
+ ip6_add_del_interface_address (vm, sw_if_index, &localhost6, length6, is_del);
+
+ flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
+ vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
}
/*
diff --git a/hicn-plugin/src/route.h b/hicn-plugin/src/route.h
index 678a828b5..4ff514740 100644
--- a/hicn-plugin/src/route.h
+++ b/hicn-plugin/src/route.h
@@ -22,6 +22,9 @@
#include "faces/face.h"
extern fib_source_t hicn_fib_src;
+
+extern dpo_type_t udp_encap_dpo_types[FIB_PROTOCOL_MAX];
+
/*
* Retrieve the hicn dpo corresponding to a hicn prefix
*/
diff --git a/hicn-plugin/src/udp_tunnels/udp_decap.h b/hicn-plugin/src/udp_tunnels/udp_decap.h
new file mode 100644
index 000000000..adbec3f03
--- /dev/null
+++ b/hicn-plugin/src/udp_tunnels/udp_decap.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020 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.
+ */
+
+extern vlib_node_registration_t udp_decap_node;
diff --git a/hicn-plugin/src/udp_tunnels/udp_decap_node.c b/hicn-plugin/src/udp_tunnels/udp_decap_node.c
new file mode 100644
index 000000000..6a5831c2b
--- /dev/null
+++ b/hicn-plugin/src/udp_tunnels/udp_decap_node.c
@@ -0,0 +1,629 @@
+/*
+ * Copyright (c) 2020 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/fib/fib_table.h>
+
+#include "udp_tunnel.h"
+#include "../mgmt.h"
+#include "../hicn.h"
+#include "../strategy_dpo_ctx.h"
+
+/**
+ * @File
+ *
+ * Definition of the nodes for ip incomplete faces.
+ */
+
+vlib_node_registration_t udp_decap_node;
+
+static char *udp_decap_error_strings[] = {
+#define _(sym, string) string,
+ foreach_hicnfwd_error
+#undef _
+};
+
+/* Trace context struct */
+typedef enum
+{
+ UDP4_DECAP_NEXT_LOOKUP_IP4,
+ UDP4_DECAP_NEXT_LOOKUP_IP6,
+ UDP4_DECAP_N_NEXT,
+} udp4_decap_next_t;
+
+typedef enum
+{
+ UDP6_DECAP_NEXT_LOOKUP_IP4,
+ UDP6_DECAP_NEXT_LOOKUP_IP6,
+ UDP6_DECAP_N_NEXT,
+} udp6_decap_next_t;
+
+typedef struct udp4_decap_trace_t_
+{
+ ip4_header_t ip;
+ udp_header_t udp;
+} udp4_decap_trace_t;
+
+typedef struct udp6_decap_trace_t_
+{
+ ip6_header_t ip;
+ udp_header_t udp;
+} udp6_decap_trace_t;
+
+typedef struct udp_decap_trace_t_
+{
+ union
+ {
+ udp4_decap_trace_t udp4;
+ udp6_decap_trace_t udp6;
+ };
+
+ u8 isv6;
+ u8 ishicn;
+} udp_decap_trace_t;
+
+
+static u8 *
+format_udp_decap_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 *);
+ udp_decap_trace_t *t;
+
+ t = va_arg (*args, udp_decap_trace_t *);
+
+ if (t->isv6)
+ {
+ s = format (s, "%U\n %U \n %s",
+ format_ip4_header, &t->udp6.ip, sizeof (t->udp6.ip),
+ format_udp_header, &t->udp6.udp, sizeof (t->udp6.udp),
+ t->ishicn ? "hICN udp tunnel" : "");
+ }
+ else
+ {
+ s = format (s, "%U\n %U \n %s",
+ format_ip4_header, &t->udp4.ip, sizeof (t->udp4.ip),
+ format_udp_header, &t->udp4.udp, sizeof (t->udp4.udp),
+ t->ishicn ? "hICN udp tunnel" : "");
+ }
+ return (s);
+}
+
+static_always_inline void
+udp_decap_trace_buffer (vlib_main_t * vm, vlib_node_runtime_t * node,
+ u8 isv6, vlib_buffer_t * b)
+{
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ udp_decap_trace_t *t =
+ vlib_add_trace (vm, node, b, sizeof (*t));
+ t->isv6 = isv6;
+ hicn_buffer_t *hb = hicn_get_buffer(b);
+
+ if (isv6)
+ {
+ clib_memcpy(&(t->udp6.udp), vlib_buffer_get_current(b) + sizeof(ip6_header_t), sizeof(udp_header_t));
+ clib_memcpy(&(t->udp6.ip), vlib_buffer_get_current(b), sizeof(ip6_header_t));
+ t->ishicn = hb->flags & hb->flags & HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL;
+ }
+ else
+ {
+ clib_memcpy(&(t->udp4.udp), vlib_buffer_get_current(b) + sizeof(ip4_header_t), sizeof(udp_header_t));
+ clib_memcpy(&(t->udp4.ip), vlib_buffer_get_current(b), sizeof(ip4_header_t));
+ t->ishicn = hb->flags & HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL;
+ }
+ }
+}
+
+static uword
+udp4_decap_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ u32 n_left_from, *from, *to_next, next_index;
+
+ 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);
+
+ /* Dual loop, X2 */
+ while (n_left_from >= 8 && n_left_to_next >= 4)
+ {
+ vlib_buffer_t *b0, *b1, *b2, *b3;
+ u32 bi0, bi1, bi2, bi3;
+ 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);
+
+ u8 *ptr0 = vlib_buffer_get_current (b0);
+ u8 *ptr1 = vlib_buffer_get_current (b1);
+ u8 *ptr2 = vlib_buffer_get_current (b2);
+ u8 *ptr3 = vlib_buffer_get_current (b3);
+ u8 v0 = *ptr0 & 0xf0;
+ u8 v1 = *ptr1 & 0xf0;
+ u8 v2 = *ptr2 & 0xf0;
+ u8 v3 = *ptr3 & 0xf0;
+
+ u8 advance = sizeof(ip4_header_t) + sizeof(udp_header_t);
+
+ vlib_buffer_advance(b0, -advance);
+ vlib_buffer_advance(b1, -advance);
+ vlib_buffer_advance(b2, -advance);
+ vlib_buffer_advance(b3, -advance);
+
+ u8 *outer_ptr0 = vlib_buffer_get_current (b0);
+ u8 *outer_ptr1 = vlib_buffer_get_current (b1);
+ u8 *outer_ptr2 = vlib_buffer_get_current (b2);
+ u8 *outer_ptr3 = vlib_buffer_get_current (b3);
+ u8 outer_v0 = *outer_ptr0 & 0xf0;
+ u8 outer_v1 = *outer_ptr1 & 0xf0;
+ u8 outer_v2 = *outer_ptr2 & 0xf0;
+ u8 outer_v3 = *outer_ptr3 & 0xf0;
+
+ ip46_address_t src0 = {0};
+ ip46_address_t src1 = {0};
+ ip46_address_t src2 = {0};
+ ip46_address_t src3 = {0};
+
+ ip46_address_t dst0 = {0};
+ ip46_address_t dst1 = {0};
+ ip46_address_t dst2 = {0};
+ ip46_address_t dst3 = {0};
+
+ udp_header_t * udp0 = NULL;
+ udp_header_t * udp1 = NULL;
+ udp_header_t * udp2 = NULL;
+ udp_header_t * udp3 = NULL;
+
+ ip46_address_set_ip4(&src0, &((ip4_header_t *)outer_ptr0)->src_address);
+ ip46_address_set_ip4(&dst0, &((ip4_header_t *)outer_ptr0)->dst_address);
+ udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip4_header_t));
+ next0 = v0 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6;
+
+ ip46_address_set_ip4(&src1, &((ip4_header_t *)outer_ptr1)->src_address);
+ ip46_address_set_ip4(&dst1, &((ip4_header_t *)outer_ptr1)->dst_address);
+ udp1 = (udp_header_t *)(outer_ptr1 + sizeof(ip4_header_t));
+ next1 = v1 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6;
+
+ ip46_address_set_ip4(&src2, &((ip4_header_t *)outer_ptr2)->src_address);
+ ip46_address_set_ip4(&dst2, &((ip4_header_t *)outer_ptr2)->dst_address);
+ udp2 = (udp_header_t *)(outer_ptr2 + sizeof(ip4_header_t));
+ next2 = v2 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6;
+
+ ip46_address_set_ip4(&src3, &((ip4_header_t *)outer_ptr3)->src_address);
+ ip46_address_set_ip4(&dst3, &((ip4_header_t *)outer_ptr3)->dst_address);
+ udp3 = (udp_header_t *)(outer_ptr3 + sizeof(ip4_header_t));
+ next3 = v3 == 0x40? UDP4_DECAP_NEXT_LOOKUP_IP4 : UDP4_DECAP_NEXT_LOOKUP_IP6;
+
+ hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3;
+ hicnb0 = hicn_get_buffer(b0);
+ hicnb1 = hicn_get_buffer(b1);
+ hicnb2 = hicn_get_buffer(b2);
+ hicnb3 = hicn_get_buffer(b3);
+
+
+ /* Udp encap-decap tunnels have dst and src addresses and port swapped */
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port);
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst1, &src1, udp1->dst_port, udp1->src_port);
+ vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst2, &src2, udp2->dst_port, udp2->src_port);
+ vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst3, &src3, udp3->dst_port, udp3->src_port);
+
+ if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb1->flags |= (outer_v1 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb2->flags |= (outer_v2 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb3->flags |= (outer_v3 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ udp_decap_trace_buffer (vm, node, 1, b0);
+ udp_decap_trace_buffer (vm, node, 1, b1);
+ udp_decap_trace_buffer (vm, node, 1, b2);
+ udp_decap_trace_buffer (vm, node, 1, b3);
+
+ vlib_buffer_advance(b0, advance);
+ vlib_buffer_advance(b1, advance);
+ vlib_buffer_advance(b2, advance);
+ vlib_buffer_advance(b3, advance);
+
+ vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, bi2, bi3,
+ next0, next1, next2, next3);
+ }
+
+ /* Dual loop, X1 */
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ vlib_buffer_t *b0;
+ u32 bi0;
+ /* udp_encap_t *udp_tunnel0 = 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);
+
+ u8 *ptr0 = vlib_buffer_get_current (b0);
+ u8 v0 = *ptr0 & 0xf0;
+
+ u8 advance = sizeof(ip4_header_t) + sizeof(udp_header_t);;
+
+ vlib_buffer_advance(b0, -advance);
+
+ u8 *outer_ptr0 = vlib_buffer_get_current (b0);
+ u8 outer_v0 = *outer_ptr0 & 0xf0;
+
+ ip46_address_t src0 = {0};
+ ip46_address_t dst0 = {0};
+ udp_header_t * udp0 = NULL;
+
+ ip46_address_set_ip4(&src0, &((ip4_header_t *)outer_ptr0)->src_address);
+ ip46_address_set_ip4(&dst0, &((ip4_header_t *)outer_ptr0)->dst_address);
+ udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip4_header_t));
+ next0 = v0 == 0x40 ? UDP4_DECAP_NEXT_LOOKUP_IP4: UDP4_DECAP_NEXT_LOOKUP_IP6;
+
+ hicn_buffer_t *hicnb0 = hicn_get_buffer(b0);
+
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port);
+
+ if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb0->flags |= (outer_v0 == 0x40 ? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ udp_decap_trace_buffer (vm, node, 1, b0);
+
+ vlib_buffer_advance(b0, advance);
+
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+
+ }
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ return (frame->n_vectors);
+}
+
+
+/*
+ * Node registration for the interest forwarder node
+ */
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE(udp4_decap_node) =
+{
+ .function = udp4_decap_node_fn,
+ .name = "udp4-decap",
+ .vector_size = sizeof(u32),
+ .format_trace = format_udp_decap_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(udp_decap_error_strings),
+ .error_strings = udp_decap_error_strings,
+ .n_next_nodes = UDP4_DECAP_N_NEXT,
+ /* edit / add dispositions here */
+ .next_nodes =
+ {
+ [UDP4_DECAP_NEXT_LOOKUP_IP4] = "ip4-lookup",
+ [UDP4_DECAP_NEXT_LOOKUP_IP6] = "ip6-lookup"
+ },
+};
+/* *INDENT-ON* */
+
+static uword
+udp6_decap_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ u32 n_left_from, *from, *to_next, next_index;
+
+ 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);
+
+ /* Dual loop, X2 */
+ while (n_left_from >= 8 && n_left_to_next >= 4)
+ {
+ vlib_buffer_t *b0, *b1, *b2, *b3;
+ u32 bi0, bi1, bi2, bi3;
+ 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);
+
+ u8 *ptr0 = vlib_buffer_get_current (b0);
+ u8 *ptr1 = vlib_buffer_get_current (b1);
+ u8 *ptr2 = vlib_buffer_get_current (b2);
+ u8 *ptr3 = vlib_buffer_get_current (b3);
+ u8 v0 = *ptr0 & 0xf0;
+ u8 v1 = *ptr1 & 0xf0;
+ u8 v2 = *ptr2 & 0xf0;
+ u8 v3 = *ptr3 & 0xf0;
+
+ u8 advance = sizeof(ip6_header_t) + sizeof(udp_header_t);
+
+ vlib_buffer_advance(b0, -advance);
+ vlib_buffer_advance(b1, -advance);
+ vlib_buffer_advance(b2, -advance);
+ vlib_buffer_advance(b3, -advance);
+
+ u8 *outer_ptr0 = vlib_buffer_get_current (b0);
+ u8 *outer_ptr1 = vlib_buffer_get_current (b1);
+ u8 *outer_ptr2 = vlib_buffer_get_current (b2);
+ u8 *outer_ptr3 = vlib_buffer_get_current (b3);
+ u8 outer_v0 = *outer_ptr0 & 0xf0;
+ u8 outer_v1 = *outer_ptr1 & 0xf0;
+ u8 outer_v2 = *outer_ptr2 & 0xf0;
+ u8 outer_v3 = *outer_ptr3 & 0xf0;
+
+ ip46_address_t src0 = {0};
+ ip46_address_t src1 = {0};
+ ip46_address_t src2 = {0};
+ ip46_address_t src3 = {0};
+
+ ip46_address_t dst0 = {0};
+ ip46_address_t dst1 = {0};
+ ip46_address_t dst2 = {0};
+ ip46_address_t dst3 = {0};
+
+ udp_header_t * udp0 = NULL;
+ udp_header_t * udp1 = NULL;
+ udp_header_t * udp2 = NULL;
+ udp_header_t * udp3 = NULL;
+
+ ip46_address_set_ip6(&src0, &((ip6_header_t *)outer_ptr0)->src_address);
+ ip46_address_set_ip6(&dst0, &((ip6_header_t *)outer_ptr0)->dst_address);
+ udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip6_header_t));
+ next0 = v0 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6;
+
+ ip46_address_set_ip6(&src1, &((ip6_header_t *)outer_ptr1)->src_address);
+ ip46_address_set_ip6(&dst1, &((ip6_header_t *)outer_ptr1)->dst_address);
+ udp1 = (udp_header_t *)(outer_ptr1 + sizeof(ip6_header_t));
+ next1 = v1 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6;
+
+ ip46_address_set_ip6(&src2, &((ip6_header_t *)outer_ptr2)->src_address);
+ ip46_address_set_ip6(&dst2, &((ip6_header_t *)outer_ptr2)->dst_address);
+ udp2 = (udp_header_t *)(outer_ptr2 + sizeof(ip6_header_t));
+ next2 = v2 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6;
+
+ ip46_address_set_ip6(&src3, &((ip6_header_t *)outer_ptr3)->src_address);
+ ip46_address_set_ip6(&dst3, &((ip6_header_t *)outer_ptr3)->dst_address);
+ udp3 = (udp_header_t *)(outer_ptr3 + sizeof(ip6_header_t));
+ next3 = v3 == 0x40 ? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6;
+
+ hicn_buffer_t *hicnb0, *hicnb1, *hicnb2, *hicnb3;
+ hicnb0 = hicn_get_buffer(b0);
+ hicnb1 = hicn_get_buffer(b1);
+ hicnb2 = hicn_get_buffer(b2);
+ hicnb3 = hicn_get_buffer(b3);
+
+
+ /* Udp encap-decap tunnels have dst and src addresses and port swapped */
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port);
+ vnet_buffer (b1)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst1, &src1, udp1->dst_port, udp1->src_port);
+ vnet_buffer (b2)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst2, &src2, udp2->dst_port, udp2->src_port);
+ vnet_buffer (b3)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst3, &src3, udp3->dst_port, udp3->src_port);
+
+ if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ if (vnet_buffer (b1)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb1->flags |= (outer_v1 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ if (vnet_buffer (b2)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb2->flags |= (outer_v2 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ if (vnet_buffer (b3)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb3->flags |= (outer_v3 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ udp_decap_trace_buffer (vm, node, 0, b0);
+ udp_decap_trace_buffer (vm, node, 0, b1);
+ udp_decap_trace_buffer (vm, node, 0, b2);
+ udp_decap_trace_buffer (vm, node, 0, b3);
+
+ vlib_buffer_advance(b0, advance);
+ vlib_buffer_advance(b1, advance);
+ vlib_buffer_advance(b2, advance);
+ vlib_buffer_advance(b3, advance);
+
+ vlib_validate_buffer_enqueue_x4 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, bi1, bi2, bi3,
+ next0, next1, next2, next3);
+ }
+
+ /* Dual loop, X1 */
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ vlib_buffer_t *b0;
+ u32 bi0;
+ /* udp_encap_t *udp_tunnel0 = 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);
+
+ u8 *ptr0 = vlib_buffer_get_current (b0);
+ u8 v0 = *ptr0 & 0xf0;
+
+ u8 advance = sizeof(ip6_header_t) + sizeof(udp_header_t);
+
+ vlib_buffer_advance(b0, -advance);
+
+ u8 *outer_ptr0 = vlib_buffer_get_current (b0);
+ u8 outer_v0 = *outer_ptr0 & 0xf0;
+
+ ip46_address_t src0 = {0};
+ ip46_address_t dst0 = {0};
+ udp_header_t * udp0 = NULL;
+
+ ip46_address_set_ip6(&src0, &((ip6_header_t *)outer_ptr0)->src_address);
+ ip46_address_set_ip6(&dst0, &((ip6_header_t *)outer_ptr0)->dst_address);
+ udp0 = (udp_header_t *)(outer_ptr0 + sizeof(ip6_header_t));
+ next0 = v0 == 0x40? UDP6_DECAP_NEXT_LOOKUP_IP4 : UDP6_DECAP_NEXT_LOOKUP_IP6;
+
+ hicn_buffer_t *hicnb0 = hicn_get_buffer(b0);
+
+ vnet_buffer (b0)->ip.adj_index[VLIB_RX] = udp_tunnel_get(&dst0, &src0, udp0->dst_port, udp0->src_port);
+
+ if (vnet_buffer (b0)->ip.adj_index[VLIB_RX] !=
+ UDP_TUNNEL_INVALID)
+ hicnb0->flags |= (outer_v0 == 0x40? HICN_BUFFER_FLAGS_FROM_UDP4_TUNNEL : HICN_BUFFER_FLAGS_FROM_UDP6_TUNNEL);
+
+ udp_decap_trace_buffer (vm, node, 0, b0);
+
+ vlib_buffer_advance(b0, advance);
+
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+
+ }
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ return (frame->n_vectors);
+}
+
+
+/*
+ * Node registration for the interest forwarder node
+ */
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE(udp6_decap_node) =
+{
+ .function = udp6_decap_node_fn,
+ .name = "udp6-decap",
+ .vector_size = sizeof(u32),
+ .format_trace = format_udp_decap_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(udp_decap_error_strings),
+ .error_strings = udp_decap_error_strings,
+ .n_next_nodes = UDP6_DECAP_N_NEXT,
+ /* edit / add dispositions here */
+ .next_nodes =
+ {
+ [UDP6_DECAP_NEXT_LOOKUP_IP4] = "ip4-lookup",
+ [UDP6_DECAP_NEXT_LOOKUP_IP6] = "ip6-lookup"
+ },
+};
+/* *INDENT-ON* */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/hicn-plugin/src/udp_tunnels/udp_tunnel.c b/hicn-plugin/src/udp_tunnels/udp_tunnel.c
new file mode 100644
index 000000000..872e4cd82
--- /dev/null
+++ b/hicn-plugin/src/udp_tunnels/udp_tunnel.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2020 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 <vlib/vlib.h>
+#include <vnet/vnet.h>
+#include <vppinfra/bihash_40_8.h>
+#include <vnet/fib/fib_table.h>
+
+#include "../error.h"
+#include "../strategy_dpo_ctx.h"
+#include "udp_tunnel.h"
+
+clib_bihash_40_8_t udp_tunnels_hashtb;
+dpo_type_t dpo_type_udp_ip4;
+dpo_type_t dpo_type_udp_ip6;
+
+u32 udp_tunnel_add (fib_protocol_t proto,
+ index_t fib_index,
+ const ip46_address_t * src_ip,
+ const ip46_address_t * dst_ip,
+ u16 src_port,
+ u16 dst_port,
+ udp_encap_fixup_flags_t flags)
+{
+ vlib_main_t *vm = vlib_get_main();
+ clib_bihash_kv_40_8_t kv;
+ clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t));
+ clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t));
+ kv.key[4] = (clib_host_to_net_u16(src_port) << 16) + clib_host_to_net_u16(dst_port);
+
+ clib_bihash_kv_40_8_t value;
+ int rv = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value);
+
+ if (rv != 0)
+ {
+ u32 uei = udp_encap_add_and_lock(proto, fib_index, src_ip, dst_ip, src_port, dst_port, flags);
+ kv.value = uei;
+ clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 1);
+ value.value = kv.value;
+ if (proto == FIB_PROTOCOL_IP4)
+ {
+ udp_register_dst_port(vm, src_port, udp4_decap_node.index, 1);
+ }
+ else
+ {
+ udp_register_dst_port(vm, src_port, udp6_decap_node.index, 0);
+ }
+ }
+
+ return value.value;
+}
+
+void udp_tunnel_add_existing (index_t uei, dpo_proto_t proto)
+{
+ vlib_main_t *vm = vlib_get_main();
+ udp_encap_t * udp_encap = udp_encap_get(uei);
+ clib_bihash_kv_40_8_t kv;
+
+ ip46_address_t src = {0};
+ ip46_address_t dst = {0};
+ u16 src_port = 0, dst_port = 0;
+
+ switch (proto)
+ {
+ case DPO_PROTO_IP4:
+ ip46_address_set_ip4(&src, &(udp_encap->ue_hdrs.ip4.ue_ip4.src_address));
+ ip46_address_set_ip4(&dst, &(udp_encap->ue_hdrs.ip4.ue_ip4.dst_address));
+ src_port = udp_encap->ue_hdrs.ip4.ue_udp.src_port;
+ dst_port = udp_encap->ue_hdrs.ip4.ue_udp.dst_port;
+ break;
+ case DPO_PROTO_IP6:
+ ip46_address_set_ip6(&src, &(udp_encap->ue_hdrs.ip6.ue_ip6.src_address));
+ ip46_address_set_ip6(&dst, &(udp_encap->ue_hdrs.ip6.ue_ip6.dst_address));
+ src_port = udp_encap->ue_hdrs.ip6.ue_udp.src_port;
+ dst_port = udp_encap->ue_hdrs.ip6.ue_udp.dst_port;
+ break;
+ default:
+ break;
+ }
+
+ clib_memcpy(&kv.key[0], &src, sizeof(ip46_address_t));
+ clib_memcpy(&kv.key[2], &dst, sizeof(ip46_address_t));
+ kv.key[4] = (src_port << 16) + dst_port ;
+ kv.value = uei;
+
+ clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 1);
+
+ if (proto == DPO_PROTO_IP4)
+ {
+ udp_register_dst_port(vm, clib_net_to_host_u16(src_port), udp4_decap_node.index, 1);
+ }
+ else
+ {
+ udp_register_dst_port(vm, clib_net_to_host_u16(src_port), udp6_decap_node.index, 0);
+ }
+}
+
+int udp_tunnel_del (fib_protocol_t proto,
+ index_t fib_index,
+ const ip46_address_t * src_ip,
+ const ip46_address_t * dst_ip,
+ u16 src_port,
+ u16 dst_port,
+ udp_encap_fixup_flags_t flags)
+{
+ clib_bihash_kv_40_8_t kv;
+ clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t));
+ clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t));
+ kv.key[4] = (clib_host_to_net_u16(src_port) << 16) + clib_host_to_net_u16(dst_port);
+
+ clib_bihash_kv_40_8_t value;
+ int ret = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value);
+
+ if (ret == 0)
+ {
+ udp_encap_unlock((u32)value.value);
+ clib_bihash_add_del_40_8(&udp_tunnels_hashtb, &kv, 0);
+ ret = HICN_ERROR_NONE;
+ }
+ else
+ {
+ ret = HICN_ERROR_UDP_TUNNEL_NOT_FOUND;
+ }
+
+ return ret;
+}
+
+u32 udp_tunnel_get(const ip46_address_t * src_ip,
+ const ip46_address_t * dst_ip,
+ u16 src_port,
+ u16 dst_port)
+{
+ clib_bihash_kv_40_8_t kv;
+ clib_memcpy(&kv.key[0], src_ip, sizeof(ip46_address_t));
+ clib_memcpy(&kv.key[2], dst_ip, sizeof(ip46_address_t));
+ kv.key[4] = (src_port << 16) + dst_port;
+
+ clib_bihash_kv_40_8_t value;
+ int ret = clib_bihash_search_40_8 (&udp_tunnels_hashtb, &kv, &value);
+
+ return ret == 0 ? (u32)value.value : UDP_TUNNEL_INVALID;
+}
+
+
+void udp_tunnel_init()
+{
+ clib_bihash_init_40_8(&udp_tunnels_hashtb, "udp encap table",
+ 2048, 256 << 20);
+
+ /*
+ * Udp encap does not expose the dpo type when it registers.
+ * In the following we understand what is the dpo type for a udp_encap dpo.
+ */
+ ip46_address_t src = {0};
+ ip46_address_t dst = {0};
+
+ src.ip6.as_u8[15] = 1;
+ dst.ip6.as_u8[15] = 2;
+
+ u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, HICN_FIB_TABLE);
+ u32 uei = udp_encap_add_and_lock(FIB_PROTOCOL_IP6, fib_index, &src, &dst, 4444, 4444, UDP_ENCAP_FIXUP_NONE);
+
+ dpo_id_t temp = DPO_INVALID;
+ udp_encap_contribute_forwarding(uei, DPO_PROTO_IP6, &temp);
+ dpo_type_udp_ip6 = temp.dpoi_type;
+ udp_encap_unlock(uei);
+
+ dpo_id_t temp2 = DPO_INVALID;
+ fib_index = fib_table_find (FIB_PROTOCOL_IP4, HICN_FIB_TABLE);
+ uei = udp_encap_add_and_lock(FIB_PROTOCOL_IP4, fib_index, &src, &dst, 4444, 4444, UDP_ENCAP_FIXUP_NONE);
+ udp_encap_contribute_forwarding(uei, DPO_PROTO_IP4, &temp2);
+ dpo_type_udp_ip4 = temp2.dpoi_type;
+ udp_encap_unlock(uei);
+}
+
+static clib_error_t *
+udp_tunnel_command_fn (vlib_main_t * vm,
+ unformat_input_t * main_input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = NULL;
+ ip46_address_t src_ip = {0}, dst_ip = {0};
+ u32 table_id, src_port, dst_port;
+ fib_protocol_t fproto;
+ u8 is_del;
+ index_t uei;
+
+ is_del = 0;
+ fproto = FIB_PROTOCOL_MAX;
+ uei = ~0;
+ table_id = HICN_FIB_TABLE;
+
+ /* Get a line of input. */
+ if (unformat_user (main_input, unformat_line_input, line_input))
+ {
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "index %d", &uei))
+ ;
+ else if (unformat (line_input, "add"))
+ is_del = 0;
+ else if (unformat (line_input, "del"))
+ is_del = 1;
+ else if (unformat (line_input, "%U %U",
+ unformat_ip4_address,
+ &src_ip.ip4, unformat_ip4_address, &dst_ip.ip4))
+ fproto = FIB_PROTOCOL_IP4;
+ else if (unformat (line_input, "%U %U",
+ unformat_ip6_address,
+ &src_ip.ip6, unformat_ip6_address, &dst_ip.ip6))
+ fproto = FIB_PROTOCOL_IP6;
+ else if (unformat (line_input, "%d %d", &src_port, &dst_port))
+ ;
+ else if (unformat (line_input, "table-id %d", &table_id))
+ ;
+ else
+ {
+ error = unformat_parse_error (line_input);
+ goto done;
+ }
+ }
+ }
+
+ index_t fib_index = fib_table_find (fproto, table_id);
+ if (~0 == fib_index)
+ {
+ error = clib_error_return (0, "Nonexistent table id %d", table_id);
+ goto done;
+ }
+
+ if (!is_del && fproto != FIB_PROTOCOL_MAX)
+ {
+ uei = udp_tunnel_add(fproto, fib_index, &src_ip, &dst_ip, src_port, dst_port, UDP_ENCAP_FIXUP_NONE);
+
+ vlib_cli_output (vm, "udp-encap: %d\n", uei);
+ }
+ else if (is_del)
+ {
+ int ret = udp_tunnel_del(fproto, fib_index, &src_ip, &dst_ip, src_port, dst_port, UDP_ENCAP_FIXUP_NONE);
+ error = (ret == HICN_ERROR_NONE) ? 0 : clib_error_return (0, "%s\n",
+ get_error_string
+ (ret));
+ }
+ else
+ {
+ error = clib_error_return (0, "specify some IP addresses");
+ }
+
+ done:
+ unformat_free (line_input);
+ return error;
+
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (udp_tunnel_command, static) =
+ {
+ .path = "udp tunnel",
+ .short_help = "udp tunnel [add/del] src_address dst_address src_port dst_port",
+ .function = udp_tunnel_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/udp_tunnels/udp_tunnel.h b/hicn-plugin/src/udp_tunnels/udp_tunnel.h
new file mode 100644
index 000000000..8f38a47e4
--- /dev/null
+++ b/hicn-plugin/src/udp_tunnels/udp_tunnel.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020 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 __UDP_TUNNEL__
+#define __UDP_TUNNEL__
+
+#include <vlib/vlib.h>
+#include <vppinfra/error.h>
+#include <vnet/udp/udp_encap.h>
+
+#define UDP_TUNNEL_INVALID ~0
+
+extern dpo_type_t dpo_type_udp_ip4;
+extern dpo_type_t dpo_type_udp_ip6;
+
+extern vlib_node_registration_t udp4_decap_node;
+extern vlib_node_registration_t udp6_decap_node;
+
+
+u32 udp_tunnel_add (fib_protocol_t proto,
+ index_t fib_index,
+ const ip46_address_t * src_ip,
+ const ip46_address_t * dst_ip,
+ u16 src_port,
+ u16 dst_port,
+ udp_encap_fixup_flags_t flags);
+
+u32 udp_tunnel_get(const ip46_address_t * src_ip,
+ const ip46_address_t * dst_ip,
+ u16 src_port,
+ u16 dst_port);
+
+int udp_tunnel_del (fib_protocol_t proto,
+ index_t fib_index,
+ const ip46_address_t * src_ip,
+ const ip46_address_t * dst_ip,
+ u16 src_port,
+ u16 dst_port,
+ udp_encap_fixup_flags_t flags);
+
+void udp_tunnel_add_existing (index_t uei, dpo_proto_t proto);
+
+void udp_tunnel_init();
+
+#endif