vxlan: add udp-port configuration support
Type: improvement Signed-off-by: Artem Glazychev <artem.glazychev@xored.com> Change-Id: Ie30d51ab4df5599b52f7335f863b930cd69dbdc1
This commit is contained in:

committed by
Ole Tr�an

parent
6b354914c2
commit
839dcc0fb7
@ -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);
|
||||
clib_memset (&last4, 0xff, sizeof last4);
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
|
@ -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";
|
||||
@ -44,12 +44,48 @@ define vxlan_add_del_tunnel
|
||||
u32 vni;
|
||||
};
|
||||
|
||||
/** \brief Create or delete a VXLAN tunnel
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - Use 1 to create the tunnel, 0 to remove it
|
||||
@param instance - optional unique custom device instance, else ~0.
|
||||
@param src_address - Source IP address
|
||||
@param dst_address - Destination IP address, can be multicast
|
||||
@param src_port - Source UDP port. It is not included in sent packets. Used only for port registration
|
||||
@param dst_port - Destination UDP port
|
||||
@param mcast_sw_if_index - Interface for multicast destination
|
||||
@param encap_vrf_id - Encap route table FIB index
|
||||
@param decap_next_index - index of decap next graph node
|
||||
@param vni - The VXLAN Network Identifier, uint24
|
||||
*/
|
||||
define vxlan_add_del_tunnel_v2
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
bool is_add [default=true];
|
||||
u32 instance [default=0xffffffff]; /* If non-~0, specifies a custom dev instance */
|
||||
vl_api_address_t src_address;
|
||||
vl_api_address_t dst_address;
|
||||
u16 src_port;
|
||||
u16 dst_port;
|
||||
vl_api_interface_index_t mcast_sw_if_index;
|
||||
u32 encap_vrf_id;
|
||||
u32 decap_next_index;
|
||||
u32 vni;
|
||||
};
|
||||
|
||||
define vxlan_add_del_tunnel_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
define vxlan_add_del_tunnel_v2_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
define vxlan_tunnel_dump
|
||||
{
|
||||
@ -57,6 +93,12 @@ define vxlan_tunnel_dump
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
define vxlan_tunnel_v2_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
};
|
||||
|
||||
define vxlan_tunnel_details
|
||||
{
|
||||
@ -70,6 +112,20 @@ define vxlan_tunnel_details
|
||||
u32 decap_next_index;
|
||||
u32 vni;
|
||||
};
|
||||
define vxlan_tunnel_v2_details
|
||||
{
|
||||
u32 context;
|
||||
vl_api_interface_index_t sw_if_index;
|
||||
u32 instance;
|
||||
vl_api_address_t src_address;
|
||||
vl_api_address_t dst_address;
|
||||
u16 src_port;
|
||||
u16 dst_port;
|
||||
vl_api_interface_index_t mcast_sw_if_index;
|
||||
u32 encap_vrf_id;
|
||||
u32 decap_next_index;
|
||||
u32 vni;
|
||||
};
|
||||
|
||||
/** \brief Interface set vxlan-bypass request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
|
@ -70,11 +70,12 @@ format_vxlan_tunnel (u8 * s, va_list * args)
|
||||
vxlan_tunnel_t *t = va_arg (*args, vxlan_tunnel_t *);
|
||||
|
||||
s = format (s,
|
||||
"[%d] instance %d src %U dst %U vni %d fib-idx %d sw-if-idx %d ",
|
||||
t->dev_instance, t->user_instance,
|
||||
format_ip46_address, &t->src, IP46_TYPE_ANY,
|
||||
format_ip46_address, &t->dst, IP46_TYPE_ANY,
|
||||
t->vni, t->encap_fib_index, t->sw_if_index);
|
||||
"[%d] instance %d src %U dst %U src_port %d dst_port %d vni %d "
|
||||
"fib-idx %d sw-if-idx %d ",
|
||||
t->dev_instance, t->user_instance, format_ip46_address, &t->src,
|
||||
IP46_TYPE_ANY, format_ip46_address, &t->dst, IP46_TYPE_ANY,
|
||||
t->src_port, t->dst_port, t->vni, t->encap_fib_index,
|
||||
t->sw_if_index);
|
||||
|
||||
s = format (s, "encap-dpo-idx %d ", t->next_dpo.dpoi_index);
|
||||
|
||||
@ -236,14 +237,15 @@ const static fib_node_vft_t vxlan_vft = {
|
||||
.fnv_back_walk = vxlan_tunnel_back_walk,
|
||||
};
|
||||
|
||||
|
||||
#define foreach_copy_field \
|
||||
_(vni) \
|
||||
_(mcast_sw_if_index) \
|
||||
_(encap_fib_index) \
|
||||
_(decap_next_index) \
|
||||
_(src) \
|
||||
_(dst)
|
||||
_ (vni) \
|
||||
_ (mcast_sw_if_index) \
|
||||
_ (encap_fib_index) \
|
||||
_ (decap_next_index) \
|
||||
_ (src) \
|
||||
_ (dst) \
|
||||
_ (src_port) \
|
||||
_ (dst_port)
|
||||
|
||||
static void
|
||||
vxlan_rewrite (vxlan_tunnel_t * t, bool is_ip6)
|
||||
@ -288,8 +290,8 @@ vxlan_rewrite (vxlan_tunnel_t * t, bool is_ip6)
|
||||
}
|
||||
|
||||
/* UDP header, randomize src port on something, maybe? */
|
||||
udp->src_port = clib_host_to_net_u16 (4789);
|
||||
udp->dst_port = clib_host_to_net_u16 (UDP_DST_PORT_vxlan);
|
||||
udp->src_port = clib_host_to_net_u16 (t->src_port);
|
||||
udp->dst_port = clib_host_to_net_u16 (t->dst_port);
|
||||
|
||||
/* VXLAN header */
|
||||
vnet_set_vni_and_flags (vxlan, t->vni);
|
||||
@ -365,6 +367,13 @@ int vnet_vxlan_add_del_tunnel
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
u8 hw_addr[6];
|
||||
|
||||
/* Set udp-ports */
|
||||
if (a->src_port == 0)
|
||||
a->src_port = is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan;
|
||||
|
||||
if (a->dst_port == 0)
|
||||
a->dst_port = is_ip6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan;
|
||||
|
||||
int not_found;
|
||||
if (!is_ip6)
|
||||
{
|
||||
@ -372,8 +381,9 @@ int vnet_vxlan_add_del_tunnel
|
||||
key4.key[0] = ip46_address_is_multicast (&a->dst) ?
|
||||
a->dst.ip4.as_u32 :
|
||||
a->dst.ip4.as_u32 | (((u64) a->src.ip4.as_u32) << 32);
|
||||
key4.key[1] = (((u64) a->encap_fib_index) << 32)
|
||||
| clib_host_to_net_u32 (a->vni << 8);
|
||||
key4.key[1] = ((u64) clib_host_to_net_u16 (a->src_port) << 48) |
|
||||
(((u64) a->encap_fib_index) << 32) |
|
||||
clib_host_to_net_u32 (a->vni << 8);
|
||||
not_found =
|
||||
clib_bihash_search_inline_16_8 (&vxm->vxlan4_tunnel_by_key, &key4);
|
||||
p = (void *) &key4.value;
|
||||
@ -382,8 +392,9 @@ int vnet_vxlan_add_del_tunnel
|
||||
{
|
||||
key6.key[0] = a->dst.ip6.as_u64[0];
|
||||
key6.key[1] = a->dst.ip6.as_u64[1];
|
||||
key6.key[2] = (((u64) a->encap_fib_index) << 32)
|
||||
| clib_host_to_net_u32 (a->vni << 8);
|
||||
key6.key[2] = (((u64) clib_host_to_net_u16 (a->src_port) << 48) |
|
||||
((u64) a->encap_fib_index) << 32) |
|
||||
clib_host_to_net_u32 (a->vni << 8);
|
||||
not_found =
|
||||
clib_bihash_search_inline_24_8 (&vxm->vxlan6_tunnel_by_key, &key6);
|
||||
p = (void *) &key6.value;
|
||||
@ -649,11 +660,11 @@ int vnet_vxlan_add_del_tunnel
|
||||
if (a->is_add)
|
||||
{
|
||||
/* register udp ports */
|
||||
if (!is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_vxlan, 1))
|
||||
udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_vxlan,
|
||||
if (!is_ip6 && !udp_is_valid_dst_port (a->src_port, 1))
|
||||
udp_register_dst_port (vxm->vlib_main, a->src_port,
|
||||
vxlan4_input_node.index, 1);
|
||||
if (is_ip6 && !udp_is_valid_dst_port (UDP_DST_PORT_vxlan6, 0))
|
||||
udp_register_dst_port (vxm->vlib_main, UDP_DST_PORT_vxlan6,
|
||||
if (is_ip6 && !udp_is_valid_dst_port (a->src_port, 0))
|
||||
udp_register_dst_port (vxm->vlib_main, a->src_port,
|
||||
vxlan6_input_node.index, 0);
|
||||
}
|
||||
|
||||
@ -711,6 +722,8 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm,
|
||||
u32 mcast_sw_if_index = ~0;
|
||||
u32 decap_next_index = VXLAN_INPUT_NEXT_L2_INPUT;
|
||||
u32 vni = 0;
|
||||
u32 src_port = 0;
|
||||
u32 dst_port = 0;
|
||||
u32 table_id;
|
||||
clib_error_t *parse_error = NULL;
|
||||
|
||||
@ -756,6 +769,10 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm,
|
||||
;
|
||||
else if (unformat (line_input, "vni %d", &vni))
|
||||
;
|
||||
else if (unformat (line_input, "src_port %d", &src_port))
|
||||
;
|
||||
else if (unformat (line_input, "dst_port %d", &dst_port))
|
||||
;
|
||||
else
|
||||
{
|
||||
parse_error = clib_error_return (0, "parse error: '%U'",
|
||||
@ -855,11 +872,17 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm,
|
||||
*
|
||||
* @cliexpar
|
||||
* Example of how to create a VXLAN Tunnel:
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 encap-vrf-id 7}
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 encap-vrf-id
|
||||
7}
|
||||
* Example of how to create a VXLAN Tunnel with a known name, vxlan_tunnel42:
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 instance 42}
|
||||
* Example of how to create a multicast VXLAN Tunnel with a known name, vxlan_tunnel23:
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 group 239.1.1.1 GigabitEthernet0/8/0 instance 23}
|
||||
* Example of how to create a multicast VXLAN Tunnel with a known name,
|
||||
vxlan_tunnel23:
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 group 239.1.1.1
|
||||
GigabitEthernet0/8/0 instance 23}
|
||||
* Example of how to create a VXLAN Tunnel with custom udp-ports:
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 src_port
|
||||
59000 dst_port 59001}
|
||||
* Example of how to delete a VXLAN Tunnel:
|
||||
* @cliexcmd{create vxlan tunnel src 10.0.3.1 dst 10.0.3.3 vni 13 del}
|
||||
?*/
|
||||
@ -870,7 +893,8 @@ VLIB_CLI_COMMAND (create_vxlan_tunnel_command, static) = {
|
||||
"create vxlan tunnel src <local-vtep-addr>"
|
||||
" {dst <remote-vtep-addr>|group <mcast-vtep-addr> <intf-name>} vni <nn>"
|
||||
" [instance <id>]"
|
||||
" [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [del]",
|
||||
" [encap-vrf-id <nn>] [decap-next [l2|node <name>]] [del]"
|
||||
" [src_port <local-vtep-udp-port>] [dst_port <remote-vtep-udp-port>]",
|
||||
.function = vxlan_add_del_tunnel_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
@ -922,7 +946,8 @@ show_vxlan_tunnel_command_fn (vlib_main_t * vm,
|
||||
* @cliexpar
|
||||
* Example of how to display the VXLAN Tunnel entries:
|
||||
* @cliexstart{show vxlan tunnel}
|
||||
* [0] src 10.0.3.1 dst 10.0.3.3 vni 13 encap_fib_index 0 sw_if_index 5 decap_next l2
|
||||
* [0] src 10.0.3.1 dst 10.0.3.3 src_port 4789 dst_port 4789 vni 13
|
||||
encap_fib_index 0 sw_if_index 5 decap_next l2
|
||||
* @cliexend
|
||||
?*/
|
||||
/* *INDENT-OFF* */
|
||||
@ -1155,7 +1180,7 @@ vnet_vxlan_add_del_rx_flow (u32 hw_if_index, u32 t_index, int is_add)
|
||||
.dst_addr.addr = t->src.ip4,
|
||||
.src_addr.mask.as_u32 = ~0,
|
||||
.dst_addr.mask.as_u32 = ~0,
|
||||
.dst_port.port = UDP_DST_PORT_vxlan,
|
||||
.dst_port.port = t->src_port,
|
||||
.dst_port.mask = 0xFF,
|
||||
.vni = t->vni,
|
||||
}
|
||||
|
@ -93,6 +93,10 @@ typedef struct
|
||||
ip46_address_t src;
|
||||
ip46_address_t dst;
|
||||
|
||||
/* udp-ports */
|
||||
u16 src_port;
|
||||
u16 dst_port;
|
||||
|
||||
/* mcast packet output intfc index (used only if dst is mcast) */
|
||||
u32 mcast_sw_if_index;
|
||||
|
||||
@ -159,8 +163,10 @@ typedef struct
|
||||
vxlan_tunnel_t *tunnels;
|
||||
|
||||
/* lookup tunnel by key */
|
||||
clib_bihash_16_8_t vxlan4_tunnel_by_key; /* keyed on ipv4.dst + fib + vni */
|
||||
clib_bihash_24_8_t vxlan6_tunnel_by_key; /* keyed on ipv6.dst + fib + vni */
|
||||
clib_bihash_16_8_t
|
||||
vxlan4_tunnel_by_key; /* keyed on ipv4.dst + src_port + fib + vni */
|
||||
clib_bihash_24_8_t
|
||||
vxlan6_tunnel_by_key; /* keyed on ipv6.dst + src_port + fib + vni */
|
||||
|
||||
/* local VTEP IPs ref count used by vxlan-bypass node to check if
|
||||
received VXLAN packet DIP matches any local VTEP address */
|
||||
@ -208,6 +214,8 @@ typedef struct
|
||||
u32 encap_fib_index;
|
||||
u32 decap_next_index;
|
||||
u32 vni;
|
||||
u16 src_port;
|
||||
u16 dst_port;
|
||||
} vnet_vxlan_add_del_tunnel_args_t;
|
||||
|
||||
int vnet_vxlan_add_del_tunnel
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <vnet/fib/fib_table.h>
|
||||
|
||||
#include <vnet/ip/ip_types_api.h>
|
||||
#include <vnet/udp/udp_local.h>
|
||||
|
||||
#include <vnet/vnet_msg_enum.h>
|
||||
|
||||
@ -47,10 +48,12 @@
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
#define foreach_vpe_api_msg \
|
||||
_(SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass) \
|
||||
_(VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel) \
|
||||
_(VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump) \
|
||||
_(VXLAN_OFFLOAD_RX, vxlan_offload_rx)
|
||||
_ (SW_INTERFACE_SET_VXLAN_BYPASS, sw_interface_set_vxlan_bypass) \
|
||||
_ (VXLAN_ADD_DEL_TUNNEL, vxlan_add_del_tunnel) \
|
||||
_ (VXLAN_TUNNEL_DUMP, vxlan_tunnel_dump) \
|
||||
_ (VXLAN_ADD_DEL_TUNNEL_V2, vxlan_add_del_tunnel_v2) \
|
||||
_ (VXLAN_TUNNEL_V2_DUMP, vxlan_tunnel_v2_dump) \
|
||||
_ (VXLAN_OFFLOAD_RX, vxlan_offload_rx)
|
||||
|
||||
static void
|
||||
vl_api_vxlan_offload_rx_t_handler (vl_api_vxlan_offload_rx_t * mp)
|
||||
@ -159,6 +162,8 @@ static void vl_api_vxlan_add_del_tunnel_t_handler
|
||||
.vni = ntohl (mp->vni),
|
||||
.dst = dst,
|
||||
.src = src,
|
||||
.dst_port = is_ipv6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan,
|
||||
.src_port = is_ipv6 ? UDP_DST_PORT_vxlan6 : UDP_DST_PORT_vxlan,
|
||||
};
|
||||
|
||||
/* Check src & dst are different */
|
||||
@ -178,12 +183,73 @@ static void vl_api_vxlan_add_del_tunnel_t_handler
|
||||
rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
|
||||
|
||||
out:
|
||||
/* *INDENT-OFF* */
|
||||
REPLY_MACRO2(VL_API_VXLAN_ADD_DEL_TUNNEL_REPLY,
|
||||
({
|
||||
rmp->sw_if_index = ntohl (sw_if_index);
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_vxlan_add_del_tunnel_v2_t_handler (vl_api_vxlan_add_del_tunnel_v2_t *mp)
|
||||
{
|
||||
vl_api_vxlan_add_del_tunnel_v2_reply_t *rmp;
|
||||
int rv = 0;
|
||||
bool is_ipv6;
|
||||
u32 fib_index;
|
||||
ip46_address_t src, dst;
|
||||
|
||||
ip_address_decode (&mp->src_address, &src);
|
||||
ip_address_decode (&mp->dst_address, &dst);
|
||||
|
||||
if (ip46_address_is_ip4 (&src) != ip46_address_is_ip4 (&dst))
|
||||
{
|
||||
rv = VNET_API_ERROR_INVALID_VALUE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
is_ipv6 = !ip46_address_is_ip4 (&src);
|
||||
|
||||
fib_index =
|
||||
fib_table_find (fib_ip_proto (is_ipv6), ntohl (mp->encap_vrf_id));
|
||||
if (fib_index == ~0)
|
||||
{
|
||||
rv = VNET_API_ERROR_NO_SUCH_FIB;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vnet_vxlan_add_del_tunnel_args_t a = {
|
||||
.is_add = mp->is_add,
|
||||
.is_ip6 = is_ipv6,
|
||||
.instance = ntohl (mp->instance),
|
||||
.mcast_sw_if_index = ntohl (mp->mcast_sw_if_index),
|
||||
.encap_fib_index = fib_index,
|
||||
.decap_next_index = ntohl (mp->decap_next_index),
|
||||
.vni = ntohl (mp->vni),
|
||||
.dst = dst,
|
||||
.src = src,
|
||||
.dst_port = ntohs (mp->dst_port),
|
||||
.src_port = ntohs (mp->src_port),
|
||||
};
|
||||
|
||||
/* Check src & dst are different */
|
||||
if (ip46_address_cmp (&a.dst, &a.src) == 0)
|
||||
{
|
||||
rv = VNET_API_ERROR_SAME_SRC_DST;
|
||||
goto out;
|
||||
}
|
||||
if (ip46_address_is_multicast (&a.dst) &&
|
||||
!vnet_sw_if_index_is_api_valid (a.mcast_sw_if_index))
|
||||
{
|
||||
rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
|
||||
goto out;
|
||||
}
|
||||
|
||||
u32 sw_if_index = ~0;
|
||||
rv = vnet_vxlan_add_del_tunnel (&a, &sw_if_index);
|
||||
|
||||
out:
|
||||
REPLY_MACRO2 (VL_API_VXLAN_ADD_DEL_TUNNEL_V2_REPLY,
|
||||
({ rmp->sw_if_index = ntohl (sw_if_index); }));
|
||||
}
|
||||
|
||||
static void send_vxlan_tunnel_details
|
||||
@ -231,13 +297,9 @@ static void vl_api_vxlan_tunnel_dump_t_handler
|
||||
|
||||
if (~0 == sw_if_index)
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (t, vxm->tunnels)
|
||||
{
|
||||
send_vxlan_tunnel_details(t, reg, mp->context);
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
|
||||
@ -250,6 +312,69 @@ static void vl_api_vxlan_tunnel_dump_t_handler
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
send_vxlan_tunnel_v2_details (vxlan_tunnel_t *t, vl_api_registration_t *reg,
|
||||
u32 context)
|
||||
{
|
||||
vl_api_vxlan_tunnel_v2_details_t *rmp;
|
||||
ip4_main_t *im4 = &ip4_main;
|
||||
ip6_main_t *im6 = &ip6_main;
|
||||
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||
clib_memset (rmp, 0, sizeof (*rmp));
|
||||
rmp->_vl_msg_id = ntohs (VL_API_VXLAN_TUNNEL_V2_DETAILS);
|
||||
|
||||
ip_address_encode (&t->src, IP46_TYPE_ANY, &rmp->src_address);
|
||||
ip_address_encode (&t->dst, IP46_TYPE_ANY, &rmp->dst_address);
|
||||
rmp->src_port = htons (t->src_port);
|
||||
rmp->dst_port = htons (t->dst_port);
|
||||
|
||||
if (ip46_address_is_ip4 (&t->dst))
|
||||
rmp->encap_vrf_id = htonl (im4->fibs[t->encap_fib_index].ft_table_id);
|
||||
else
|
||||
rmp->encap_vrf_id = htonl (im6->fibs[t->encap_fib_index].ft_table_id);
|
||||
|
||||
rmp->instance = htonl (t->user_instance);
|
||||
rmp->mcast_sw_if_index = htonl (t->mcast_sw_if_index);
|
||||
rmp->vni = htonl (t->vni);
|
||||
rmp->decap_next_index = htonl (t->decap_next_index);
|
||||
rmp->sw_if_index = htonl (t->sw_if_index);
|
||||
rmp->context = context;
|
||||
|
||||
vl_api_send_msg (reg, (u8 *) rmp);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_vxlan_tunnel_v2_dump_t_handler (vl_api_vxlan_tunnel_v2_dump_t *mp)
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
vxlan_main_t *vxm = &vxlan_main;
|
||||
vxlan_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, vxm->tunnels)
|
||||
send_vxlan_tunnel_v2_details (t, reg, mp->context);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((sw_if_index >= vec_len (vxm->tunnel_index_by_sw_if_index)) ||
|
||||
(~0 == vxm->tunnel_index_by_sw_if_index[sw_if_index]))
|
||||
{
|
||||
return;
|
||||
}
|
||||
t = &vxm->tunnels[vxm->tunnel_index_by_sw_if_index[sw_if_index]];
|
||||
send_vxlan_tunnel_v2_details (t, reg, mp->context);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* vpe_api_hookup
|
||||
* Add vpe's API message handlers to the table.
|
||||
|
@ -7,7 +7,7 @@ from framework import VppTestCase, VppTestRunner
|
||||
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
|
||||
|
||||
@ -79,14 +79,14 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
self.assertEqual(pkt[IP].dst, type(self).mcast_ip4)
|
||||
# Verify UDP destination port is VXLAN 4789, 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_flood_test_bd(cls, vni, n_ucast_tunnels):
|
||||
def create_vxlan_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
|
||||
@ -101,12 +101,13 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
rip.add_vpp_config()
|
||||
|
||||
r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4,
|
||||
src_port=port, dst_port=port,
|
||||
dst=dest_ip4, vni=vni)
|
||||
r.add_vpp_config()
|
||||
cls.vapi.sw_interface_set_l2_bridge(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 ref_count mechanism
|
||||
@ -116,6 +117,7 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
vni_end = vni_start + n_shared_dst_tunnels
|
||||
for vni in range(vni_start, vni_end):
|
||||
r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4,
|
||||
src_port=port, dst_port=port,
|
||||
dst=cls.mcast_ip4, mcast_sw_if_index=1, vni=vni)
|
||||
if is_add:
|
||||
r.add_vpp_config()
|
||||
@ -125,15 +127,15 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
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 stability
|
||||
"""
|
||||
@ -144,6 +146,7 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
ip_range_end):
|
||||
vni = bytearray(socket.inet_pton(socket.AF_INET, dest_ip4))[3]
|
||||
r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4,
|
||||
src_port=port, dst_port=port,
|
||||
dst=dest_ip4, mcast_sw_if_index=1, vni=vni)
|
||||
if is_add:
|
||||
r.add_vpp_config()
|
||||
@ -151,12 +154,12 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
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 test case.
|
||||
# Overrides setUpClass method in VppTestCase class.
|
||||
@ -168,7 +171,6 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
super(TestVxlan, cls).setUpClass()
|
||||
|
||||
try:
|
||||
cls.dport = 4789
|
||||
cls.flags = 0x8
|
||||
|
||||
# Create 2 pg interfaces.
|
||||
@ -195,12 +197,17 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVxlan, self).setUp()
|
||||
|
||||
def createVxLANInterfaces(self, port=4789):
|
||||
# Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1
|
||||
# into BD.
|
||||
self.dport = port
|
||||
|
||||
self.single_tunnel_vni = 0x12345
|
||||
self.single_tunnel_bd = 1
|
||||
r = VppVxlanTunnel(self, src=self.pg0.local_ip4,
|
||||
dst=self.pg0.remote_ip4,
|
||||
src_port=self.dport, dst_port=self.dport,
|
||||
vni=self.single_tunnel_vni)
|
||||
r.add_vpp_config()
|
||||
self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
|
||||
@ -212,8 +219,10 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
self.n_ucast_tunnels = 10
|
||||
self.mcast_flood_bd = 2
|
||||
self.create_vxlan_flood_test_bd(self.mcast_flood_bd,
|
||||
self.n_ucast_tunnels)
|
||||
self.n_ucast_tunnels,
|
||||
self.dport)
|
||||
r = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.mcast_ip4,
|
||||
src_port=self.dport, dst_port=self.dport,
|
||||
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,
|
||||
@ -222,29 +231,23 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
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.add_mcast_tunnels_load()
|
||||
self.del_shared_mcast_dst_load()
|
||||
self.del_mcast_tunnels_load()
|
||||
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 = 3
|
||||
self.create_vxlan_flood_test_bd(self.ucast_flood_bd,
|
||||
self.n_ucast_tunnels)
|
||||
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)
|
||||
|
||||
def test_decap(self):
|
||||
""" Decapsulation test
|
||||
from BridgeDoman
|
||||
"""
|
||||
super(TestVxlan, self).test_decap()
|
||||
|
||||
def test_encap_big_packet(self):
|
||||
""" Encapsulation test send big frame from pg1
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
# Set scapy listen custom port for VxLAN
|
||||
bind_layers(UDP, VXLAN, dport=self.dport)
|
||||
|
||||
def encap_big_packet(self):
|
||||
self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0])
|
||||
|
||||
frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') /
|
||||
@ -269,9 +272,93 @@ class TestVxlan(BridgeDomain, VppTestCase):
|
||||
# TODO: Scapy bug?
|
||||
# self.assert_eq_pkts(payload, frame)
|
||||
|
||||
"""
|
||||
Tests with default port (4789)
|
||||
"""
|
||||
def test_decap(self):
|
||||
""" Decapsulation test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan, self).test_decap()
|
||||
|
||||
def test_encap(self):
|
||||
""" Encapsulation test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan, self).test_encap()
|
||||
|
||||
def test_encap_big_packet(self):
|
||||
""" Encapsulation test send big frame from pg1
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
self.encap_big_packet()
|
||||
|
||||
def test_ucast_flood(self):
|
||||
""" Unicast flood test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan, self).test_ucast_flood()
|
||||
|
||||
def test_mcast_flood(self):
|
||||
""" Multicast flood test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan, self).test_mcast_flood()
|
||||
|
||||
def test_mcast_rcv(self):
|
||||
""" Multicast receive test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan, self).test_mcast_rcv()
|
||||
|
||||
"""
|
||||
Tests with custom port
|
||||
"""
|
||||
def test_decap_custom_port(self):
|
||||
""" Decapsulation test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan, self).test_decap()
|
||||
|
||||
def test_encap_custom_port(self):
|
||||
""" Encapsulation test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan, self).test_encap()
|
||||
|
||||
def test_ucast_flood_custom_port(self):
|
||||
""" Unicast flood test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan, self).test_ucast_flood()
|
||||
|
||||
def test_mcast_flood_custom_port(self):
|
||||
""" Multicast flood test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan, self).test_mcast_flood()
|
||||
|
||||
def test_mcast_rcv_custom_port(self):
|
||||
""" Multicast receive test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan, self).test_mcast_rcv()
|
||||
|
||||
# Method to define VPP actions before tear down of the test case.
|
||||
# Overrides tearDown method in VppTestCase class.
|
||||
# @param self The object pointer.
|
||||
|
||||
def tearDown(self):
|
||||
super(TestVxlan, self).tearDown()
|
||||
|
||||
|
@ -6,7 +6,7 @@ from framework import VppTestCase, VppTestRunner
|
||||
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.inet6 import IP, IPv6, UDP
|
||||
from scapy.layers.vxlan import VXLAN
|
||||
|
||||
@ -80,14 +80,14 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
self.assertEqual(pkt[IPv6].dst, type(self).mcast_ip6)
|
||||
# Verify UDP destination port is VXLAN 4789, 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, ignore_zero_checksum=False)
|
||||
# Verify VNI
|
||||
self.assertEqual(pkt[VXLAN].vni, vni)
|
||||
|
||||
@classmethod
|
||||
def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels):
|
||||
def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels, port):
|
||||
# Create 10 ucast vxlan tunnels under bd
|
||||
start = 10
|
||||
end = start + n_ucast_tunnels
|
||||
@ -98,6 +98,7 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
register=False)
|
||||
rip.add_vpp_config()
|
||||
r = VppVxlanTunnel(cls, src=cls.pg0.local_ip6,
|
||||
src_port=port, dst_port=port,
|
||||
dst=dest_ip6, vni=vni)
|
||||
r.add_vpp_config()
|
||||
cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni)
|
||||
@ -120,7 +121,6 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
super(TestVxlan6, cls).setUpClass()
|
||||
|
||||
try:
|
||||
cls.dport = 4789
|
||||
cls.flags = 0x8
|
||||
|
||||
# Create 2 pg interfaces.
|
||||
@ -147,12 +147,17 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVxlan6, self).setUp()
|
||||
|
||||
def createVxLANInterfaces(self, port=4789):
|
||||
# Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1
|
||||
# into BD.
|
||||
self.dport = port
|
||||
|
||||
self.single_tunnel_vni = 0x12345
|
||||
self.single_tunnel_bd = 1
|
||||
r = VppVxlanTunnel(self, src=self.pg0.local_ip6,
|
||||
dst=self.pg0.remote_ip6,
|
||||
src_port=self.dport, dst_port=self.dport,
|
||||
vni=self.single_tunnel_vni)
|
||||
r.add_vpp_config()
|
||||
self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
|
||||
@ -164,8 +169,10 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
self.n_ucast_tunnels = 10
|
||||
self.mcast_flood_bd = 2
|
||||
self.create_vxlan_flood_test_bd(self.mcast_flood_bd,
|
||||
self.n_ucast_tunnels)
|
||||
self.n_ucast_tunnels,
|
||||
self.dport)
|
||||
r = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.mcast_ip6,
|
||||
src_port=self.dport, dst_port=self.dport,
|
||||
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,
|
||||
@ -176,10 +183,14 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
# Setup vni 3 to test unicast flooding
|
||||
self.ucast_flood_bd = 3
|
||||
self.create_vxlan_flood_test_bd(self.ucast_flood_bd,
|
||||
self.n_ucast_tunnels)
|
||||
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)
|
||||
|
||||
# Method to define VPP actions before tear down of the test case.
|
||||
# Overrides tearDown method in VppTestCase class.
|
||||
# @param self The object pointer.
|
||||
@ -192,11 +203,7 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
self.logger.info(self.vapi.cli("show bridge-domain 3 detail"))
|
||||
self.logger.info(self.vapi.cli("show vxlan tunnel"))
|
||||
|
||||
def test_encap_fragmented_packet(self):
|
||||
""" Encapsulation test send fragments from pg1
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
|
||||
def encap_fragmented_packet(self):
|
||||
frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') /
|
||||
IP(src='4.3.2.1', dst='1.2.3.4') /
|
||||
UDP(sport=20000, dport=10000) /
|
||||
@ -221,6 +228,89 @@ class TestVxlan6(BridgeDomain, VppTestCase):
|
||||
|
||||
self.assertEqual(Ether(raw(frame))[IP], reassembled[IP])
|
||||
|
||||
"""
|
||||
Tests with default port (4789)
|
||||
"""
|
||||
def test_decap(self):
|
||||
""" Decapsulation test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan6, self).test_decap()
|
||||
|
||||
def test_encap(self):
|
||||
""" Encapsulation test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan6, self).test_encap()
|
||||
|
||||
def test_encap_fragmented_packet(self):
|
||||
""" Encapsulation test send fragments from pg1
|
||||
Verify receipt of encapsulated frames on pg0
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
self.encap_fragmented_packet()
|
||||
|
||||
def test_ucast_flood(self):
|
||||
""" Unicast flood test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan6, self).test_ucast_flood()
|
||||
|
||||
def test_mcast_flood(self):
|
||||
""" Multicast flood test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan6, self).test_mcast_flood()
|
||||
|
||||
def test_mcast_rcv(self):
|
||||
""" Multicast receive test
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces()
|
||||
super(TestVxlan6, self).test_mcast_rcv()
|
||||
|
||||
"""
|
||||
Tests with custom port
|
||||
"""
|
||||
def test_decap_custom_port(self):
|
||||
""" Decapsulation test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan6, self).test_decap()
|
||||
|
||||
def test_encap_custom_port(self):
|
||||
""" Encapsulation test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan6, self).test_encap()
|
||||
|
||||
def test_ucast_flood_custom_port(self):
|
||||
""" Unicast flood test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan6, self).test_ucast_flood()
|
||||
|
||||
def test_mcast_flood_custom_port(self):
|
||||
""" Multicast flood test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan6, self).test_mcast_flood()
|
||||
|
||||
def test_mcast_rcv_custom_port(self):
|
||||
""" Multicast receive test custom port
|
||||
from BridgeDoman
|
||||
"""
|
||||
self.createVxLANInterfaces(1111)
|
||||
super(TestVxlan6, self).test_mcast_rcv()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
@ -3,13 +3,26 @@ from vpp_papi import VppEnum
|
||||
|
||||
|
||||
INDEX_INVALID = 0xffffffff
|
||||
DEFAULT_PORT = 4789
|
||||
UNDEFINED_PORT = 0
|
||||
|
||||
|
||||
def find_vxlan_tunnel(test, src, dst, vni):
|
||||
ts = test.vapi.vxlan_tunnel_dump(INDEX_INVALID)
|
||||
def find_vxlan_tunnel(test, src, dst, s_port, d_port, vni):
|
||||
ts = test.vapi.vxlan_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.src_address) and \
|
||||
dst == str(t.dst_address) and \
|
||||
src_port == t.src_port and \
|
||||
dst_port == t.dst_port and \
|
||||
t.vni == vni:
|
||||
return t.sw_if_index
|
||||
return INDEX_INVALID
|
||||
@ -20,7 +33,9 @@ class VppVxlanTunnel(VppInterface):
|
||||
VPP VXLAN interface
|
||||
"""
|
||||
|
||||
def __init__(self, test, src, dst, vni, mcast_itf=None,
|
||||
def __init__(self, test, src, dst, vni,
|
||||
src_port=UNDEFINED_PORT, dst_port=UNDEFINED_PORT,
|
||||
mcast_itf=None,
|
||||
mcast_sw_if_index=INDEX_INVALID,
|
||||
decap_next_index=INDEX_INVALID,
|
||||
encap_vrf_id=None, instance=0xffffffff):
|
||||
@ -29,6 +44,8 @@ class VppVxlanTunnel(VppInterface):
|
||||
self.src = src
|
||||
self.dst = dst
|
||||
self.vni = vni
|
||||
self.src_port = src_port
|
||||
self.dst_port = dst_port
|
||||
self.mcast_itf = mcast_itf
|
||||
self.mcast_sw_if_index = mcast_sw_if_index
|
||||
self.encap_vrf_id = encap_vrf_id
|
||||
@ -39,8 +56,9 @@ class VppVxlanTunnel(VppInterface):
|
||||
self.mcast_sw_if_index = self.mcast_itf.sw_if_index
|
||||
|
||||
def add_vpp_config(self):
|
||||
reply = self.test.vapi.vxlan_add_del_tunnel(
|
||||
reply = self.test.vapi.vxlan_add_del_tunnel_v2(
|
||||
is_add=1, src_address=self.src, dst_address=self.dst, vni=self.vni,
|
||||
src_port=self.src_port, dst_port=self.dst_port,
|
||||
mcast_sw_if_index=self.mcast_sw_if_index,
|
||||
encap_vrf_id=self.encap_vrf_id,
|
||||
instance=self.instance, decap_next_index=self.decap_next_index)
|
||||
@ -48,8 +66,9 @@ class VppVxlanTunnel(VppInterface):
|
||||
self._test.registry.register(self, self._test.logger)
|
||||
|
||||
def remove_vpp_config(self):
|
||||
self.test.vapi.vxlan_add_del_tunnel(
|
||||
self.test.vapi.vxlan_add_del_tunnel_v2(
|
||||
is_add=0, src_address=self.src, dst_address=self.dst, vni=self.vni,
|
||||
src_port=self.src_port, dst_port=self.dst_port,
|
||||
mcast_sw_if_index=self.mcast_sw_if_index,
|
||||
encap_vrf_id=self.encap_vrf_id, instance=self.instance,
|
||||
decap_next_index=self.decap_next_index)
|
||||
@ -58,6 +77,8 @@ class VppVxlanTunnel(VppInterface):
|
||||
return (INDEX_INVALID != find_vxlan_tunnel(self._test,
|
||||
self.src,
|
||||
self.dst,
|
||||
self.src_port,
|
||||
self.dst_port,
|
||||
self.vni))
|
||||
|
||||
def object_id(self):
|
||||
|
Reference in New Issue
Block a user