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 <jdl@netgate.com>
This commit is contained in:
@ -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";
|
||||
|
@ -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 */
|
||||
|
@ -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] [<interface> [<interface> [..]]] [verbose]",
|
||||
.short_help = "show interface [address|addr|features|feat|vtr] [<interface> [<interface> [..]]] [verbose]",
|
||||
.function = show_sw_interfaces,
|
||||
.is_mp_safe = 1,
|
||||
};
|
||||
|
@ -41,6 +41,42 @@
|
||||
#include <vppinfra/bitmap.h>
|
||||
#include <vnet/l2/l2_input.h>
|
||||
#include <vnet/l2/l2_output.h>
|
||||
#include <vnet/l2/l2_vtr.h>
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user