From 9485d99bd3941b13abf7e47fc7e1d56f7b4fee55 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Fri, 8 Nov 2019 15:05:23 -0600 Subject: [PATCH] interface: Allow VLAN tag-rewrite on non-sub-interfaces too. This fix was first made in commit fdea5c6a00b74971dbb1b7ec4e25839a871006ca but was subsequently lost in commit 053204ab039d34a990ff0e14c32ce3b294fcce0e Added unit test for setting VTR on a non-sub-interface to help ensure no future regressions of this ability. Type: fix Change-Id: I71ce2684fb72383741455829ae2d397ea2e95eae Signed-off-by: Jon Loeliger --- src/vnet/interface.api | 2 +- src/vnet/interface_api.c | 36 ++++++++++++++++---------------- src/vnet/interface_cli.c | 28 +++++++++++++++++++++++-- src/vnet/interface_format.c | 36 ++++++++++++++++++++++++++++++++ src/vnet/interface_funcs.h | 3 +++ src/vnet/l2/l2_bd.c | 35 ------------------------------- test/test_vtr.py | 50 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 134 insertions(+), 56 deletions(-) diff --git a/src/vnet/interface.api b/src/vnet/interface.api index efc5bb487c9..39bb9ca0fcc 100644 --- a/src/vnet/interface.api +++ b/src/vnet/interface.api @@ -14,7 +14,7 @@ * limitations under the License. */ -option version = "3.2.1"; +option version = "3.2.2"; import "vnet/interface_types.api"; import "vnet/ethernet/ethernet_types.api"; diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index 3b0c515f013..0dad168203d 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -272,26 +272,26 @@ send_sw_interface_details (vpe_api_main_t * am, mp->sub_inner_vlan_id = ntohs (sub->eth.inner_vlan_id); mp->sub_if_flags = ntohl (sub->eth.raw_flags & SUB_IF_API_FLAG_MASK_VNET); + } - /* vlan tag rewrite data */ - u32 vtr_op = L2_VTR_DISABLED; - u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0; + /* vlan tag rewrite data */ + u32 vtr_op = L2_VTR_DISABLED; + u32 vtr_push_dot1q = 0, vtr_tag1 = 0, vtr_tag2 = 0; - if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index, - &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0) - { - // error - default to disabled - mp->vtr_op = ntohl (L2_VTR_DISABLED); - clib_warning ("cannot get vlan tag rewrite for sw_if_index %d", - swif->sw_if_index); - } - else - { - mp->vtr_op = ntohl (vtr_op); - mp->vtr_push_dot1q = ntohl (vtr_push_dot1q); - mp->vtr_tag1 = ntohl (vtr_tag1); - mp->vtr_tag2 = ntohl (vtr_tag2); - } + if (l2vtr_get (am->vlib_main, am->vnet_main, swif->sw_if_index, + &vtr_op, &vtr_push_dot1q, &vtr_tag1, &vtr_tag2) != 0) + { + // error - default to disabled + mp->vtr_op = ntohl (L2_VTR_DISABLED); + clib_warning ("cannot get vlan tag rewrite for sw_if_index %d", + swif->sw_if_index); + } + else + { + mp->vtr_op = ntohl (vtr_op); + mp->vtr_push_dot1q = ntohl (vtr_push_dot1q); + mp->vtr_tag1 = ntohl (vtr_tag1); + mp->vtr_tag2 = ntohl (vtr_tag2); } /* pbb tag rewrite data */ diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c index a66e1576bde..9de674a10fa 100644 --- a/src/vnet/interface_cli.c +++ b/src/vnet/interface_cli.c @@ -277,6 +277,7 @@ show_sw_interfaces (vlib_main_t * vm, u8 show_addresses = 0; u8 show_features = 0; u8 show_tag = 0; + u8 show_vtr = 0; int verbose = 0; /* @@ -300,6 +301,8 @@ show_sw_interfaces (vlib_main_t * vm, show_features = 1; else if (unformat (linput, "tag")) show_tag = 1; + else if (unformat (linput, "vtr")) + show_vtr = 1; else if (unformat (linput, "verbose")) verbose = 1; else @@ -312,7 +315,7 @@ show_sw_interfaces (vlib_main_t * vm, } unformat_free (linput); } - if (show_features || show_tag) + if (show_features || show_tag || show_vtr) { if (sw_if_index == ~(u32) 0) { @@ -353,6 +356,27 @@ show_sw_interfaces (vlib_main_t * vm, return 0; } + /* + * Show vlan tag rewrite data for one interface. + */ + if (show_vtr) + { + u32 vtr_op = L2_VTR_DISABLED; + u32 push_dot1q = 0, tag1 = 0, tag2 = 0; + + if (l2vtr_get (vm, vnm, sw_if_index, + &vtr_op, &push_dot1q, &tag1, &tag2) != 0) + { + vlib_cli_output (vm, "%U: Problem getting vlan tag-rewrite data", + format_vnet_sw_if_index_name, vnm, sw_if_index); + return 0; + } + vlib_cli_output (vm, "%U: VTR %0U", + format_vnet_sw_if_index_name, vnm, sw_if_index, + format_vtr, vtr_op, push_dot1q, tag1, tag2); + return 0; + } + if (!show_addresses) vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, 0); @@ -474,7 +498,7 @@ done: /* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sw_interfaces_command, static) = { .path = "show interface", - .short_help = "show interface [address|addr|features|feat] [ [ [..]]] [verbose]", + .short_help = "show interface [address|addr|features|feat|vtr] [ [ [..]]] [verbose]", .function = show_sw_interfaces, .is_mp_safe = 1, }; diff --git a/src/vnet/interface_format.c b/src/vnet/interface_format.c index 69f481c303d..507e2676ccb 100644 --- a/src/vnet/interface_format.c +++ b/src/vnet/interface_format.c @@ -41,6 +41,42 @@ #include #include #include +#include + +u8 * +format_vtr (u8 * s, va_list * args) +{ + u32 vtr_op = va_arg (*args, u32); + u32 dot1q = va_arg (*args, u32); + u32 tag1 = va_arg (*args, u32); + u32 tag2 = va_arg (*args, u32); + switch (vtr_op) + { + case L2_VTR_DISABLED: + return format (s, "none"); + case L2_VTR_PUSH_1: + return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); + case L2_VTR_PUSH_2: + return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1, + tag2); + case L2_VTR_POP_1: + return format (s, "pop-1"); + case L2_VTR_POP_2: + return format (s, "pop-2"); + case L2_VTR_TRANSLATE_1_1: + return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); + case L2_VTR_TRANSLATE_1_2: + return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", + tag1, tag2); + case L2_VTR_TRANSLATE_2_1: + return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); + case L2_VTR_TRANSLATE_2_2: + return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", + tag1, tag2); + default: + return format (s, "none"); + } +} u8 * format_vnet_sw_interface_flags (u8 * s, va_list * args) diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h index 9241b34d59d..388a438c02b 100644 --- a/src/vnet/interface_funcs.h +++ b/src/vnet/interface_funcs.h @@ -448,6 +448,9 @@ unformat_function_t unformat_vnet_hw_interface; unformat_function_t unformat_vnet_hw_interface_flags; unformat_function_t unformat_vnet_sw_interface_flags; +/* VLAN tag-rewrite */ +format_function_t format_vtr; + /* Node runtime for interface output function. */ typedef struct { diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c index 207ef4d6601..e54d437f0ea 100644 --- a/src/vnet/l2/l2_bd.c +++ b/src/vnet/l2/l2_bd.c @@ -994,41 +994,6 @@ VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = { }; /* *INDENT-ON* */ -static u8 * -format_vtr (u8 * s, va_list * args) -{ - u32 vtr_op = va_arg (*args, u32); - u32 dot1q = va_arg (*args, u32); - u32 tag1 = va_arg (*args, u32); - u32 tag2 = va_arg (*args, u32); - switch (vtr_op) - { - case L2_VTR_DISABLED: - return format (s, "none"); - case L2_VTR_PUSH_1: - return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); - case L2_VTR_PUSH_2: - return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1, - tag2); - case L2_VTR_POP_1: - return format (s, "pop-1"); - case L2_VTR_POP_2: - return format (s, "pop-2"); - case L2_VTR_TRANSLATE_1_1: - return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); - case L2_VTR_TRANSLATE_1_2: - return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", - tag1, tag2); - case L2_VTR_TRANSLATE_2_1: - return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); - case L2_VTR_TRANSLATE_2_2: - return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", - tag1, tag2); - default: - return format (s, "none"); - } -} - static u8 * format_uu_cfg (u8 * s, va_list * args) { diff --git a/test/test_vtr.py b/test/test_vtr.py index 239767a5d17..c3704f1e7b6 100644 --- a/test/test_vtr.py +++ b/test/test_vtr.py @@ -331,6 +331,56 @@ class TestVtr(VppTestCase): self.vtr_test(self.pg2, [Tag(dot1=DOT1AD, vlan=400), Tag(dot1=DOT1Q, vlan=300)]) + def test_if_vtr_disable(self): + """ Disable VTR on non-sub-interfaces + """ + # First set the VTR fields to junk + self.vapi.l2_interface_vlan_tag_rewrite( + sw_if_index=self.pg0.sw_if_index, vtr_op=L2_VTR_OP.L2_PUSH_2, + push_dot1q=1, tag1=19, tag2=630) + + if_state = self.vapi.sw_interface_dump( + sw_if_index=self.pg0.sw_if_index) + self.assertEqual(if_state[0].sw_if_index, self.pg0.sw_if_index) + self.assertNotEqual(if_state[0].vtr_op, L2_VTR_OP.L2_DISABLED) + + # Then ensure that a request to disable VTR is honored. + self.vapi.l2_interface_vlan_tag_rewrite( + sw_if_index=self.pg0.sw_if_index, vtr_op=L2_VTR_OP.L2_DISABLED) + + if_state = self.vapi.sw_interface_dump( + sw_if_index=self.pg0.sw_if_index) + self.assertEqual(if_state[0].sw_if_index, self.pg0.sw_if_index) + self.assertEqual(if_state[0].vtr_op, L2_VTR_OP.L2_DISABLED) + + def test_if_vtr_push_1q(self): + """ 1Q VTR push 1 on non-sub-interfaces + """ + self.vapi.l2_interface_vlan_tag_rewrite( + sw_if_index=self.pg0.sw_if_index, vtr_op=L2_VTR_OP.L2_PUSH_1, + push_dot1q=1, tag1=150) + + if_state = self.vapi.sw_interface_dump( + sw_if_index=self.pg0.sw_if_index) + self.assertEqual(if_state[0].sw_if_index, self.pg0.sw_if_index) + self.assertEqual(if_state[0].vtr_op, L2_VTR_OP.L2_PUSH_1) + self.assertEqual(if_state[0].vtr_tag1, 150) + self.assertNotEqual(if_state[0].vtr_push_dot1q, 0) + + def test_if_vtr_push_2ad(self): + """ 1AD VTR push 2 on non-sub-interfaces + """ + self.vapi.l2_interface_vlan_tag_rewrite( + sw_if_index=self.pg0.sw_if_index, vtr_op=L2_VTR_OP.L2_PUSH_2, + push_dot1q=0, tag1=450, tag2=350) + + if_state = self.vapi.sw_interface_dump( + sw_if_index=self.pg0.sw_if_index) + self.assertEqual(if_state[0].sw_if_index, self.pg0.sw_if_index) + self.assertEqual(if_state[0].vtr_op, L2_VTR_OP.L2_PUSH_2) + self.assertEqual(if_state[0].vtr_tag1, 450) # outer + self.assertEqual(if_state[0].vtr_tag2, 350) # inner + self.assertEqual(if_state[0].vtr_push_dot1q, 0) if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) -- 2.16.6