summaryrefslogtreecommitdiffstats
path: root/src/vnet/vxlan/decap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/vxlan/decap.c')
-rw-r--r--src/vnet/vxlan/decap.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/src/vnet/vxlan/decap.c b/src/vnet/vxlan/decap.c
index e838c038f93..4678aa31219 100644
--- a/src/vnet/vxlan/decap.c
+++ b/src/vnet/vxlan/decap.c
@@ -68,12 +68,15 @@ vxlan4_find_tunnel (vxlan_main_t * vxm, last_tunnel_cache4 * cache,
if (PREDICT_FALSE (vxlan0->flags != VXLAN_FLAGS_I))
return decap_bad_flags;
- /* Make sure VXLAN tunnel exist according to packet S/D IP, VRF, and VNI */
+ /* Make sure VXLAN tunnel exist according to packet S/D IP, UDP port, VRF,
+ * and VNI */
u32 dst = ip4_0->dst_address.as_u32;
u32 src = ip4_0->src_address.as_u32;
+ udp_header_t *udp = ip4_next_header (ip4_0);
vxlan4_tunnel_key_t key4 = {
.key[0] = ((u64) dst << 32) | src,
- .key[1] = ((u64) fib_index << 32) | vxlan0->vni_reserved,
+ .key[1] = ((u64) udp->dst_port << 48) | ((u64) fib_index << 32) |
+ vxlan0->vni_reserved,
};
if (PREDICT_TRUE
@@ -127,11 +130,14 @@ vxlan6_find_tunnel (vxlan_main_t * vxm, last_tunnel_cache6 * cache,
if (PREDICT_FALSE (vxlan0->flags != VXLAN_FLAGS_I))
return decap_bad_flags;
- /* Make sure VXLAN tunnel exist according to packet SIP and VNI */
+ /* Make sure VXLAN tunnel exist according to packet SIP, UDP port, VRF, and
+ * VNI */
+ udp_header_t *udp = ip6_next_header (ip6_0);
vxlan6_tunnel_key_t key6 = {
.key[0] = ip6_0->src_address.as_u64[0],
.key[1] = ip6_0->src_address.as_u64[1],
- .key[2] = (((u64) fib_index) << 32) | vxlan0->vni_reserved,
+ .key[2] = ((u64) udp->dst_port << 48) | ((u64) fib_index << 32) |
+ vxlan0->vni_reserved,
};
if (PREDICT_FALSE
@@ -460,6 +466,9 @@ ip_vxlan_bypass_inline (vlib_main_t * vm,
matching a local VTEP address */
vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
+ last_tunnel_cache4 last4;
+ last_tunnel_cache6 last6;
+
#ifdef CLIB_HAVE_VEC512
vtep4_cache_t vtep4_u512;
clib_memset (&vtep4_u512, 0, sizeof (vtep4_u512));
@@ -475,9 +484,15 @@ ip_vxlan_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)
{
@@ -489,11 +504,13 @@ ip_vxlan_bypass_inline (vlib_main_t * vm,
ip4_header_t *ip40, *ip41;
ip6_header_t *ip60, *ip61;
udp_header_t *udp0, *udp1;
+ vxlan_header_t *vxlan0, *vxlan1;
u32 bi0, ip_len0, udp_len0, flags0, next0;
u32 bi1, ip_len1, udp_len1, flags1, next1;
i32 len_diff0, len_diff1;
u8 error0, good_udp0, proto0;
u8 error1, good_udp1, proto1;
+ u32 stats_if0 = ~0, stats_if1 = ~0;
/* Prefetch next iteration. */
{
@@ -551,8 +568,17 @@ ip_vxlan_bypass_inline (vlib_main_t * vm,
else
udp0 = ip6_next_header (ip60);
- if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
- goto exit0; /* not VXLAN packet */
+ u32 fi0 = vlib_buffer_get_ip_fib_index (b0, is_ip4);
+ vxlan0 = vlib_buffer_get_current (b0) + sizeof (udp_header_t) +
+ sizeof (ip4_header_t);
+
+ vxlan_decap_info_t di0 =
+ is_ip4 ?
+ vxlan4_find_tunnel (vxm, &last4, fi0, ip40, vxlan0, &stats_if0) :
+ vxlan6_find_tunnel (vxm, &last6, fi0, ip60, vxlan0, &stats_if0);
+
+ if (PREDICT_FALSE (di0.sw_if_index == ~0))
+ goto exit0; /* unknown interface */
/* Validate DIP against VTEPs */
if (is_ip4)
@@ -630,8 +656,17 @@ ip_vxlan_bypass_inline (vlib_main_t * vm,
else
udp1 = ip6_next_header (ip61);
- if (udp1->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
- goto exit1; /* not VXLAN packet */
+ u32 fi1 = vlib_buffer_get_ip_fib_index (b1, is_ip4);
+ vxlan1 = vlib_buffer_get_current (b1) + sizeof (udp_header_t) +
+ sizeof (ip4_header_t);
+
+ vxlan_decap_info_t di1 =
+ is_ip4 ?
+ vxlan4_find_tunnel (vxm, &last4, fi1, ip41, vxlan1, &stats_if1) :
+ vxlan6_find_tunnel (vxm, &last6, fi1, ip61, vxlan1, &stats_if1);
+
+ if (PREDICT_FALSE (di1.sw_if_index == ~0))
+ goto exit1; /* unknown interface */
/* Validate DIP against VTEPs */
if (is_ip4)
@@ -711,9 +746,11 @@ ip_vxlan_bypass_inline (vlib_main_t * vm,
ip4_header_t *ip40;
ip6_header_t *ip60;
udp_header_t *udp0;
+ vxlan_header_t *vxlan0;
u32 bi0, ip_len0, udp_len0, flags0, next0;
i32 len_diff0;
u8 error0, good_udp0, proto0;
+ u32 stats_if0 = ~0;
bi0 = to_next[0] = from[0];
from += 1;
@@ -746,8 +783,17 @@ ip_vxlan_bypass_inline (vlib_main_t * vm,
else
udp0 = ip6_next_header (ip60);
- if (udp0->dst_port != clib_host_to_net_u16 (UDP_DST_PORT_vxlan))
- goto exit; /* not VXLAN packet */
+ u32 fi0 = vlib_buffer_get_ip_fib_index (b0, is_ip4);
+ vxlan0 = vlib_buffer_get_current (b0) + sizeof (udp_header_t) +
+ sizeof (ip4_header_t);
+
+ vxlan_decap_info_t di0 =
+ is_ip4 ?
+ vxlan4_find_tunnel (vxm, &last4, fi0, ip40, vxlan0, &stats_if0) :
+ vxlan6_find_tunnel (vxm, &last6, fi0, ip60, vxlan0, &stats_if0);
+
+ if (PREDICT_FALSE (di0.sw_if_index == ~0))
+ goto exit; /* unknown interface */
/* Validate DIP against VTEPs */
if (is_ip4)