From a342da22f35676114ca928c65b0219fac8009f7a Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 6 Jun 2019 10:35:07 +0000 Subject: DVR: Control the reinject as L2 or L3 based on the output interface type Change-Id: Ib4cdbe8a6a1d10a643941c13aa0acbed410f876c Type: Feature Signed-off-by: Neale Ranns --- src/vnet/buffer.h | 2 +- src/vnet/dpo/dvr_dpo.c | 76 +++++++++++++++++++++++++++++++++++++++++++------- src/vnet/dpo/dvr_dpo.h | 17 +++++++++++ 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/vnet/buffer.h b/src/vnet/buffer.h index 5114dc68a71..7065bd745d0 100644 --- a/src/vnet/buffer.h +++ b/src/vnet/buffer.h @@ -239,9 +239,9 @@ typedef struct { u32 feature_bitmap; u16 bd_index; /* bridge-domain index */ + u16 l2fib_sn; /* l2fib bd/int seq_num */ u8 l2_len; /* ethernet header length */ u8 shg; /* split-horizon group */ - u16 l2fib_sn; /* l2fib bd/int seq_num */ u8 bd_age; /* aging enabled */ } l2; diff --git a/src/vnet/dpo/dvr_dpo.c b/src/vnet/dpo/dvr_dpo.c index 877f42a9893..6dd58108091 100644 --- a/src/vnet/dpo/dvr_dpo.c +++ b/src/vnet/dpo/dvr_dpo.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifndef CLIB_MARCH_VARIANT dvr_dpo_t *dvr_dpo_pool; @@ -91,6 +92,7 @@ dvr_dpo_add_or_lock (u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo) { + l2_input_config_t *config; dvr_dpo_t *dd; vec_validate_init_empty(dvr_dpo_db[dproto], @@ -106,6 +108,17 @@ dvr_dpo_add_or_lock (u32 sw_if_index, dvr_dpo_db[dproto][sw_if_index] = dvr_dpo_get_index(dd); + config = l2input_intf_config (sw_if_index); + + if (config->bridge || config->xconnect) + { + dd->dd_reinject = DVR_REINJECT_L2; + } + else + { + dd->dd_reinject = DVR_REINJECT_L3; + } + /* * enable the reinject into L2 path feature on the interface */ @@ -167,6 +180,23 @@ VNET_SW_INTERFACE_ADD_DEL_FUNCTION( dvr_dpo_interface_delete); #ifndef CLIB_MARCH_VARIANT +static u8* +format_dvr_reinject (u8* s, va_list *ap) +{ + dvr_dpo_reinject_t ddr = va_arg(*ap, int); + + switch (ddr) + { + case DVR_REINJECT_L2: + s = format (s, "l2"); + break; + case DVR_REINJECT_L3: + s = format (s, "l3"); + break; + } + return (s); +} + static u8* format_dvr_dpo (u8* s, va_list *ap) { @@ -175,10 +205,12 @@ format_dvr_dpo (u8* s, va_list *ap) vnet_main_t * vnm = vnet_get_main(); dvr_dpo_t *dd = dvr_dpo_get(index); - return (format(s, "dvr-%U-dpo", + return (format(s, "%U-dvr-%U-dpo %U", + format_dpo_proto, dd->dd_proto, format_vnet_sw_interface_name, vnm, - vnet_get_sw_interface(vnm, dd->dd_sw_if_index))); + vnet_get_sw_interface(vnm, dd->dd_sw_if_index), + format_dvr_reinject, dd->dd_reinject)); } static void @@ -300,6 +332,7 @@ dvr_dpo_inline (vlib_main_t * vm, vnet_buffer(b1)->l2.l2_len = vnet_buffer(b1)->ip.save_rewrite_length = len1; + b0->flags |= VNET_BUFFER_F_IS_DVR; b1->flags |= VNET_BUFFER_F_IS_DVR; @@ -430,7 +463,8 @@ VLIB_REGISTER_NODE (ip6_dvr_dpo_node) = { typedef enum dvr_reinject_next_t_ { - DVR_REINJECT_OUTPUT = 0, + DVR_REINJECT_NEXT_L2, + DVR_REINJECT_NEXT_L3, } dvr_reinject_next_t; always_inline uword @@ -454,8 +488,9 @@ dvr_reinject_inline (vlib_main_t * vm, while (n_left_from >= 4 && n_left_to_next > 2) { dvr_reinject_next_t next0, next1; + const dvr_dpo_t *dd0, *dd1; + u32 bi0, bi1, ddi0, ddi1; vlib_buffer_t *b0, *b1; - u32 bi0, bi1; bi0 = from[0]; to_next[0] = bi0; @@ -470,12 +505,24 @@ dvr_reinject_inline (vlib_main_t * vm, b1 = vlib_get_buffer (vm, bi1); if (b0->flags & VNET_BUFFER_F_IS_DVR) - next0 = DVR_REINJECT_OUTPUT; + { + ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; + dd0 = dvr_dpo_get(ddi0); + next0 = (dd0->dd_reinject == DVR_REINJECT_L2 ? + DVR_REINJECT_NEXT_L2 : + DVR_REINJECT_NEXT_L3); + } else vnet_feature_next( &next0, b0); if (b1->flags & VNET_BUFFER_F_IS_DVR) - next1 = DVR_REINJECT_OUTPUT; + { + ddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX]; + dd1 = dvr_dpo_get(ddi1); + next1 = (dd1->dd_reinject == DVR_REINJECT_L2 ? + DVR_REINJECT_NEXT_L2 : + DVR_REINJECT_NEXT_L3); + } else vnet_feature_next( &next1, b1); @@ -502,8 +549,9 @@ dvr_reinject_inline (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { dvr_reinject_next_t next0; + const dvr_dpo_t *dd0; vlib_buffer_t * b0; - u32 bi0; + u32 bi0, ddi0; bi0 = from[0]; to_next[0] = bi0; @@ -515,7 +563,13 @@ dvr_reinject_inline (vlib_main_t * vm, b0 = vlib_get_buffer (vm, bi0); if (b0->flags & VNET_BUFFER_F_IS_DVR) - next0 = DVR_REINJECT_OUTPUT; + { + ddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; + dd0 = dvr_dpo_get(ddi0); + next0 = (dd0->dd_reinject == DVR_REINJECT_L2 ? + DVR_REINJECT_NEXT_L2 : + DVR_REINJECT_NEXT_L3); + } else vnet_feature_next( &next0, b0); @@ -556,7 +610,8 @@ VLIB_REGISTER_NODE (ip4_dvr_reinject_node) = { .n_next_nodes = 1, .next_nodes = { - [DVR_REINJECT_OUTPUT] = "l2-output", + [DVR_REINJECT_NEXT_L2] = "l2-output", + [DVR_REINJECT_NEXT_L3] = "interface-output", }, }; @@ -567,7 +622,8 @@ VLIB_REGISTER_NODE (ip6_dvr_reinject_node) = { .n_next_nodes = 1, .next_nodes = { - [DVR_REINJECT_OUTPUT] = "l2-output", + [DVR_REINJECT_NEXT_L2] = "l2-output", + [DVR_REINJECT_NEXT_L3] = "interface-output", }, }; diff --git a/src/vnet/dpo/dvr_dpo.h b/src/vnet/dpo/dvr_dpo.h index 669c49201c8..4fef2811b10 100644 --- a/src/vnet/dpo/dvr_dpo.h +++ b/src/vnet/dpo/dvr_dpo.h @@ -18,6 +18,15 @@ #include +/** + * Control how the reinject is performed + */ +typedef enum dvr_dpo_reinject_t_ +{ + DVR_REINJECT_L2, + DVR_REINJECT_L3, +} __clib_packed dvr_dpo_reinject_t; + /** * @brief * The DVR DPO. Used as the resolving object for a DVR route. @@ -39,12 +48,20 @@ typedef struct dvr_dpo_t_ */ dpo_proto_t dd_proto; + /** + * Control for how the re-inject is performed + */ + dvr_dpo_reinject_t dd_reinject; + /** * number of locks. */ u16 dd_locks; } dvr_dpo_t; +/* 8 bytes is a factor of cache line size so this struct will never span */ +STATIC_ASSERT_SIZEOF(dvr_dpo_t, 8); + extern void dvr_dpo_add_or_lock (u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo); -- cgit 1.2.3-korg