interface: Allow VLAN tag-rewrite on non-sub-interfaces too. 45/23345/6
authorJon Loeliger <jdl@netgate.com>
Fri, 8 Nov 2019 21:05:23 +0000 (15:05 -0600)
committerOle Trøan <otroan@employees.org>
Tue, 12 Nov 2019 20:37:55 +0000 (20:37 +0000)
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>
src/vnet/interface.api
src/vnet/interface_api.c
src/vnet/interface_cli.c
src/vnet/interface_format.c
src/vnet/interface_funcs.h
src/vnet/l2/l2_bd.c
test/test_vtr.py

index efc5bb4..39bb9ca 100644 (file)
@@ -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";
index 3b0c515..0dad168 100644 (file)
@@ -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 */
index a66e157..9de674a 100644 (file)
@@ -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,
 };
index 69f481c..507e267 100644 (file)
 #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)
index 9241b34..388a438 100644 (file)
@@ -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
 {
index 207ef4d..e54d437 100644 (file)
@@ -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)
 {
index 239767a..c3704f1 100644 (file)
@@ -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)