aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/vxlan-gpe
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/vxlan-gpe')
-rw-r--r--src/vnet/vxlan-gpe/decap.c443
-rw-r--r--src/vnet/vxlan-gpe/encap.c51
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.api59
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.c141
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.h34
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe_api.c155
6 files changed, 504 insertions, 379 deletions
diff --git a/src/vnet/vxlan-gpe/decap.c b/src/vnet/vxlan-gpe/decap.c
index 035e8a3fd6a..d4c7424630d 100644
--- a/src/vnet/vxlan-gpe/decap.c
+++ b/src/vnet/vxlan-gpe/decap.c
@@ -79,10 +79,106 @@ format_vxlan_gpe_with_length (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 *);
-
return s;
}
+typedef struct
+{
+ vxlan4_gpe_tunnel_key_t key;
+ vxlan_gpe_decap_info_t val;
+} vxlan4_gpe_tunnel_cache_t;
+
+static const vxlan_gpe_decap_info_t decap_not_found = {
+ .tunnel_index = ~0,
+ .next_index = VXLAN_GPE_INPUT_NEXT_DROP,
+ .error = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL
+};
+
+always_inline vxlan_gpe_decap_info_t
+vxlan4_gpe_find_tunnel (vxlan_gpe_main_t *nngm,
+ vxlan4_gpe_tunnel_cache_t *cache,
+ ip4_vxlan_gpe_header_t *iuvn4_0)
+{
+ /* Make sure VXLAN GPE tunnel exist according to packet S/D IP, UDP port and
+ * VNI */
+ vxlan4_gpe_tunnel_key_t key4 = {
+ .local = iuvn4_0->ip4.dst_address.as_u32,
+ .remote = iuvn4_0->ip4.src_address.as_u32,
+ .vni = iuvn4_0->vxlan.vni_res,
+ .port = (u32) iuvn4_0->udp.dst_port,
+ };
+
+ if (PREDICT_TRUE (key4.as_u64[0] == cache->key.as_u64[0] &&
+ key4.as_u64[1] == cache->key.as_u64[1]))
+ {
+ /* cache hit */
+ return cache->val;
+ }
+
+ uword *p = hash_get_mem (nngm->vxlan4_gpe_tunnel_by_key, &key4);
+ if (PREDICT_TRUE (p != 0))
+ {
+ u32 next = (iuvn4_0->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
+ nngm->decap_next_node_list[iuvn4_0->vxlan.protocol] :
+ VXLAN_GPE_INPUT_NEXT_DROP;
+
+ cache->key.as_u64[0] = key4.as_u64[0];
+ cache->key.as_u64[1] = key4.as_u64[1];
+
+ cache->val.error = 0;
+ cache->val.tunnel_index = p[0];
+ cache->val.next_index = next;
+
+ return cache->val;
+ }
+
+ return decap_not_found;
+}
+
+typedef struct
+{
+ vxlan6_gpe_tunnel_key_t key;
+ vxlan_gpe_decap_info_t val;
+} vxlan6_gpe_tunnel_cache_t;
+
+always_inline vxlan_gpe_decap_info_t
+vxlan6_gpe_find_tunnel (vxlan_gpe_main_t *nngm,
+ vxlan6_gpe_tunnel_cache_t *cache,
+ ip6_vxlan_gpe_header_t *iuvn6_0)
+{
+ /* Make sure VXLAN GPE tunnel exist according to packet S/D IP, UDP port and
+ * VNI */
+ vxlan6_gpe_tunnel_key_t key6;
+
+ ip6_address_copy (&key6.local, &iuvn6_0->ip6.dst_address);
+ ip6_address_copy (&key6.remote, &iuvn6_0->ip6.src_address);
+ key6.vni = iuvn6_0->vxlan.vni_res;
+ key6.port = iuvn6_0->udp.dst_port;
+
+ if (PREDICT_TRUE (memcmp (&key6, &cache->key, sizeof (cache->key)) == 0))
+ {
+ /* cache hit */
+ return cache->val;
+ }
+
+ uword *p = hash_get_mem (nngm->vxlan6_gpe_tunnel_by_key, &key6);
+ if (PREDICT_TRUE (p != 0))
+ {
+ u32 next = (iuvn6_0->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
+ nngm->decap_next_node_list[iuvn6_0->vxlan.protocol] :
+ VXLAN_GPE_INPUT_NEXT_DROP;
+
+ clib_memcpy_fast (&cache->key, &key6, sizeof (key6));
+ cache->val.error = 0;
+ cache->val.tunnel_index = p[0];
+ cache->val.next_index = next;
+
+ return cache->val;
+ }
+
+ return decap_not_found;
+}
+
/**
* @brief Common processing for IPv4 and IPv6 VXLAN GPE decap dispatch functions
*
@@ -111,17 +207,16 @@ vxlan_gpe_input (vlib_main_t * vm,
vxlan_gpe_main_t *nngm = &vxlan_gpe_main;
vnet_main_t *vnm = nngm->vnet_main;
vnet_interface_main_t *im = &vnm->interface_main;
- u32 last_tunnel_index = ~0;
- vxlan4_gpe_tunnel_key_t last_key4;
- vxlan6_gpe_tunnel_key_t last_key6;
+ vxlan4_gpe_tunnel_cache_t last4;
+ vxlan6_gpe_tunnel_cache_t last6;
u32 pkts_decapsulated = 0;
u32 thread_index = vm->thread_index;
u32 stats_sw_if_index, stats_n_packets, stats_n_bytes;
if (is_ip4)
- clib_memset (&last_key4, 0xff, sizeof (last_key4));
+ clib_memset (&last4, 0xff, sizeof (last4));
else
- clib_memset (&last_key6, 0xff, sizeof (last_key6));
+ clib_memset (&last6, 0xff, sizeof (last6));
from = vlib_frame_vector_args (from_frame);
n_left_from = from_frame->n_vectors;
@@ -143,11 +238,8 @@ vxlan_gpe_input (vlib_main_t * vm,
u32 next0, next1;
ip4_vxlan_gpe_header_t *iuvn4_0, *iuvn4_1;
ip6_vxlan_gpe_header_t *iuvn6_0, *iuvn6_1;
- uword *p0, *p1;
- u32 tunnel_index0, tunnel_index1;
+ vxlan_gpe_decap_info_t di0, di1;
vxlan_gpe_tunnel_t *t0, *t1;
- vxlan4_gpe_tunnel_key_t key4_0, key4_1;
- vxlan6_gpe_tunnel_key_t key6_0, key6_1;
u32 error0, error1;
u32 sw_if_index0, sw_if_index1, len0, len1;
@@ -193,6 +285,9 @@ vxlan_gpe_input (vlib_main_t * vm,
/* pop (ip, udp, vxlan) */
vlib_buffer_advance (b0, sizeof (*iuvn4_0));
vlib_buffer_advance (b1, sizeof (*iuvn4_1));
+
+ di0 = vxlan4_gpe_find_tunnel (nngm, &last4, iuvn4_0);
+ di1 = vxlan4_gpe_find_tunnel (nngm, &last4, iuvn4_1);
}
else
{
@@ -210,125 +305,20 @@ vxlan_gpe_input (vlib_main_t * vm,
/* pop (ip, udp, vxlan) */
vlib_buffer_advance (b0, sizeof (*iuvn6_0));
vlib_buffer_advance (b1, sizeof (*iuvn6_1));
- }
- tunnel_index0 = ~0;
- tunnel_index1 = ~0;
- error0 = 0;
- error1 = 0;
-
- if (is_ip4)
- {
- next0 =
- (iuvn4_0->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
- nngm->decap_next_node_list[iuvn4_0->vxlan.protocol] :
- VXLAN_GPE_INPUT_NEXT_DROP;
- next1 =
- (iuvn4_1->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
- nngm->decap_next_node_list[iuvn4_1->vxlan.protocol] :
- VXLAN_GPE_INPUT_NEXT_DROP;
-
- key4_0.local = iuvn4_0->ip4.dst_address.as_u32;
- key4_1.local = iuvn4_1->ip4.dst_address.as_u32;
-
- key4_0.remote = iuvn4_0->ip4.src_address.as_u32;
- key4_1.remote = iuvn4_1->ip4.src_address.as_u32;
-
- key4_0.vni = iuvn4_0->vxlan.vni_res;
- key4_1.vni = iuvn4_1->vxlan.vni_res;
-
- key4_0.pad = 0;
- key4_1.pad = 0;
+ di0 = vxlan6_gpe_find_tunnel (nngm, &last6, iuvn6_0);
+ di1 = vxlan6_gpe_find_tunnel (nngm, &last6, iuvn6_1);
}
- else /* is_ip6 */
- {
- next0 = (iuvn6_0->vxlan.protocol < node->n_next_nodes) ?
- iuvn6_0->vxlan.protocol : VXLAN_GPE_INPUT_NEXT_DROP;
- next1 = (iuvn6_1->vxlan.protocol < node->n_next_nodes) ?
- iuvn6_1->vxlan.protocol : VXLAN_GPE_INPUT_NEXT_DROP;
-
- key6_0.local.as_u64[0] = iuvn6_0->ip6.dst_address.as_u64[0];
- key6_0.local.as_u64[1] = iuvn6_0->ip6.dst_address.as_u64[1];
- key6_1.local.as_u64[0] = iuvn6_1->ip6.dst_address.as_u64[0];
- key6_1.local.as_u64[1] = iuvn6_1->ip6.dst_address.as_u64[1];
-
- key6_0.remote.as_u64[0] = iuvn6_0->ip6.src_address.as_u64[0];
- key6_0.remote.as_u64[1] = iuvn6_0->ip6.src_address.as_u64[1];
- key6_1.remote.as_u64[0] = iuvn6_1->ip6.src_address.as_u64[0];
- key6_1.remote.as_u64[1] = iuvn6_1->ip6.src_address.as_u64[1];
-
- key6_0.vni = iuvn6_0->vxlan.vni_res;
- key6_1.vni = iuvn6_1->vxlan.vni_res;
- }
-
- /* Processing packet 0 */
- if (is_ip4)
- {
- /* Processing for key4_0 */
- if (PREDICT_FALSE ((key4_0.as_u64[0] != last_key4.as_u64[0])
- || (key4_0.as_u64[1] !=
- last_key4.as_u64[1])))
- {
- p0 = hash_get_mem (nngm->vxlan4_gpe_tunnel_by_key, &key4_0);
-
- if (p0 == 0)
- {
- error0 = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL;
- goto trace0;
- }
- last_key4.as_u64[0] = key4_0.as_u64[0];
- last_key4.as_u64[1] = key4_0.as_u64[1];
- tunnel_index0 = last_tunnel_index = p0[0];
- }
- else
- tunnel_index0 = last_tunnel_index;
- }
- else /* is_ip6 */
+ /* Process packet 0 */
+ next0 = di0.next_index;
+ error0 = di0.error;
+ if (error0 != 0)
{
- next0 =
- (iuvn6_0->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
- nngm->decap_next_node_list[iuvn6_0->vxlan.protocol] :
- VXLAN_GPE_INPUT_NEXT_DROP;
- next1 =
- (iuvn6_1->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
- nngm->decap_next_node_list[iuvn6_1->vxlan.protocol] :
- VXLAN_GPE_INPUT_NEXT_DROP;
-
- key6_0.local.as_u64[0] = iuvn6_0->ip6.dst_address.as_u64[0];
- key6_0.local.as_u64[1] = iuvn6_0->ip6.dst_address.as_u64[1];
- key6_1.local.as_u64[0] = iuvn6_1->ip6.dst_address.as_u64[0];
- key6_1.local.as_u64[1] = iuvn6_1->ip6.dst_address.as_u64[1];
-
- key6_0.remote.as_u64[0] = iuvn6_0->ip6.src_address.as_u64[0];
- key6_0.remote.as_u64[1] = iuvn6_0->ip6.src_address.as_u64[1];
- key6_1.remote.as_u64[0] = iuvn6_1->ip6.src_address.as_u64[0];
- key6_1.remote.as_u64[1] = iuvn6_1->ip6.src_address.as_u64[1];
-
- key6_0.vni = iuvn6_0->vxlan.vni_res;
- key6_1.vni = iuvn6_1->vxlan.vni_res;
-
- /* Processing for key6_0 */
- if (PREDICT_FALSE
- (memcmp (&key6_0, &last_key6, sizeof (last_key6)) != 0))
- {
- p0 = hash_get_mem (nngm->vxlan6_gpe_tunnel_by_key, &key6_0);
-
- if (p0 == 0)
- {
- error0 = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL;
- goto trace0;
- }
-
- memcpy (&last_key6, &key6_0, sizeof (key6_0));
- tunnel_index0 = last_tunnel_index = p0[0];
- }
- else
- tunnel_index0 = last_tunnel_index;
+ goto trace0;
}
- t0 = pool_elt_at_index (nngm->tunnels, tunnel_index0);
-
+ t0 = pool_elt_at_index (nngm->tunnels, di0.tunnel_index);
sw_if_index0 = t0->sw_if_index;
len0 = vlib_buffer_length_in_chain (vm, b0);
@@ -372,54 +362,18 @@ vxlan_gpe_input (vlib_main_t * vm,
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->next_index = next0;
tr->error = error0;
- tr->tunnel_index = tunnel_index0;
+ tr->tunnel_index = di0.tunnel_index;
}
/* Process packet 1 */
- if (is_ip4)
+ next1 = di1.next_index;
+ error1 = di1.error;
+ if (error1 != 0)
{
- /* Processing for key4_1 */
- if (PREDICT_FALSE ((key4_1.as_u64[0] != last_key4.as_u64[0])
- || (key4_1.as_u64[1] !=
- last_key4.as_u64[1])))
- {
- p1 = hash_get_mem (nngm->vxlan4_gpe_tunnel_by_key, &key4_1);
-
- if (p1 == 0)
- {
- error1 = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL;
- goto trace1;
- }
-
- last_key4.as_u64[0] = key4_1.as_u64[0];
- last_key4.as_u64[1] = key4_1.as_u64[1];
- tunnel_index1 = last_tunnel_index = p1[0];
- }
- else
- tunnel_index1 = last_tunnel_index;
+ goto trace1;
}
- else /* is_ip6 */
- {
- /* Processing for key6_1 */
- if (PREDICT_FALSE
- (memcmp (&key6_1, &last_key6, sizeof (last_key6)) != 0))
- {
- p1 = hash_get_mem (nngm->vxlan6_gpe_tunnel_by_key, &key6_1);
- if (p1 == 0)
- {
- error1 = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL;
- goto trace1;
- }
-
- memcpy (&last_key6, &key6_1, sizeof (key6_1));
- tunnel_index1 = last_tunnel_index = p1[0];
- }
- else
- tunnel_index1 = last_tunnel_index;
- }
-
- t1 = pool_elt_at_index (nngm->tunnels, tunnel_index1);
+ t1 = pool_elt_at_index (nngm->tunnels, di1.tunnel_index);
sw_if_index1 = t1->sw_if_index;
len1 = vlib_buffer_length_in_chain (vm, b1);
@@ -466,7 +420,7 @@ vxlan_gpe_input (vlib_main_t * vm,
vlib_add_trace (vm, node, b1, sizeof (*tr));
tr->next_index = next1;
tr->error = error1;
- tr->tunnel_index = tunnel_index1;
+ tr->tunnel_index = di1.tunnel_index;
}
vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
@@ -481,11 +435,8 @@ vxlan_gpe_input (vlib_main_t * vm,
u32 next0;
ip4_vxlan_gpe_header_t *iuvn4_0;
ip6_vxlan_gpe_header_t *iuvn6_0;
- uword *p0;
- u32 tunnel_index0;
+ vxlan_gpe_decap_info_t di0;
vxlan_gpe_tunnel_t *t0;
- vxlan4_gpe_tunnel_key_t key4_0;
- vxlan6_gpe_tunnel_key_t key6_0;
u32 error0;
u32 sw_if_index0, len0;
@@ -509,6 +460,8 @@ vxlan_gpe_input (vlib_main_t * vm,
/* pop (ip, udp, vxlan) */
vlib_buffer_advance (b0, sizeof (*iuvn4_0));
+
+ di0 = vxlan4_gpe_find_tunnel (nngm, &last4, iuvn4_0);
}
else
{
@@ -521,77 +474,18 @@ vxlan_gpe_input (vlib_main_t * vm,
/* pop (ip, udp, vxlan) */
vlib_buffer_advance (b0, sizeof (*iuvn6_0));
- }
-
- tunnel_index0 = ~0;
- error0 = 0;
- if (is_ip4)
- {
- next0 =
- (iuvn4_0->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
- nngm->decap_next_node_list[iuvn4_0->vxlan.protocol] :
- VXLAN_GPE_INPUT_NEXT_DROP;
-
- key4_0.local = iuvn4_0->ip4.dst_address.as_u32;
- key4_0.remote = iuvn4_0->ip4.src_address.as_u32;
- key4_0.vni = iuvn4_0->vxlan.vni_res;
- key4_0.pad = 0;
-
- /* Processing for key4_0 */
- if (PREDICT_FALSE ((key4_0.as_u64[0] != last_key4.as_u64[0])
- || (key4_0.as_u64[1] !=
- last_key4.as_u64[1])))
- {
- p0 = hash_get_mem (nngm->vxlan4_gpe_tunnel_by_key, &key4_0);
-
- if (p0 == 0)
- {
- error0 = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL;
- goto trace00;
- }
-
- last_key4.as_u64[0] = key4_0.as_u64[0];
- last_key4.as_u64[1] = key4_0.as_u64[1];
- tunnel_index0 = last_tunnel_index = p0[0];
+ di0 = vxlan6_gpe_find_tunnel (nngm, &last6, iuvn6_0);
}
- else
- tunnel_index0 = last_tunnel_index;
- }
- else /* is_ip6 */
- {
- next0 =
- (iuvn6_0->vxlan.protocol < VXLAN_GPE_PROTOCOL_MAX) ?
- nngm->decap_next_node_list[iuvn6_0->vxlan.protocol] :
- VXLAN_GPE_INPUT_NEXT_DROP;
-
- key6_0.local.as_u64[0] = iuvn6_0->ip6.dst_address.as_u64[0];
- key6_0.local.as_u64[1] = iuvn6_0->ip6.dst_address.as_u64[1];
- key6_0.remote.as_u64[0] = iuvn6_0->ip6.src_address.as_u64[0];
- key6_0.remote.as_u64[1] = iuvn6_0->ip6.src_address.as_u64[1];
- key6_0.vni = iuvn6_0->vxlan.vni_res;
-
- /* Processing for key6_0 */
- if (PREDICT_FALSE
- (memcmp (&key6_0, &last_key6, sizeof (last_key6)) != 0))
- {
- p0 = hash_get_mem (nngm->vxlan6_gpe_tunnel_by_key, &key6_0);
-
- if (p0 == 0)
- {
- error0 = VXLAN_GPE_ERROR_NO_SUCH_TUNNEL;
- goto trace00;
- }
- memcpy (&last_key6, &key6_0, sizeof (key6_0));
- tunnel_index0 = last_tunnel_index = p0[0];
- }
- else
- tunnel_index0 = last_tunnel_index;
+ next0 = di0.next_index;
+ error0 = di0.error;
+ if (error0 != 0)
+ {
+ goto trace00;
}
- t0 = pool_elt_at_index (nngm->tunnels, tunnel_index0);
-
+ t0 = pool_elt_at_index (nngm->tunnels, di0.tunnel_index);
sw_if_index0 = t0->sw_if_index;
len0 = vlib_buffer_length_in_chain (vm, b0);
@@ -637,7 +531,7 @@ vxlan_gpe_input (vlib_main_t * vm,
vlib_add_trace (vm, node, b0, sizeof (*tr));
tr->next_index = next0;
tr->error = error0;
- tr->tunnel_index = tunnel_index0;
+ tr->tunnel_index = di0.tunnel_index;
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, bi0, next0);
@@ -728,7 +622,6 @@ static char *vxlan_gpe_error_strings[] = {
#undef _
};
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vxlan4_gpe_input_node) = {
.name = "vxlan4-gpe-input",
/* Takes a vector of packets. */
@@ -748,9 +641,7 @@ VLIB_REGISTER_NODE (vxlan4_gpe_input_node) = {
.format_trace = format_vxlan_gpe_rx_trace,
// $$$$ .unformat_buffer = unformat_vxlan_gpe_header,
};
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vxlan6_gpe_input_node) = {
.name = "vxlan6-gpe-input",
/* Takes a vector of packets. */
@@ -770,7 +661,6 @@ VLIB_REGISTER_NODE (vxlan6_gpe_input_node) = {
.format_trace = format_vxlan_gpe_rx_trace,
// $$$$ .unformat_buffer = unformat_vxlan_gpe_header,
};
-/* *INDENT-ON* */
typedef enum
{
@@ -794,6 +684,9 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
matching a local VTEP address */
vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
+ vxlan4_gpe_tunnel_cache_t last4;
+ vxlan6_gpe_tunnel_cache_t last6;
+
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
next_index = node->cached_next_index;
@@ -804,9 +697,15 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
ip4_forward_next_trace (vm, node, frame, VLIB_TX);
if (is_ip4)
- vtep4_key_init (&last_vtep4);
+ {
+ vtep4_key_init (&last_vtep4);
+ clib_memset (&last4, 0xff, sizeof last4);
+ }
else
- vtep6_key_init (&last_vtep6);
+ {
+ vtep6_key_init (&last_vtep6);
+ clib_memset (&last6, 0xff, sizeof last6);
+ }
while (n_left_from > 0)
{
@@ -818,6 +717,9 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
ip4_header_t *ip40, *ip41;
ip6_header_t *ip60, *ip61;
udp_header_t *udp0, *udp1;
+ ip4_vxlan_gpe_header_t *iuvn4_0, *iuvn4_1;
+ ip6_vxlan_gpe_header_t *iuvn6_0, *iuvn6_1;
+ vxlan_gpe_decap_info_t di0, di1;
u32 bi0, ip_len0, udp_len0, flags0, next0;
u32 bi1, ip_len1, udp_len1, flags1, next1;
i32 len_diff0, len_diff1;
@@ -874,12 +776,20 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
goto exit0; /* not UDP packet */
if (is_ip4)
- udp0 = ip4_next_header (ip40);
+ {
+ udp0 = ip4_next_header (ip40);
+ iuvn4_0 = vlib_buffer_get_current (b0);
+ di0 = vxlan4_gpe_find_tunnel (ngm, &last4, iuvn4_0);
+ }
else
- udp0 = ip6_next_header (ip60);
+ {
+ udp0 = ip6_next_header (ip60);
+ iuvn6_0 = vlib_buffer_get_current (b0);
+ di0 = vxlan6_gpe_find_tunnel (ngm, &last6, iuvn6_0);
+ }
- if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE))
- goto exit0; /* not VXLAN packet */
+ if (PREDICT_FALSE (di0.tunnel_index == ~0))
+ goto exit0; /* unknown interface */
/* Validate DIP against VTEPs */
if (is_ip4)
@@ -957,12 +867,20 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
goto exit1; /* not UDP packet */
if (is_ip4)
- udp1 = ip4_next_header (ip41);
+ {
+ udp1 = ip4_next_header (ip41);
+ iuvn4_1 = vlib_buffer_get_current (b1);
+ di1 = vxlan4_gpe_find_tunnel (ngm, &last4, iuvn4_1);
+ }
else
- udp1 = ip6_next_header (ip61);
+ {
+ udp1 = ip6_next_header (ip61);
+ iuvn6_1 = vlib_buffer_get_current (b1);
+ di1 = vxlan6_gpe_find_tunnel (ngm, &last6, iuvn6_1);
+ }
- if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE))
- goto exit1; /* not VXLAN packet */
+ if (PREDICT_FALSE (di1.tunnel_index == ~0))
+ goto exit1; /* unknown interface */
/* Validate DIP against VTEPs */
if (is_ip4)
@@ -1046,6 +964,9 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
ip4_header_t *ip40;
ip6_header_t *ip60;
udp_header_t *udp0;
+ ip4_vxlan_gpe_header_t *iuvn4_0;
+ ip6_vxlan_gpe_header_t *iuvn6_0;
+ vxlan_gpe_decap_info_t di0;
u32 bi0, ip_len0, udp_len0, flags0, next0;
i32 len_diff0;
u8 error0, good_udp0, proto0;
@@ -1075,12 +996,20 @@ ip_vxlan_gpe_bypass_inline (vlib_main_t * vm,
goto exit; /* not UDP packet */
if (is_ip4)
- udp0 = ip4_next_header (ip40);
+ {
+ udp0 = ip4_next_header (ip40);
+ iuvn4_0 = vlib_buffer_get_current (b0);
+ di0 = vxlan4_gpe_find_tunnel (ngm, &last4, iuvn4_0);
+ }
else
- udp0 = ip6_next_header (ip60);
+ {
+ udp0 = ip6_next_header (ip60);
+ iuvn6_0 = vlib_buffer_get_current (b0);
+ di0 = vxlan6_gpe_find_tunnel (ngm, &last6, iuvn6_0);
+ }
- if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE))
- goto exit; /* not VXLAN packet */
+ if (PREDICT_FALSE (di0.tunnel_index == ~0))
+ goto exit; /* unknown interface */
/* Validate DIP against VTEPs */
@@ -1172,7 +1101,6 @@ VLIB_NODE_FN (ip4_vxlan_gpe_bypass_node) (vlib_main_t * vm,
return ip_vxlan_gpe_bypass_inline (vm, node, frame, /* is_ip4 */ 1);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip4_vxlan_gpe_bypass_node) = {
.name = "ip4-vxlan-gpe-bypass",
.vector_size = sizeof (u32),
@@ -1186,7 +1114,6 @@ VLIB_REGISTER_NODE (ip4_vxlan_gpe_bypass_node) = {
.format_buffer = format_ip4_header,
.format_trace = format_ip4_forward_next_trace,
};
-/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
/* Dummy init function to get us linked in. */
@@ -1206,7 +1133,6 @@ VLIB_NODE_FN (ip6_vxlan_gpe_bypass_node) (vlib_main_t * vm,
return ip_vxlan_gpe_bypass_inline (vm, node, frame, /* is_ip4 */ 0);
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_vxlan_gpe_bypass_node) = {
.name = "ip6-vxlan-gpe-bypass",
.vector_size = sizeof (u32),
@@ -1220,7 +1146,6 @@ VLIB_REGISTER_NODE (ip6_vxlan_gpe_bypass_node) = {
.format_buffer = format_ip6_header,
.format_trace = format_ip6_forward_next_trace,
};
-/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
/* Dummy init function to get us linked in. */
diff --git a/src/vnet/vxlan-gpe/encap.c b/src/vnet/vxlan-gpe/encap.c
index daa0381c4bb..a769861577d 100644
--- a/src/vnet/vxlan-gpe/encap.c
+++ b/src/vnet/vxlan-gpe/encap.c
@@ -88,13 +88,15 @@ format_vxlan_gpe_encap_trace (u8 * s, va_list * args)
*
*/
always_inline void
-vxlan_gpe_encap_one_inline (vxlan_gpe_main_t * ngm, vlib_buffer_t * b0,
- vxlan_gpe_tunnel_t * t0, u32 * next0, u8 is_v4)
+vxlan_gpe_encap_one_inline (vxlan_gpe_main_t *ngm, vlib_buffer_t *b0,
+ vxlan_gpe_tunnel_t *t0, u32 *next0,
+ ip_address_family_t af)
{
ASSERT (sizeof (ip4_vxlan_gpe_header_t) == 36);
ASSERT (sizeof (ip6_vxlan_gpe_header_t) == 56);
- ip_udp_encap_one (ngm->vlib_main, b0, t0->rewrite, t0->rewrite_size, is_v4);
+ ip_udp_encap_one (ngm->vlib_main, b0, t0->rewrite, t0->rewrite_size, af,
+ N_AF, UDP_ENCAP_FIXUP_NONE);
next0[0] = t0->encap_next_node;
}
@@ -112,16 +114,18 @@ vxlan_gpe_encap_one_inline (vxlan_gpe_main_t * ngm, vlib_buffer_t * b0,
*
*/
always_inline void
-vxlan_gpe_encap_two_inline (vxlan_gpe_main_t * ngm, vlib_buffer_t * b0,
- vlib_buffer_t * b1, vxlan_gpe_tunnel_t * t0,
- vxlan_gpe_tunnel_t * t1, u32 * next0,
- u32 * next1, u8 is_v4)
+vxlan_gpe_encap_two_inline (vxlan_gpe_main_t *ngm, vlib_buffer_t *b0,
+ vlib_buffer_t *b1, vxlan_gpe_tunnel_t *t0,
+ vxlan_gpe_tunnel_t *t1, u32 *next0, u32 *next1,
+ ip_address_family_t af)
{
ASSERT (sizeof (ip4_vxlan_gpe_header_t) == 36);
ASSERT (sizeof (ip6_vxlan_gpe_header_t) == 56);
- ip_udp_encap_one (ngm->vlib_main, b0, t0->rewrite, t0->rewrite_size, is_v4);
- ip_udp_encap_one (ngm->vlib_main, b1, t1->rewrite, t1->rewrite_size, is_v4);
+ ip_udp_encap_one (ngm->vlib_main, b0, t0->rewrite, t0->rewrite_size, af,
+ N_AF, UDP_ENCAP_FIXUP_NONE);
+ ip_udp_encap_one (ngm->vlib_main, b1, t1->rewrite, t1->rewrite_size, af,
+ N_AF, UDP_ENCAP_FIXUP_NONE);
next0[0] = next1[0] = t0->encap_next_node;
}
@@ -170,7 +174,7 @@ vxlan_gpe_encap (vlib_main_t * vm,
u32 sw_if_index0 = ~0, sw_if_index1 = ~0, len0, len1;
vnet_hw_interface_t *hi0, *hi1;
vxlan_gpe_tunnel_t *t0 = NULL, *t1 = NULL;
- u8 is_ip4_0 = 0, is_ip4_1 = 0;
+ ip_address_family_t af_0 = AF_IP4, af_1 = AF_IP4;
vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
@@ -201,7 +205,7 @@ vxlan_gpe_encap (vlib_main_t * vm,
n_left_to_next -= 2;
n_left_from -= 2;
- /* get the flag "is_ip4" */
+ /* get "af_0" */
if (sw_if_index0 != vnet_buffer (b[0])->sw_if_index[VLIB_TX])
{
sw_if_index0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
@@ -210,10 +214,10 @@ vxlan_gpe_encap (vlib_main_t * vm,
vnet_buffer (b[0])->sw_if_index
[VLIB_TX]);
t0 = pool_elt_at_index (ngm->tunnels, hi0->dev_instance);
- is_ip4_0 = (t0->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
+ af_0 = (t0->flags & VXLAN_GPE_TUNNEL_IS_IPV4 ? AF_IP4 : AF_IP6);
}
- /* get the flag "is_ip4" */
+ /* get "af_1" */
if (sw_if_index1 != vnet_buffer (b[1])->sw_if_index[VLIB_TX])
{
if (sw_if_index0 == vnet_buffer (b[1])->sw_if_index[VLIB_TX])
@@ -221,7 +225,7 @@ vxlan_gpe_encap (vlib_main_t * vm,
sw_if_index1 = sw_if_index0;
hi1 = hi0;
t1 = t0;
- is_ip4_1 = is_ip4_0;
+ af_1 = af_0;
}
else
{
@@ -231,19 +235,20 @@ vxlan_gpe_encap (vlib_main_t * vm,
vnet_buffer (b[1])->sw_if_index
[VLIB_TX]);
t1 = pool_elt_at_index (ngm->tunnels, hi1->dev_instance);
- is_ip4_1 = (t1->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
+ af_1 =
+ (t1->flags & VXLAN_GPE_TUNNEL_IS_IPV4 ? AF_IP4 : AF_IP6);
}
}
- if (PREDICT_TRUE (is_ip4_0 == is_ip4_1))
+ if (PREDICT_TRUE (af_0 == af_1))
{
vxlan_gpe_encap_two_inline (ngm, b[0], b[1], t0, t1, &next0,
- &next1, is_ip4_0);
+ &next1, af_0);
}
else
{
- vxlan_gpe_encap_one_inline (ngm, b[0], t0, &next0, is_ip4_0);
- vxlan_gpe_encap_one_inline (ngm, b[1], t1, &next1, is_ip4_1);
+ vxlan_gpe_encap_one_inline (ngm, b[0], t0, &next0, af_0);
+ vxlan_gpe_encap_one_inline (ngm, b[1], t1, &next1, af_1);
}
/* Reset to look up tunnel partner in the configured FIB */
@@ -325,7 +330,7 @@ vxlan_gpe_encap (vlib_main_t * vm,
n_left_from -= 1;
n_left_to_next -= 1;
- /* get the flag "is_ip4" */
+ /* get "af_0" */
if (sw_if_index0 != vnet_buffer (b[0])->sw_if_index[VLIB_TX])
{
sw_if_index0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
@@ -336,10 +341,10 @@ vxlan_gpe_encap (vlib_main_t * vm,
t0 = pool_elt_at_index (ngm->tunnels, hi0->dev_instance);
- is_ip4_0 = (t0->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
+ af_0 = (t0->flags & VXLAN_GPE_TUNNEL_IS_IPV4 ? AF_IP4 : AF_IP6);
}
- vxlan_gpe_encap_one_inline (ngm, b[0], t0, &next0, is_ip4_0);
+ vxlan_gpe_encap_one_inline (ngm, b[0], t0, &next0, af_0);
/* Reset to look up tunnel partner in the configured FIB */
vnet_buffer (b[0])->sw_if_index[VLIB_TX] = t0->encap_fib_index;
@@ -399,7 +404,6 @@ vxlan_gpe_encap (vlib_main_t * vm,
return from_frame->n_vectors;
}
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vxlan_gpe_encap_node) = {
.function = vxlan_gpe_encap,
.name = "vxlan-gpe-encap",
@@ -418,7 +422,6 @@ VLIB_REGISTER_NODE (vxlan_gpe_encap_node) = {
[VXLAN_GPE_ENCAP_NEXT_DROP] = "error-drop",
},
};
-/* *INDENT-ON* */
/*
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.api b/src/vnet/vxlan-gpe/vxlan_gpe.api
index 35d8c642192..3cbd7ab7f71 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe.api
+++ b/src/vnet/vxlan-gpe/vxlan_gpe.api
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-option version = "2.0.0";
+option version = "2.1.0";
import "vnet/interface_types.api";
import "vnet/ip/ip_types.api";
@@ -32,12 +32,48 @@ define vxlan_gpe_add_del_tunnel
bool is_add [default=true];
};
+/** \brief Create or delete a VXLAN-GPE tunnel
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param local - Source IP address
+ @param remote - Destination IP address, can be multicast
+ @param local_port - Source UDP port. It is not included in sent packets. Used only for port registration
+ @param remote_port - Destination UDP port
+ @param mcast_sw_if_index - Interface for multicast destination
+ @param encap_vrf_id - Encap route table FIB index
+ @param decap_vrf_id - Decap route table FIB index
+ @param protocol - Encapsulated protocol
+ @param vni - The VXLAN Network Identifier, uint24
+ @param is_add - Use 1 to create the tunnel, 0 to remove it
+*/
+define vxlan_gpe_add_del_tunnel_v2
+{
+ u32 client_index;
+ u32 context;
+ vl_api_address_t local;
+ vl_api_address_t remote;
+ u16 local_port;
+ u16 remote_port;
+ vl_api_interface_index_t mcast_sw_if_index;
+ u32 encap_vrf_id;
+ u32 decap_vrf_id;
+ vl_api_ip_proto_t protocol;
+ u32 vni;
+ bool is_add [default=true];
+};
+
define vxlan_gpe_add_del_tunnel_reply
{
u32 context;
i32 retval;
vl_api_interface_index_t sw_if_index;
};
+define vxlan_gpe_add_del_tunnel_v2_reply
+{
+ u32 context;
+ i32 retval;
+ vl_api_interface_index_t sw_if_index;
+};
define vxlan_gpe_tunnel_dump
{
@@ -45,6 +81,12 @@ define vxlan_gpe_tunnel_dump
u32 context;
vl_api_interface_index_t sw_if_index;
};
+define vxlan_gpe_tunnel_v2_dump
+{
+ u32 client_index;
+ u32 context;
+ vl_api_interface_index_t sw_if_index;
+};
define vxlan_gpe_tunnel_details
{
@@ -59,6 +101,21 @@ define vxlan_gpe_tunnel_details
u32 decap_vrf_id;
bool is_ipv6;
};
+define vxlan_gpe_tunnel_v2_details
+{
+ u32 context;
+ vl_api_interface_index_t sw_if_index;
+ vl_api_address_t local;
+ vl_api_address_t remote;
+ u16 local_port;
+ u16 remote_port;
+ u32 vni;
+ vl_api_ip_proto_t protocol;
+ vl_api_interface_index_t mcast_sw_if_index;
+ u32 encap_vrf_id;
+ u32 decap_vrf_id;
+ bool is_ipv6;
+};
/** \brief Interface set vxlan-gpe-bypass request
@param client_index - opaque cookie to identify the sender
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.c b/src/vnet/vxlan-gpe/vxlan_gpe.c
index e5ca4ec769e..5a5262ea9db 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe.c
+++ b/src/vnet/vxlan-gpe/vxlan_gpe.c
@@ -87,11 +87,12 @@ format_vxlan_gpe_tunnel (u8 * s, va_list * args)
vxlan_gpe_tunnel_t *t = va_arg (*args, vxlan_gpe_tunnel_t *);
vxlan_gpe_main_t *ngm = &vxlan_gpe_main;
- s = format (s, "[%d] lcl %U rmt %U vni %d fib-idx %d sw-if-idx %d ",
- t - ngm->tunnels,
- format_ip46_address, &t->local, IP46_TYPE_ANY,
- format_ip46_address, &t->remote, IP46_TYPE_ANY,
- t->vni, t->encap_fib_index, t->sw_if_index);
+ s = format (s,
+ "[%d] lcl %U rmt %U lcl_port %d rmt_port %d vni %d "
+ "fib-idx %d sw-if-idx %d ",
+ t - ngm->tunnels, format_ip46_address, &t->local, IP46_TYPE_ANY,
+ format_ip46_address, &t->remote, IP46_TYPE_ANY, t->local_port,
+ t->remote_port, t->vni, t->encap_fib_index, t->sw_if_index);
#if 0
/* next_dpo not yet used by vxlan-gpe-encap node */
@@ -143,14 +144,12 @@ vxlan_gpe_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index,
return 0;
}
-/* *INDENT-OFF* */
VNET_DEVICE_CLASS (vxlan_gpe_device_class,static) = {
.name = "VXLAN_GPE",
.format_device_name = format_vxlan_gpe_name,
.format_tx_trace = format_vxlan_gpe_encap_trace,
.admin_up_down_function = vxlan_gpe_interface_admin_up_down,
};
-/* *INDENT-ON* */
/**
@@ -170,13 +169,11 @@ format_vxlan_gpe_header_with_length (u8 * s, va_list * args)
return s;
}
-/* *INDENT-OFF* */
VNET_HW_INTERFACE_CLASS (vxlan_gpe_hw_class) = {
.name = "VXLAN_GPE",
.format_header = format_vxlan_gpe_header_with_length,
.build_rewrite = default_build_rewrite,
};
-/* *INDENT-ON* */
static void
vxlan_gpe_tunnel_restack_dpo (vxlan_gpe_tunnel_t * t)
@@ -248,12 +245,14 @@ const static fib_node_vft_t vxlan_gpe_vft = {
.fnv_back_walk = vxlan_gpe_tunnel_back_walk,
};
-#define foreach_gpe_copy_field \
-_(vni) \
-_(protocol) \
-_(mcast_sw_if_index) \
-_(encap_fib_index) \
-_(decap_fib_index)
+#define foreach_gpe_copy_field \
+ _ (vni) \
+ _ (protocol) \
+ _ (mcast_sw_if_index) \
+ _ (encap_fib_index) \
+ _ (decap_fib_index) \
+ _ (local_port) \
+ _ (remote_port)
#define foreach_copy_ipv4 { \
_(local.ip4.as_u32) \
@@ -304,8 +303,8 @@ vxlan4_gpe_rewrite (vxlan_gpe_tunnel_t * t, u32 extension_size,
ip0->checksum = ip4_header_checksum (ip0);
/* UDP header, randomize src port on something, maybe? */
- h0->udp.src_port = clib_host_to_net_u16 (4790);
- h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
+ h0->udp.src_port = clib_host_to_net_u16 (t->local_port);
+ h0->udp.dst_port = clib_host_to_net_u16 (t->remote_port);
/* VXLAN header. Are we having fun yet? */
h0->vxlan.flags = VXLAN_GPE_FLAGS_I | VXLAN_GPE_FLAGS_P;
@@ -363,8 +362,8 @@ vxlan6_gpe_rewrite (vxlan_gpe_tunnel_t * t, u32 extension_size,
ip0->dst_address.as_u64[1] = t->remote.ip6.as_u64[1];
/* UDP header, randomize src port on something, maybe? */
- h0->udp.src_port = clib_host_to_net_u16 (4790);
- h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
+ h0->udp.src_port = clib_host_to_net_u16 (t->local_port);
+ h0->udp.dst_port = clib_host_to_net_u16 (t->remote_port);
/* VXLAN header. Are we having fun yet? */
h0->vxlan.flags = VXLAN_GPE_FLAGS_I | VXLAN_GPE_FLAGS_P;
@@ -385,7 +384,6 @@ vxlan6_gpe_rewrite (vxlan_gpe_tunnel_t * t, u32 extension_size,
return (0);
}
-/* *INDENT-OFF* */
typedef CLIB_PACKED(union {
struct {
fib_node_index_t mfib_entry_index;
@@ -393,7 +391,6 @@ typedef CLIB_PACKED(union {
};
u64 as_u64;
}) mcast_shared_t;
-/* *INDENT-ON* */
static inline mcast_shared_t
mcast_shared_get (ip46_address_t * ip)
@@ -453,12 +450,19 @@ int vnet_vxlan_gpe_add_del_tunnel
vxlan6_gpe_tunnel_key_t key6, *key6_copy;
u32 is_ip6 = a->is_ip6;
+ /* Set udp-ports */
+ if (a->local_port == 0)
+ a->local_port = is_ip6 ? UDP_DST_PORT_VXLAN6_GPE : UDP_DST_PORT_VXLAN_GPE;
+
+ if (a->remote_port == 0)
+ a->remote_port = is_ip6 ? UDP_DST_PORT_VXLAN6_GPE : UDP_DST_PORT_VXLAN_GPE;
+
if (!is_ip6)
{
key4.local = a->local.ip4.as_u32;
key4.remote = a->remote.ip4.as_u32;
key4.vni = clib_host_to_net_u32 (a->vni << 8);
- key4.pad = 0;
+ key4.port = (u32) clib_host_to_net_u16 (a->local_port);
p = hash_get_mem (ngm->vxlan4_gpe_tunnel_by_key, &key4);
}
@@ -469,6 +473,7 @@ int vnet_vxlan_gpe_add_del_tunnel
key6.remote.as_u64[0] = a->remote.ip6.as_u64[0];
key6.remote.as_u64[1] = a->remote.ip6.as_u64[1];
key6.vni = clib_host_to_net_u32 (a->vni << 8);
+ key6.port = (u32) clib_host_to_net_u16 (a->local_port);
p = hash_get_mem (ngm->vxlan6_gpe_tunnel_by_key, &key6);
}
@@ -485,7 +490,6 @@ int vnet_vxlan_gpe_add_del_tunnel
clib_memset (t, 0, sizeof (*t));
/* copy from arg structure */
-/* *INDENT-OFF* */
#define _(x) t->x = a->x;
foreach_gpe_copy_field;
if (!a->is_ip6)
@@ -493,7 +497,6 @@ int vnet_vxlan_gpe_add_del_tunnel
else
foreach_copy_ipv6
#undef _
-/* *INDENT-ON* */
if (!a->is_ip6)
t->flags |= VXLAN_GPE_TUNNEL_IS_IPV4;
@@ -533,7 +536,7 @@ int vnet_vxlan_gpe_add_del_tunnel
vnet_interface_main_t *im = &vnm->interface_main;
hw_if_index = ngm->free_vxlan_gpe_tunnel_hw_if_indices
[vec_len (ngm->free_vxlan_gpe_tunnel_hw_if_indices) - 1];
- _vec_len (ngm->free_vxlan_gpe_tunnel_hw_if_indices) -= 1;
+ vec_dec_len (ngm->free_vxlan_gpe_tunnel_hw_if_indices, 1);
hi = vnet_get_hw_interface (vnm, hw_if_index);
hi->dev_instance = t - ngm->tunnels;
@@ -583,7 +586,8 @@ int vnet_vxlan_gpe_add_del_tunnel
fib_prefix_t tun_remote_pfx;
vnet_flood_class_t flood_class = VNET_FLOOD_CLASS_TUNNEL_NORMAL;
- fib_prefix_from_ip46_addr (&t->remote, &tun_remote_pfx);
+ fib_protocol_t fp = fib_ip_proto (is_ip6);
+ fib_prefix_from_ip46_addr (fp, &t->remote, &tun_remote_pfx);
if (!ip46_address_is_multicast (&t->remote))
{
/* Unicast tunnel -
@@ -607,8 +611,6 @@ int vnet_vxlan_gpe_add_del_tunnel
* with different VNIs, create the output fib adjacency only if
* it does not already exist
*/
- fib_protocol_t fp = fib_ip_proto (is_ip6);
-
if (vtep_addr_ref (&ngm->vtep_table,
t->encap_fib_index, &t->remote) == 1)
{
@@ -634,17 +636,16 @@ int vnet_vxlan_gpe_add_del_tunnel
* - the forwarding interface is for-us
* - the accepting interface is that from the API
*/
- mfib_table_entry_path_update (t->encap_fib_index,
- &mpfx,
- MFIB_SOURCE_VXLAN_GPE, &path);
+ mfib_table_entry_path_update (t->encap_fib_index, &mpfx,
+ MFIB_SOURCE_VXLAN_GPE,
+ MFIB_ENTRY_FLAG_NONE, &path);
path.frp_sw_if_index = a->mcast_sw_if_index;
path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE;
path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
- mfei = mfib_table_entry_path_update (t->encap_fib_index,
- &mpfx,
- MFIB_SOURCE_VXLAN_GPE,
- &path);
+ mfei = mfib_table_entry_path_update (
+ t->encap_fib_index, &mpfx, MFIB_SOURCE_VXLAN_GPE,
+ MFIB_ENTRY_FLAG_NONE, &path);
/*
* Create the mcast adjacency to send traffic to the group
@@ -719,12 +720,12 @@ int vnet_vxlan_gpe_add_del_tunnel
if (a->is_add)
{
/* register udp ports */
- if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_VXLAN_GPE, 1))
- udp_register_dst_port (ngm->vlib_main, UDP_DST_PORT_VXLAN_GPE,
- vxlan4_gpe_input_node.index, 1 /* is_ip4 */ );
- if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_VXLAN6_GPE, 0))
- udp_register_dst_port (ngm->vlib_main, UDP_DST_PORT_VXLAN6_GPE,
- vxlan6_gpe_input_node.index, 0 /* is_ip4 */ );
+ if (!is_ip6 && !udp_is_valid_dst_port (a->local_port, 1))
+ udp_register_dst_port (ngm->vlib_main, a->local_port,
+ vxlan4_gpe_input_node.index, 1 /* is_ip4 */);
+ if (is_ip6 && !udp_is_valid_dst_port (a->remote_port, 0))
+ udp_register_dst_port (ngm->vlib_main, a->remote_port,
+ vxlan6_gpe_input_node.index, 0 /* is_ip4 */);
}
return 0;
@@ -749,6 +750,8 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm,
u8 protocol = VXLAN_GPE_PROTOCOL_IP4;
u32 vni;
u8 vni_set = 0;
+ u32 local_port = 0;
+ u32 remote_port = 0;
int rv;
u32 tmp;
vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
@@ -833,6 +836,10 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm,
}
else if (unformat (line_input, "vni %d", &vni))
vni_set = 1;
+ else if (unformat (line_input, "local_port %d", &local_port))
+ ;
+ else if (unformat (line_input, "remote_port %d", &remote_port))
+ ;
else if (unformat (line_input, "next-ip4"))
protocol = VXLAN_GPE_PROTOCOL_IP4;
else if (unformat (line_input, "next-ip6"))
@@ -903,7 +910,6 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm,
a->is_add = is_add;
a->is_ip6 = ipv6_set;
-/* *INDENT-OFF* */
#define _(x) a->x = x;
foreach_gpe_copy_field;
if (ipv4_set)
@@ -911,7 +917,6 @@ vxlan_gpe_add_del_tunnel_command_fn (vlib_main_t * vm,
else
foreach_copy_ipv6
#undef _
-/* *INDENT-ON* */
rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
@@ -964,7 +969,6 @@ done:
* Example of how to delete a VXLAN-GPE Tunnel:
* @cliexcmd{create vxlan-gpe tunnel local 10.0.3.1 remote 10.0.3.3 vni 13 del}
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (create_vxlan_gpe_tunnel_command, static) = {
.path = "create vxlan-gpe tunnel",
.short_help =
@@ -974,7 +978,6 @@ VLIB_CLI_COMMAND (create_vxlan_gpe_tunnel_command, static) = {
" [encap-vrf-id <nn>] [decap-vrf-id <nn>] [del]\n",
.function = vxlan_gpe_add_del_tunnel_command_fn,
};
-/* *INDENT-ON* */
/**
* @brief CLI function for showing VXLAN GPE tunnels
@@ -997,12 +1000,10 @@ show_vxlan_gpe_tunnel_command_fn (vlib_main_t * vm,
if (pool_elts (ngm->tunnels) == 0)
vlib_cli_output (vm, "No vxlan-gpe tunnels configured.");
- /* *INDENT-OFF* */
pool_foreach (t, ngm->tunnels)
{
vlib_cli_output (vm, "%U", format_vxlan_gpe_tunnel, t);
}
- /* *INDENT-ON* */
return 0;
}
@@ -1016,12 +1017,10 @@ show_vxlan_gpe_tunnel_command_fn (vlib_main_t * vm,
* [0] local 10.0.3.1 remote 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
* @cliexend
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_vxlan_gpe_tunnel_command, static) = {
.path = "show vxlan-gpe",
.function = show_vxlan_gpe_tunnel_command_fn,
};
-/* *INDENT-ON* */
void
vnet_int_vxlan_gpe_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable)
@@ -1087,11 +1086,12 @@ set_ip4_vxlan_gpe_bypass (vlib_main_t * vm,
}
/*?
- * This command adds the 'ip4-vxlan-gpe-bypass' graph node for a given interface.
- * By adding the IPv4 vxlan-gpe-bypass graph node to an interface, the node checks
- * for and validate input vxlan_gpe packet and bypass ip4-lookup, ip4-local,
- * ip4-udp-lookup nodes to speedup vxlan_gpe packet forwarding. This node will
- * cause extra overhead to for non-vxlan_gpe packets which is kept at a minimum.
+ * This command adds the 'ip4-vxlan-gpe-bypass' graph node for a given
+ * interface. By adding the IPv4 vxlan-gpe-bypass graph node to an interface,
+ * the node checks for and validate input vxlan_gpe packet and bypass
+ * ip4-lookup, ip4-local, ip4-udp-lookup nodes to speedup vxlan_gpe packet
+ * forwarding. This node will cause extra overhead to for non-vxlan_gpe
+ * packets which is kept at a minimum.
*
* @cliexpar
* @parblock
@@ -1108,10 +1108,10 @@ set_ip4_vxlan_gpe_bypass (vlib_main_t * vm,
*
* Example of graph node after ip4-vxlan-gpe-bypass is enabled:
* @cliexstart{show vlib graph ip4-vxlan-gpe-bypass}
- * Name Next Previous
- * ip4-vxlan-gpe-bypass error-drop [0] ip4-input
- * vxlan4-gpe-input [1] ip4-input-no-checksum
- * ip4-lookup [2]
+ * Name Next Previous
+ * ip4-vxlan-gpe-bypass error-drop [0] ip4-input
+ * vxlan4-gpe-input [1] ip4-input-no-checksum
+ * ip4-lookup [2]
* @cliexend
*
* Example of how to display the feature enabled on an interface:
@@ -1128,13 +1128,11 @@ set_ip4_vxlan_gpe_bypass (vlib_main_t * vm,
* @cliexcmd{set interface ip vxlan-gpe-bypass GigabitEthernet2/0/0 del}
* @endparblock
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_interface_ip_vxlan_gpe_bypass_command, static) = {
.path = "set interface ip vxlan-gpe-bypass",
.function = set_ip4_vxlan_gpe_bypass,
.short_help = "set interface ip vxlan-gpe-bypass <interface> [del]",
};
-/* *INDENT-ON* */
static clib_error_t *
set_ip6_vxlan_gpe_bypass (vlib_main_t * vm,
@@ -1144,11 +1142,12 @@ set_ip6_vxlan_gpe_bypass (vlib_main_t * vm,
}
/*?
- * This command adds the 'ip6-vxlan-gpe-bypass' graph node for a given interface.
- * By adding the IPv6 vxlan-gpe-bypass graph node to an interface, the node checks
- * for and validate input vxlan_gpe packet and bypass ip6-lookup, ip6-local,
- * ip6-udp-lookup nodes to speedup vxlan_gpe packet forwarding. This node will
- * cause extra overhead to for non-vxlan_gpe packets which is kept at a minimum.
+ * This command adds the 'ip6-vxlan-gpe-bypass' graph node for a given
+ * interface. By adding the IPv6 vxlan-gpe-bypass graph node to an interface,
+ * the node checks for and validate input vxlan_gpe packet and bypass
+ * ip6-lookup, ip6-local, ip6-udp-lookup nodes to speedup vxlan_gpe packet
+ * forwarding. This node will cause extra overhead to for non-vxlan_gpe packets
+ * which is kept at a minimum.
*
* @cliexpar
* @parblock
@@ -1165,10 +1164,10 @@ set_ip6_vxlan_gpe_bypass (vlib_main_t * vm,
*
* Example of graph node after ip6-vxlan-gpe-bypass is enabled:
* @cliexstart{show vlib graph ip6-vxlan-gpe-bypass}
- * Name Next Previous
- * ip6-vxlan-gpe-bypass error-drop [0] ip6-input
- * vxlan6-gpe-input [1] ip4-input-no-checksum
- * ip6-lookup [2]
+ * Name Next Previous
+ * ip6-vxlan-gpe-bypass error-drop [0] ip6-input
+ * vxlan6-gpe-input [1] ip4-input-no-checksum
+ * ip6-lookup [2]
* @cliexend
*
* Example of how to display the feature enabled on an interface:
@@ -1185,15 +1184,12 @@ set_ip6_vxlan_gpe_bypass (vlib_main_t * vm,
* @cliexcmd{set interface ip6 vxlan-gpe-bypass GigabitEthernet2/0/0 del}
* @endparblock
?*/
-/* *INDENT-OFF* */
VLIB_CLI_COMMAND (set_interface_ip6_vxlan_gpe_bypass_command, static) = {
.path = "set interface ip6 vxlan-gpe-bypass",
.function = set_ip6_vxlan_gpe_bypass,
.short_help = "set interface ip6 vxlan-gpe-bypass <interface> [del]",
};
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
VNET_FEATURE_INIT (ip4_vxlan_gpe_bypass, static) =
{
.arc_name = "ip4-unicast",
@@ -1207,7 +1203,6 @@ VNET_FEATURE_INIT (ip6_vxlan_gpe_bypass, static) =
.node_name = "ip6-vxlan-gpe-bypass",
.runs_before = VNET_FEATURES ("ip6-lookup"),
};
-/* *INDENT-ON* */
/**
* @brief Feature init function for VXLAN GPE
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.h b/src/vnet/vxlan-gpe/vxlan_gpe.h
index 0f8250a1788..aabaafeee6f 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe.h
+++ b/src/vnet/vxlan-gpe/vxlan_gpe.h
@@ -40,7 +40,6 @@
* @brief VXLAN GPE header struct
*
*/
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
/** 20 bytes */
ip4_header_t ip4;
@@ -49,9 +48,7 @@ typedef CLIB_PACKED (struct {
/** 8 bytes */
vxlan_gpe_header_t vxlan;
}) ip4_vxlan_gpe_header_t;
-/* *INDENT-ON* */
-/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
/** 40 bytes */
ip6_header_t ip6;
@@ -60,15 +57,13 @@ typedef CLIB_PACKED (struct {
/** 8 bytes */
vxlan_gpe_header_t vxlan;
}) ip6_vxlan_gpe_header_t;
-/* *INDENT-ON* */
/**
* @brief Key struct for IPv4 VXLAN GPE tunnel.
- * Key fields: local remote, vni
+ * Key fields: local remote, vni, udp-port
* all fields in NET byte order
* VNI shifted 8 bits
*/
-/* *INDENT-OFF* */
typedef CLIB_PACKED(struct {
union {
struct {
@@ -76,26 +71,35 @@ typedef CLIB_PACKED(struct {
u32 remote;
u32 vni;
- u32 pad;
+ u32 port;
};
u64 as_u64[2];
};
}) vxlan4_gpe_tunnel_key_t;
-/* *INDENT-ON* */
/**
* @brief Key struct for IPv6 VXLAN GPE tunnel.
- * Key fields: local remote, vni
+ * Key fields: local remote, vni, udp-port
* all fields in NET byte order
* VNI shifted 8 bits
*/
-/* *INDENT-OFF* */
typedef CLIB_PACKED(struct {
ip6_address_t local;
ip6_address_t remote;
u32 vni;
+ u32 port;
}) vxlan6_gpe_tunnel_key_t;
-/* *INDENT-ON* */
+
+typedef union
+{
+ struct
+ {
+ u32 tunnel_index;
+ u16 next_index;
+ u8 error;
+ };
+ u64 as_u64;
+} vxlan_gpe_decap_info_t;
/**
* @brief Struct for VXLAN GPE tunnel
@@ -117,6 +121,10 @@ typedef struct
ip46_address_t local;
/** tunnel remote address */
ip46_address_t remote;
+ /** local udp-port **/
+ u16 local_port;
+ /** remote udp-port **/
+ u16 remote_port;
/* mcast packet output intfc index (used only if dst is mcast) */
u32 mcast_sw_if_index;
@@ -221,9 +229,7 @@ typedef struct
vnet_main_t *vnet_main;
/* cache for last 8 vxlan_gpe tunnel */
-#ifdef CLIB_HAVE_VEC512
vtep4_cache_t vtep4_u512;
-#endif
/** List of next nodes for the decap indexed on protocol */
uword decap_next_node_list[VXLAN_GPE_PROTOCOL_MAX];
@@ -248,6 +254,8 @@ typedef struct
u32 encap_fib_index;
u32 decap_fib_index;
u32 vni;
+ u16 local_port;
+ u16 remote_port;
} vnet_vxlan_gpe_add_del_tunnel_args_t;
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe_api.c b/src/vnet/vxlan-gpe/vxlan_gpe_api.c
index 243ddfb7fe1..cc74e1f58d4 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe_api.c
+++ b/src/vnet/vxlan-gpe/vxlan_gpe_api.c
@@ -114,12 +114,77 @@ static void
rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
out:
- /* *INDENT-OFF* */
REPLY_MACRO2(VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_REPLY,
({
rmp->sw_if_index = ntohl (sw_if_index);
}));
- /* *INDENT-ON* */
+}
+
+static void
+vl_api_vxlan_gpe_add_del_tunnel_v2_t_handler (
+ vl_api_vxlan_gpe_add_del_tunnel_v2_t *mp)
+{
+ vl_api_vxlan_gpe_add_del_tunnel_v2_reply_t *rmp;
+ int rv = 0;
+ vnet_vxlan_gpe_add_del_tunnel_args_t _a, *a = &_a;
+ u32 encap_fib_index, decap_fib_index;
+ u8 protocol;
+ uword *p;
+ ip4_main_t *im = &ip4_main;
+ u32 sw_if_index = ~0;
+
+ p = hash_get (im->fib_index_by_table_id, ntohl (mp->encap_vrf_id));
+ if (!p)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto out;
+ }
+ encap_fib_index = p[0];
+
+ protocol = mp->protocol;
+
+ /* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
+ if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT)
+ {
+ p = hash_get (im->fib_index_by_table_id, ntohl (mp->decap_vrf_id));
+ if (!p)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_INNER_FIB;
+ goto out;
+ }
+ decap_fib_index = p[0];
+ }
+ else
+ {
+ decap_fib_index = ntohl (mp->decap_vrf_id);
+ }
+
+ clib_memset (a, 0, sizeof (*a));
+
+ a->is_add = mp->is_add;
+ ip_address_decode (&mp->local, &a->local);
+ ip_address_decode (&mp->remote, &a->remote);
+
+ /* Check src & dst are different */
+ if (ip46_address_is_equal (&a->local, &a->remote))
+ {
+ rv = VNET_API_ERROR_SAME_SRC_DST;
+ goto out;
+ }
+
+ a->local_port = ntohs (mp->local_port);
+ a->remote_port = ntohs (mp->remote_port);
+ a->is_ip6 = !ip46_address_is_ip4 (&a->local);
+ a->mcast_sw_if_index = ntohl (mp->mcast_sw_if_index);
+ a->encap_fib_index = encap_fib_index;
+ a->decap_fib_index = decap_fib_index;
+ a->protocol = protocol;
+ a->vni = ntohl (mp->vni);
+ rv = vnet_vxlan_gpe_add_del_tunnel (a, &sw_if_index);
+
+out:
+ REPLY_MACRO2 (VL_API_VXLAN_GPE_ADD_DEL_TUNNEL_V2_REPLY,
+ ({ rmp->sw_if_index = ntohl (sw_if_index); }));
}
static void send_vxlan_gpe_tunnel_details
@@ -175,12 +240,10 @@ static void vl_api_vxlan_gpe_tunnel_dump_t_handler
if (~0 == sw_if_index)
{
- /* *INDENT-OFF* */
pool_foreach (t, vgm->tunnels)
- {
- send_vxlan_gpe_tunnel_details(t, reg, mp->context);
- }
- /* *INDENT-ON* */
+ {
+ send_vxlan_gpe_tunnel_details (t, reg, mp->context);
+ }
}
else
{
@@ -194,6 +257,80 @@ static void vl_api_vxlan_gpe_tunnel_dump_t_handler
}
}
+static void
+send_vxlan_gpe_tunnel_v2_details (vxlan_gpe_tunnel_t *t,
+ vl_api_registration_t *reg, u32 context)
+{
+ vl_api_vxlan_gpe_tunnel_v2_details_t *rmp;
+ ip4_main_t *im4 = &ip4_main;
+ ip6_main_t *im6 = &ip6_main;
+ u8 is_ipv6 = !(t->flags & VXLAN_GPE_TUNNEL_IS_IPV4);
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ clib_memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id =
+ ntohs (REPLY_MSG_ID_BASE + VL_API_VXLAN_GPE_TUNNEL_V2_DETAILS);
+
+ ip_address_encode (&t->local, is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
+ &rmp->local);
+ ip_address_encode (&t->remote, is_ipv6 ? IP46_TYPE_IP6 : IP46_TYPE_IP4,
+ &rmp->remote);
+ rmp->local_port = htons (t->local_port);
+ rmp->remote_port = htons (t->remote_port);
+
+ if (ip46_address_is_ip4 (&t->local))
+ {
+ rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
+ rmp->decap_vrf_id = htonl (im4->fibs[t->decap_fib_index].ft_table_id);
+ }
+ else
+ {
+ rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
+ rmp->decap_vrf_id = htonl (im6->fibs[t->decap_fib_index].ft_table_id);
+ }
+ rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
+ rmp->vni = htonl (t->vni);
+ rmp->protocol = t->protocol;
+ rmp->sw_if_index = htonl (t->sw_if_index);
+ rmp->context = context;
+
+ vl_api_send_msg (reg, (u8 *) rmp);
+}
+
+static void
+vl_api_vxlan_gpe_tunnel_v2_dump_t_handler (
+ vl_api_vxlan_gpe_tunnel_v2_dump_t *mp)
+{
+ vl_api_registration_t *reg;
+ vxlan_gpe_main_t *vgm = &vxlan_gpe_main;
+ vxlan_gpe_tunnel_t *t;
+ u32 sw_if_index;
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;
+
+ sw_if_index = ntohl (mp->sw_if_index);
+
+ if (~0 == sw_if_index)
+ {
+ pool_foreach (t, vgm->tunnels)
+ {
+ send_vxlan_gpe_tunnel_v2_details (t, reg, mp->context);
+ }
+ }
+ else
+ {
+ if ((sw_if_index >= vec_len (vgm->tunnel_index_by_sw_if_index)) ||
+ (~0 == vgm->tunnel_index_by_sw_if_index[sw_if_index]))
+ {
+ return;
+ }
+ t = &vgm->tunnels[vgm->tunnel_index_by_sw_if_index[sw_if_index]];
+ send_vxlan_gpe_tunnel_v2_details (t, reg, mp->context);
+ }
+}
+
#include <vxlan-gpe/vxlan_gpe.api.c>
static clib_error_t *
@@ -201,8 +338,8 @@ vxlan_gpe_api_hookup (vlib_main_t * vm)
{
api_main_t *am = vlibapi_get_main ();
- am->api_trace_cfg[VL_API_VXLAN_GPE_ADD_DEL_TUNNEL].size +=
- 17 * sizeof (u32);
+ vl_api_increase_msg_trace_size (am, VL_API_VXLAN_GPE_ADD_DEL_TUNNEL,
+ 17 * sizeof (u32));
/*
* Set up the (msg_name, crc, message-id) table