vxlan: add udp-port configuration support 04/30204/10
authorArtem Glazychev <artem.glazychev@xored.com>
Mon, 30 Nov 2020 19:39:21 +0000 (02:39 +0700)
committerOle Tr�an <otroan@employees.org>
Fri, 5 Feb 2021 11:53:38 +0000 (11:53 +0000)
Type: improvement

Signed-off-by: Artem Glazychev <artem.glazychev@xored.com>
Change-Id: Ie30d51ab4df5599b52f7335f863b930cd69dbdc1

src/vnet/vxlan/decap.c
src/vnet/vxlan/vxlan.api
src/vnet/vxlan/vxlan.c
src/vnet/vxlan/vxlan.h
src/vnet/vxlan/vxlan_api.c
test/test_vxlan.py
test/test_vxlan6.py
test/vpp_vxlan_tunnel.py

index e838c03..4678aa3 100644 (file)
@@ -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)
index 907d7d3..2370fb5 100644 (file)
@@ -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
index b2329d8..97098b8 100644 (file)
@@ -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)
+#define foreach_copy_field                                                    \
+  _ (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,15 +367,23 @@ 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)
     {
       /* ip4 mcast is indexed by mcast addr only */
       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);
+                     a->dst.ip4.as_u32 :
+                     a->dst.ip4.as_u32 | (((u64) a->src.ip4.as_u32) << 32);
+      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}
  ?*/
@@ -867,10 +890,11 @@ vxlan_add_del_tunnel_command_fn (vlib_main_t * vm,
 VLIB_CLI_COMMAND (create_vxlan_tunnel_command, static) = {
   .path = "create vxlan tunnel",
   .short_help =
-  "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]",
+    "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]"
+    " [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,
                          }
index 1c77d77..48c6146 100644 (file)
@@ -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
index 0e51f3d..6975d83 100644 (file)
@@ -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>
 
 
 #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)
+#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_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,12 +297,8 @@ 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
     {
@@ -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.
index dc48f53..028275c 100644 (file)
@@ -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()
 
index d9e2d81..123cce9 100644 (file)
@@ -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)
index 0f6ecb7..dce5ab8 100644 (file)
@@ -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):