aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Glazychev <artem.glazychev@xored.com>2021-05-28 19:09:14 +0700
committerDamjan Marion <dmarion@me.com>2021-10-08 11:38:56 +0000
commitea96292985760b7fc3af54669e3eab35e7561a10 (patch)
tree05a0317fb9cb7460f86056e16d256e448147eeaa
parent3f59c639609be9768f592111e5f8a8a2c23db3ac (diff)
vxlan-gpe: add udp-port configuration support
similar behavior as here: 839dcc0fb7313638d9b8f52a9db81350dddfe461 Type: improvement Signed-off-by: Artem Glazychev <artem.glazychev@xored.com> Change-Id: I1b0a8f8f3dab48839e27df7065cf5f786cf0b5e9
-rw-r--r--src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c5
-rw-r--r--src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c4
-rw-r--r--src/vnet/vxlan-gpe/decap.c435
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.api59
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.c61
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe.h24
-rw-r--r--src/vnet/vxlan-gpe/vxlan_gpe_api.c147
-rw-r--r--test/test_vxlan_gpe.py227
-rw-r--r--test/vpp_papi_provider.py37
-rw-r--r--test/vpp_vxlan_gpe_tunnel.py83
10 files changed, 687 insertions, 395 deletions
diff --git a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c
index 9f6d181f0b1..d61832d975a 100644
--- a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c
+++ b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c
@@ -27,6 +27,7 @@
#include <vlibmemory/api.h>
#include <vnet/format_fns.h>
#include <vnet/ip/ip_types_api.h>
+#include <vnet/udp/udp_local.h>
/* define message IDs */
#include <ioam/lib-vxlan-gpe/ioam_vxlan_gpe.api_enum.h>
@@ -92,7 +93,7 @@ static void vl_api_vxlan_gpe_ioam_vni_enable_t_handler
clib_memcpy (&key4.remote, &mp->remote.un.ip4, sizeof (key4.remote));
vni = clib_net_to_host_u32 (mp->vni);
key4.vni = clib_host_to_net_u32 (vni << 8);
- key4.pad = 0;
+ key4.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
}
@@ -141,7 +142,7 @@ static void vl_api_vxlan_gpe_ioam_vni_disable_t_handler
clib_memcpy (&key4.remote, &mp->remote, sizeof (key4.remote));
vni = clib_net_to_host_u32 (mp->vni);
key4.vni = clib_host_to_net_u32 (vni << 8);
- key4.pad = 0;
+ key4.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
}
diff --git a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c
index 108b0c0765b..59798dc7494 100644
--- a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c
+++ b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_ioam.c
@@ -19,6 +19,7 @@
#include <vnet/dpo/load_balance.h>
#include <vnet/fib/ip4_fib.h>
#include <vnet/fib/fib_entry.h>
+#include <vnet/udp/udp_local.h>
vxlan_gpe_ioam_main_t vxlan_gpe_ioam_main;
@@ -478,7 +479,7 @@ vxlan_gpe_set_ioam_rewrite_command_fn (vlib_main_t *
key4.local = local.ip4.as_u32;
key4.remote = remote.ip4.as_u32;
key4.vni = clib_host_to_net_u32 (vni << 8);
- key4.pad = 0;
+ key4.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
}
else
@@ -488,6 +489,7 @@ vxlan_gpe_set_ioam_rewrite_command_fn (vlib_main_t *
key6.remote.as_u64[0] = remote.ip6.as_u64[0];
key6.remote.as_u64[1] = remote.ip6.as_u64[1];
key6.vni = clib_host_to_net_u32 (vni << 8);
+ key6.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN6_GPE);
p = hash_get_mem (gm->vxlan6_gpe_tunnel_by_key, &key6);
}
diff --git a/src/vnet/vxlan-gpe/decap.c b/src/vnet/vxlan-gpe/decap.c
index 035e8a3fd6a..62513614389 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);
@@ -794,6 +688,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 +701,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 +721,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 +780,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 +871,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 +968,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 +1000,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 */
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 6fd0561099b..17ffcadcd9f 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 */
@@ -248,12 +249,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 +307,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 +366,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;
@@ -453,12 +456,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 +479,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);
}
@@ -719,12 +730,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 +760,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 +846,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"))
diff --git a/src/vnet/vxlan-gpe/vxlan_gpe.h b/src/vnet/vxlan-gpe/vxlan_gpe.h
index 0f8250a1788..5d21ee66d67 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe.h
+++ b/src/vnet/vxlan-gpe/vxlan_gpe.h
@@ -64,7 +64,7 @@ typedef CLIB_PACKED (struct {
/**
* @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
*/
@@ -76,7 +76,7 @@ typedef CLIB_PACKED(struct {
u32 remote;
u32 vni;
- u32 pad;
+ u32 port;
};
u64 as_u64[2];
};
@@ -85,7 +85,7 @@ typedef CLIB_PACKED(struct {
/**
* @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
*/
@@ -94,9 +94,21 @@ 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 +129,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;
@@ -248,6 +264,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..9423b2745be 100644
--- a/src/vnet/vxlan-gpe/vxlan_gpe_api.c
+++ b/src/vnet/vxlan-gpe/vxlan_gpe_api.c
@@ -122,6 +122,73 @@ out:
/* *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
(vxlan_gpe_tunnel_t * t, vl_api_registration_t * reg, u32 context)
{
@@ -177,9 +244,9 @@ static void vl_api_vxlan_gpe_tunnel_dump_t_handler
{
/* *INDENT-OFF* */
pool_foreach (t, vgm->tunnels)
- {
- send_vxlan_gpe_tunnel_details(t, reg, mp->context);
- }
+ {
+ send_vxlan_gpe_tunnel_details (t, reg, mp->context);
+ }
/* *INDENT-ON* */
}
else
@@ -194,6 +261,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 *
diff --git a/test/test_vxlan_gpe.py b/test/test_vxlan_gpe.py
index c5d6bf07f7c..28c31ccd3bb 100644
--- a/test/test_vxlan_gpe.py
+++ b/test/test_vxlan_gpe.py
@@ -7,13 +7,13 @@ from framework import VppTestCase, VppTestRunner, running_extended_tests
from template_bd import BridgeDomain
from scapy.layers.l2 import Ether
-from scapy.packet import Raw
+from scapy.packet import Raw, bind_layers
from scapy.layers.inet import IP, UDP
from scapy.layers.vxlan import VXLAN
import util
from vpp_ip_route import VppIpRoute, VppRoutePath
-
+from vpp_vxlan_gpe_tunnel import VppVxlanGpeTunnel
from vpp_ip import INVALID_INDEX
@@ -79,14 +79,14 @@ class TestVxlanGpe(BridgeDomain, VppTestCase):
self.assertEqual(pkt[IP].dst, type(self).mcast_ip4)
# Verify UDP destination port is VXLAN-GPE 4790, source UDP port
# could be arbitrary.
- self.assertEqual(pkt[UDP].dport, type(self).dport)
+ self.assertEqual(pkt[UDP].dport, self.dport)
# Verify UDP checksum
self.assert_udp_checksum_valid(pkt)
# Verify VNI
self.assertEqual(pkt[VXLAN].vni, vni)
@classmethod
- def create_vxlan_gpe_flood_test_bd(cls, vni, n_ucast_tunnels):
+ def create_vxlan_gpe_flood_test_bd(cls, vni, n_ucast_tunnels, port):
# Create 10 ucast vxlan tunnels under bd
ip_range_start = 10
ip_range_end = ip_range_start + n_ucast_tunnels
@@ -100,15 +100,18 @@ class TestVxlanGpe(BridgeDomain, VppTestCase):
register=False)
rip.add_vpp_config()
- r = cls.vapi.vxlan_gpe_add_del_tunnel(
- src_addr=cls.pg0.local_ip4,
- dst_addr=dest_ip4,
- vni=vni)
+ r = VppVxlanGpeTunnel(cls,
+ src_addr=cls.pg0.local_ip4,
+ dst_addr=dest_ip4,
+ src_port=port,
+ dst_port=port,
+ vni=vni)
+ r.add_vpp_config()
cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
bd_id=vni)
@classmethod
- def add_del_shared_mcast_dst_load(cls, is_add):
+ def add_del_shared_mcast_dst_load(cls, port, is_add):
"""
add or del tunnels sharing the same mcast dst
to test vxlan_gpe ref_count mechanism
@@ -117,25 +120,30 @@ class TestVxlanGpe(BridgeDomain, VppTestCase):
vni_start = 1000
vni_end = vni_start + n_shared_dst_tunnels
for vni in range(vni_start, vni_end):
- r = cls.vapi.vxlan_gpe_add_del_tunnel(
- local=cls.pg0.local_ip4,
- remote=cls.mcast_ip4,
- mcast_sw_if_index=1,
- vni=vni,
- is_add=is_add)
- if r.sw_if_index == 0xffffffff:
- raise ValueError("bad sw_if_index: ~0")
+ r = VppVxlanGpeTunnel(cls,
+ src_addr=cls.pg0.local_ip4,
+ dst_addr=cls.mcast_ip4,
+ src_port=port,
+ dst_port=port,
+ mcast_sw_if_index=1,
+ vni=vni)
+ if is_add:
+ r.add_vpp_config()
+ if r.sw_if_index == 0xffffffff:
+ raise ValueError("bad sw_if_index: ~0")
+ else:
+ r.remove_vpp_config()
@classmethod
- def add_shared_mcast_dst_load(cls):
- cls.add_del_shared_mcast_dst_load(is_add=1)
+ def add_shared_mcast_dst_load(cls, port):
+ cls.add_del_shared_mcast_dst_load(port=port, is_add=1)
@classmethod
- def del_shared_mcast_dst_load(cls):
- cls.add_del_shared_mcast_dst_load(is_add=0)
+ def del_shared_mcast_dst_load(cls, port):
+ cls.add_del_shared_mcast_dst_load(port=port, is_add=0)
@classmethod
- def add_del_mcast_tunnels_load(cls, is_add):
+ def add_del_mcast_tunnels_load(cls, port, is_add):
"""
add or del tunnels to test vxlan_gpe stability
"""
@@ -145,20 +153,25 @@ class TestVxlanGpe(BridgeDomain, VppTestCase):
for dest_ip4 in ip4_range(cls.mcast_ip4, ip_range_start,
ip_range_end):
vni = int(dest_ip4.split(".")[3])
- cls.vapi.vxlan_gpe_add_del_tunnel(
- src_addr=cls.pg0.local_ip4,
- dst_addr=dest_ip4,
- mcast_sw_if_index=1,
- vni=vni,
- is_add=is_add)
+ r = VppVxlanGpeTunnel(cls,
+ src_addr=cls.pg0.local_ip4,
+ dst_addr=dest_ip4,
+ src_port=port,
+ dst_port=port,
+ mcast_sw_if_index=1,
+ vni=vni)
+ if is_add:
+ r.add_vpp_config()
+ else:
+ r.remove_vpp_config()
@classmethod
- def add_mcast_tunnels_load(cls):
- cls.add_del_mcast_tunnels_load(is_add=1)
+ def add_mcast_tunnels_load(cls, port):
+ cls.add_del_mcast_tunnels_load(port=port, is_add=1)
@classmethod
- def del_mcast_tunnels_load(cls):
- cls.add_del_mcast_tunnels_load(is_add=0)
+ def del_mcast_tunnels_load(cls, port):
+ cls.add_del_mcast_tunnels_load(port=port, is_add=0)
# Class method to start the VXLAN-GPE test case.
# Overrides setUpClass method in VppTestCase class.
@@ -170,7 +183,6 @@ class TestVxlanGpe(BridgeDomain, VppTestCase):
super(TestVxlanGpe, cls).setUpClass()
try:
- cls.dport = 4790
cls.flags = 0x0c
# Create 2 pg interfaces.
@@ -187,55 +199,120 @@ class TestVxlanGpe(BridgeDomain, VppTestCase):
# Our Multicast address
cls.mcast_ip4 = '239.1.1.1'
cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip4)
-
- # Create VXLAN-GPE VTEP on VPP pg0, and put vxlan_gpe_tunnel0
- # and pg1 into BD.
- cls.single_tunnel_vni = 0xabcde
- cls.single_tunnel_bd = 11
- r = cls.vapi.vxlan_gpe_add_del_tunnel(
- src_addr=cls.pg0.local_ip4,
- dst_addr=cls.pg0.remote_ip4,
- vni=cls.single_tunnel_vni)
- cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
- bd_id=cls.single_tunnel_bd)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.single_tunnel_bd)
-
- # Setup vni 2 to test multicast flooding
- cls.n_ucast_tunnels = 10
- cls.mcast_flood_bd = 12
- cls.create_vxlan_gpe_flood_test_bd(cls.mcast_flood_bd,
- cls.n_ucast_tunnels)
- r = cls.vapi.vxlan_gpe_add_del_tunnel(
- src_addr=cls.pg0.local_ip4,
- dst_addr=cls.mcast_ip4,
- mcast_sw_if_index=1,
- vni=cls.mcast_flood_bd)
- cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
- bd_id=cls.mcast_flood_bd)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg2.sw_if_index, bd_id=cls.mcast_flood_bd)
-
- # Add and delete mcast tunnels to check stability
- cls.add_shared_mcast_dst_load()
- cls.add_mcast_tunnels_load()
- cls.del_shared_mcast_dst_load()
- cls.del_mcast_tunnels_load()
-
- # Setup vni 3 to test unicast flooding
- cls.ucast_flood_bd = 13
- cls.create_vxlan_gpe_flood_test_bd(cls.ucast_flood_bd,
- cls.n_ucast_tunnels)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg3.sw_if_index, bd_id=cls.ucast_flood_bd)
except Exception:
- super(TestVxlanGpe, cls).tearDownClass()
+ cls.tearDownClass()
raise
@classmethod
def tearDownClass(cls):
super(TestVxlanGpe, cls).tearDownClass()
+ def setUp(self):
+ super(TestVxlanGpe, self).setUp()
+
+ def createVxLANInterfaces(self, port=4790):
+ # Create VXLAN-GPE VTEP on VPP pg0, and put vxlan_gpe_tunnel0
+ # and pg1 into BD.
+ self.dport = port
+
+ self.single_tunnel_vni = 0xabcde
+ self.single_tunnel_bd = 11
+ r = VppVxlanGpeTunnel(self,
+ src_addr=self.pg0.local_ip4,
+ dst_addr=self.pg0.remote_ip4,
+ src_port=port,
+ dst_port=port,
+ vni=self.single_tunnel_vni)
+ r.add_vpp_config()
+ self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
+ bd_id=self.single_tunnel_bd)
+ self.vapi.sw_interface_set_l2_bridge(
+ rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd)
+
+ # Setup vni 2 to test multicast flooding
+ self.n_ucast_tunnels = 10
+ self.mcast_flood_bd = 12
+ self.create_vxlan_gpe_flood_test_bd(self.mcast_flood_bd,
+ self.n_ucast_tunnels,
+ self.dport)
+ r = VppVxlanGpeTunnel(self,
+ src_addr=self.pg0.local_ip4,
+ dst_addr=self.mcast_ip4,
+ src_port=port,
+ dst_port=port,
+ mcast_sw_if_index=1,
+ vni=self.mcast_flood_bd)
+ r.add_vpp_config()
+ self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
+ bd_id=self.mcast_flood_bd)
+ self.vapi.sw_interface_set_l2_bridge(
+ rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd)
+
+ # Add and delete mcast tunnels to check stability
+ self.add_shared_mcast_dst_load(self.dport)
+ self.add_mcast_tunnels_load(self.dport)
+ self.del_shared_mcast_dst_load(self.dport)
+ self.del_mcast_tunnels_load(self.dport)
+
+ # Setup vni 3 to test unicast flooding
+ self.ucast_flood_bd = 13
+ self.create_vxlan_gpe_flood_test_bd(self.ucast_flood_bd,
+ self.n_ucast_tunnels,
+ self.dport)
+ self.vapi.sw_interface_set_l2_bridge(
+ rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd)
+
+ # Set scapy listen custom port for VxLAN
+ bind_layers(UDP, VXLAN, dport=self.dport)
+
+ """
+ Tests with default port (4790)
+ """
+ def test_decap(self):
+ """ Decapsulation test
+ from BridgeDoman
+ """
+ self.createVxLANInterfaces()
+ super(TestVxlanGpe, self).test_decap()
+
+ def test_encap(self):
+ """ Encapsulation test
+ from BridgeDoman
+ """
+ self.createVxLANInterfaces()
+ super(TestVxlanGpe, self).test_encap()
+
+ def test_ucast_flood(self):
+ """ Unicast flood test
+ from BridgeDoman
+ """
+ self.createVxLANInterfaces()
+ super(TestVxlanGpe, self).test_ucast_flood()
+
+ """
+ Tests with custom port (1112)
+ """
+ def test_decap_custom_port(self):
+ """ Decapsulation test custom port
+ from BridgeDoman
+ """
+ self.createVxLANInterfaces(1112)
+ super(TestVxlanGpe, self).test_decap()
+
+ def test_encap_custom_port(self):
+ """ Encapsulation test custom port
+ from BridgeDoman
+ """
+ self.createVxLANInterfaces(1112)
+ super(TestVxlanGpe, self).test_encap()
+
+ def test_ucast_flood_custom_port(self):
+ """ Unicast flood test custom port
+ from BridgeDoman
+ """
+ self.createVxLANInterfaces(1112)
+ super(TestVxlanGpe, self).test_ucast_flood()
+
@unittest.skip("test disabled for vxlan-gpe")
def test_mcast_flood(self):
""" inherited from BridgeDomain """
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 7e87b2c5cd3..0d521455abf 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -93,8 +93,6 @@ defaultmapping = {
'vxlan_add_del_tunnel': {'mcast_sw_if_index': 4294967295, 'is_add': 1,
'decap_next_index': 4294967295,
'instance': 4294967295, },
- 'vxlan_gpe_add_del_tunnel': {'mcast_sw_if_index': 4294967295, 'is_add': 1,
- 'protocol': 3, },
'want_bfd_events': {'enable_disable': 1, },
'want_igmp_events': {'enable': 1, },
'want_interface_events': {'enable_disable': 1, },
@@ -654,41 +652,6 @@ class VppPapiProvider(object):
'is_ip6': is_ip6
}})
- def vxlan_gpe_add_del_tunnel(
- self,
- src_addr,
- dst_addr,
- mcast_sw_if_index=0xFFFFFFFF,
- is_add=1,
- is_ipv6=0,
- encap_vrf_id=0,
- decap_vrf_id=0,
- protocol=3,
- vni=0):
- """
-
- :param local:
- :param remote:
- :param is_add: (Default value = 1)
- :param is_ipv6: (Default value = 0)
- :param encap_vrf_id: (Default value = 0)
- :param decap_vrf_id: (Default value = 0)
- :param mcast_sw_if_index: (Default value = 0xFFFFFFFF)
- :param protocol: (Default value = 3)
- :param vni: (Default value = 0)
-
- """
- return self.api(self.papi.vxlan_gpe_add_del_tunnel,
- {'is_add': is_add,
- 'is_ipv6': is_ipv6,
- 'local': src_addr,
- 'remote': dst_addr,
- 'mcast_sw_if_index': mcast_sw_if_index,
- 'encap_vrf_id': encap_vrf_id,
- 'decap_vrf_id': decap_vrf_id,
- 'protocol': protocol,
- 'vni': vni})
-
def vxlan_gbp_tunnel_dump(self, sw_if_index=0xffffffff):
return self.api(self.papi.vxlan_gbp_tunnel_dump,
{'sw_if_index': sw_if_index})
diff --git a/test/vpp_vxlan_gpe_tunnel.py b/test/vpp_vxlan_gpe_tunnel.py
new file mode 100644
index 00000000000..cff5e456aee
--- /dev/null
+++ b/test/vpp_vxlan_gpe_tunnel.py
@@ -0,0 +1,83 @@
+from vpp_interface import VppInterface
+from vpp_papi import VppEnum
+
+
+INDEX_INVALID = 0xffffffff
+DEFAULT_PORT = 4790
+UNDEFINED_PORT = 0
+
+
+def find_vxlan_gpe_tunnel(test, src, dst, s_port, d_port, vni):
+ ts = test.vapi.vxlan_gpe_tunnel_v2_dump(INDEX_INVALID)
+
+ src_port = DEFAULT_PORT
+ if s_port != UNDEFINED_PORT:
+ src_port = s_port
+
+ dst_port = DEFAULT_PORT
+ if d_port != UNDEFINED_PORT:
+ dst_port = d_port
+
+ for t in ts:
+ if src == str(t.local) and \
+ dst == str(t.remote) and \
+ src_port == t.local_port and \
+ dst_port == t.remote_port and \
+ t.vni == vni:
+ return t.sw_if_index
+ return INDEX_INVALID
+
+
+class VppVxlanGpeTunnel(VppInterface):
+ """
+ VPP VXLAN GPE interface
+ """
+
+ def __init__(self, test, src_addr, dst_addr, vni,
+ src_port=UNDEFINED_PORT, dst_port=UNDEFINED_PORT,
+ mcast_sw_if_index=INDEX_INVALID,
+ encap_vrf_id=None,
+ decap_vrf_id=None, protocol=3):
+ """ Create VXLAN GPE Tunnel interface """
+ super(VppVxlanGpeTunnel, self).__init__(test)
+ self.src = src_addr
+ self.dst = dst_addr
+ self.vni = vni
+ self.src_port = src_port
+ self.dst_port = dst_port
+ self.mcast_sw_if_index = mcast_sw_if_index
+ self.encap_vrf_id = encap_vrf_id
+ self.decap_vrf_id = decap_vrf_id
+ self.protocol = 3
+
+ def add_vpp_config(self):
+ reply = self.test.vapi.vxlan_gpe_add_del_tunnel_v2(
+ is_add=1, local=self.src, remote=self.dst, vni=self.vni,
+ local_port=self.src_port, remote_port=self.dst_port,
+ mcast_sw_if_index=self.mcast_sw_if_index,
+ encap_vrf_id=self.encap_vrf_id,
+ decap_vrf_id=self.decap_vrf_id,
+ protocol=self.protocol)
+ self.set_sw_if_index(reply.sw_if_index)
+ self._test.registry.register(self, self._test.logger)
+
+ def remove_vpp_config(self):
+ self.test.vapi.vxlan_gpe_add_del_tunnel_v2(
+ is_add=0, local=self.src, remote=self.dst, vni=self.vni,
+ local_port=self.src_port, remote_port=self.dst_port,
+ mcast_sw_if_index=self.mcast_sw_if_index,
+ encap_vrf_id=self.encap_vrf_id,
+ decap_vrf_id=self.decap_vrf_id,
+ protocol=self.protocol)
+
+ def query_vpp_config(self):
+ return (INDEX_INVALID != find_vxlan_gpe_tunnel(self._test,
+ self.src,
+ self.dst,
+ self.src_port,
+ self.dst_port,
+ self.vni))
+
+ def object_id(self):
+ return "vxlan-%d-%d-%s-%s" % (self.sw_if_index, self.vni,
+ self.src, self.dst)