summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vnet/vxlan/decap.c70
-rw-r--r--src/vnet/vxlan/vxlan.api58
-rw-r--r--src/vnet/vxlan/vxlan.c93
-rw-r--r--src/vnet/vxlan/vxlan.h12
-rw-r--r--src/vnet/vxlan/vxlan_api.c147
5 files changed, 320 insertions, 60 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)
diff --git a/src/vnet/vxlan/vxlan.api b/src/vnet/vxlan/vxlan.api
index 907d7d32ce7..2370fb5157c 100644
--- a/src/vnet/vxlan/vxlan.api
+++ b/src/vnet/vxlan/vxlan.api
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-option version = "2.0.0";
+option version = "2.1.0";
import "vnet/interface_types.api";
import "vnet/ip/ip_types.api";
@@ -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
diff --git a/src/vnet/vxlan/vxlan.c b/src/vnet/vxlan/vxlan.c
index b2329d815ff..97098b83774 100644
--- a/src/vnet/vxlan/vxlan.c
+++ b/src/vnet/vxlan/vxlan.c
@@ -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,
}
diff --git a/src/vnet/vxlan/vxlan.h b/src/vnet/vxlan/vxlan.h
index 1c77d77ee51..48c61461e7c 100644
--- a/src/vnet/vxlan/vxlan.h
+++ b/src/vnet/vxlan/vxlan.h
@@ -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
diff --git a/src/vnet/vxlan/vxlan_api.c b/src/vnet/vxlan/vxlan_api.c
index 0e51f3dab5a..6975d834e2a 100644
--- a/src/vnet/vxlan/vxlan_api.c
+++ b/src/vnet/vxlan/vxlan_api.c
@@ -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>
@@ -46,11 +47,13 @@
#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.