MTU: Software interface / Per-protocol MTU support
[vpp.git] / src / vnet / interface_cli.c
index e5efb1f..264c1f3 100644 (file)
@@ -270,36 +270,47 @@ show_sw_interfaces (vlib_main_t * vm,
 {
   clib_error_t *error = 0;
   vnet_main_t *vnm = vnet_get_main ();
+  unformat_input_t _linput, *linput = &_linput;
   vnet_interface_main_t *im = &vnm->interface_main;
   vnet_sw_interface_t *si, *sorted_sis = 0;
   u32 sw_if_index = ~(u32) 0;
   u8 show_addresses = 0;
   u8 show_features = 0;
   u8 show_tag = 0;
+  int verbose = 0;
 
-  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+  /*
+   * Get a line of input. Won't work if the user typed
+   * "show interface" and nothing more.
+   */
+  if (unformat_user (input, unformat_line_input, linput))
     {
-      /* See if user wants to show specific interface */
-      if (unformat
-         (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
-       {
-         si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
-         vec_add1 (sorted_sis, si[0]);
-       }
-      else if (unformat (input, "address") || unformat (input, "addr"))
-       show_addresses = 1;
-      else if (unformat (input, "features") || unformat (input, "feat"))
-       show_features = 1;
-      else if (unformat (input, "tag"))
-       show_tag = 1;
-      else
+      while (unformat_check_input (linput) != UNFORMAT_END_OF_INPUT)
        {
-         error = clib_error_return (0, "unknown input `%U'",
-                                    format_unformat_error, input);
-         goto done;
+         /* See if user wants to show specific interface */
+         if (unformat
+             (linput, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
+           {
+             si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
+             vec_add1 (sorted_sis, si[0]);
+           }
+         else if (unformat (linput, "address") || unformat (linput, "addr"))
+           show_addresses = 1;
+         else if (unformat (linput, "features") || unformat (linput, "feat"))
+           show_features = 1;
+         else if (unformat (linput, "tag"))
+           show_tag = 1;
+         else if (unformat (linput, "verbose"))
+           verbose = 1;
+         else
+           {
+             error = clib_error_return (0, "unknown input `%U'",
+                                        format_unformat_error, linput);
+             goto done;
+           }
        }
+      unformat_free (linput);
     }
-
   if (show_features || show_tag)
     {
       if (sw_if_index == ~(u32) 0)
@@ -308,7 +319,7 @@ show_sw_interfaces (vlib_main_t * vm,
 
   if (show_features)
     {
-      vnet_interface_features_show (vm, sw_if_index);
+      vnet_interface_features_show (vm, sw_if_index, verbose);
 
       l2_input_config_t *l2_input = l2input_intf_config (sw_if_index);
       u32 fb = l2_input->feature_bitmap;
@@ -344,14 +355,14 @@ show_sw_interfaces (vlib_main_t * vm,
       sorted_sis =
        vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
       _vec_len (sorted_sis) = 0;
-      pool_foreach (si, im->sw_interfaces, (
-                                            {
-                                            int visible =
-                                            vnet_swif_is_api_visible (si);
-                                            if (visible)
-                                            vec_add1 (sorted_sis, si[0]);}
-                   ));
-
+      /* *INDENT-OFF* */
+      pool_foreach (si, im->sw_interfaces,
+      ({
+        int visible = vnet_swif_is_api_visible (si);
+        if (visible)
+          vec_add1 (sorted_sis, si[0]);}
+        ));
+      /* *INDENT-ON* */
       /* Sort by name. */
       vec_sort_with_function (sorted_sis, sw_interface_name_compare);
     }
@@ -365,11 +376,7 @@ show_sw_interfaces (vlib_main_t * vm,
        ip_lookup_main_t *lm4 = &im4->lookup_main;
        ip_lookup_main_t *lm6 = &im6->lookup_main;
        ip_interface_address_t *ia = 0;
-       ip4_address_t *r4;
-       ip6_address_t *r6;
        u32 fib_index4 = 0, fib_index6 = 0;
-       ip4_fib_t *fib4;
-       ip6_fib_t *fib6;
 
        if (vec_len (im4->fib_index_by_sw_if_index) > si->sw_if_index)
          fib_index4 = vec_elt (im4->fib_index_by_sw_if_index,
@@ -379,85 +386,69 @@ show_sw_interfaces (vlib_main_t * vm,
          fib_index6 = vec_elt (im6->fib_index_by_sw_if_index,
                                si->sw_if_index);
 
-       fib4 = ip4_fib_get (fib_index4);
-       fib6 = ip6_fib_get (fib_index6);
+       ip4_fib_t *fib4 = ip4_fib_get (fib_index4);
+       ip6_fib_t *fib6 = ip6_fib_get (fib_index6);
 
        if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
          vlib_cli_output
            (vm, "%U (%s): \n  unnumbered, use %U",
-            format_vnet_sw_if_index_name,
-            vnm, si->sw_if_index,
+            format_vnet_sw_if_index_name, vnm, si->sw_if_index,
             (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn",
             format_vnet_sw_if_index_name, vnm, si->unnumbered_sw_if_index);
-
        else
-         {
-           vlib_cli_output (vm, "%U (%s):",
-                            format_vnet_sw_if_index_name,
-                            vnm, si->sw_if_index,
-                            (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
-                            ? "up" : "dn");
-         }
+         vlib_cli_output
+           (vm, "%U (%s):",
+            format_vnet_sw_if_index_name, vnm, si->sw_if_index,
+            (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn");
 
        /* Display any L2 info */
        l2_input_config_t *l2_input = l2input_intf_config (si->sw_if_index);
        if (l2_input->bridge)
          {
+           bd_main_t *bdm = &bd_main;
            u32 bd_id = l2input_main.bd_configs[l2_input->bd_index].bd_id;
-           vlib_cli_output (vm, "  l2 bridge bd_id %d%s%d", bd_id,
-                            l2_input->bvi ? " bvi shg " : " shg ",
-                            l2_input->shg);
+           vlib_cli_output (vm, "  L2 bridge bd-id %d idx %d shg %d %s",
+                            bd_id, bd_find_index (bdm, bd_id), l2_input->shg,
+                            l2_input->bvi ? "bvi" : " ");
          }
        else if (l2_input->xconnect)
-         {
-           vlib_cli_output (vm, "  l2 xconnect %U",
-                            format_vnet_sw_if_index_name,
-                            vnm, l2_input->output_sw_if_index);
-         }
+         vlib_cli_output (vm, "  L2 xconnect %U",
+                          format_vnet_sw_if_index_name, vnm,
+                          l2_input->output_sw_if_index);
 
+       /* *INDENT-OFF* */
        /* Display any IP4 addressing info */
-          /* *INDENT-OFF* */
-         foreach_ip_interface_address (lm4, ia, si->sw_if_index,
-                                       1 /* honor unnumbered */,
-         ({
-            r4 = ip_interface_address_get_address (lm4, ia);
-            if (fib4->table_id)
-              {
-                vlib_cli_output (vm, "  %U/%d table %d",
-                                 format_ip4_address, r4,
-                                 ia->address_length,
-                                 fib4->table_id);
-              }
-            else
-              {
-                vlib_cli_output (vm, "  %U/%d",
-                                 format_ip4_address, r4,
-                                 ia->address_length);
-              }
-          }));
-          /* *INDENT-ON* */
-
+       foreach_ip_interface_address (lm4, ia, si->sw_if_index,
+                                     1 /* honor unnumbered */,
+       ({
+         ip4_address_t *r4 = ip_interface_address_get_address (lm4, ia);
+         if (fib4->table_id)
+           vlib_cli_output (vm, "  L3 %U/%d ip4 table-id %d fib-idx %d",
+                            format_ip4_address, r4, ia->address_length,
+                            fib4->table_id,
+                            ip4_fib_index_from_table_id (fib4->table_id));
+         else
+           vlib_cli_output (vm, "  L3 %U/%d",
+                            format_ip4_address, r4, ia->address_length);
+        }));
+       /* *INDENT-ON* */
+
+       /* *INDENT-OFF* */
        /* Display any IP6 addressing info */
-          /* *INDENT-OFF* */
-          foreach_ip_interface_address (lm6, ia, si->sw_if_index,
-                                        1 /* honor unnumbered */,
-          ({
-            r6 = ip_interface_address_get_address (lm6, ia);
-            if (fib6->table_id)
-              {
-                vlib_cli_output (vm, "  %U/%d table %d",
-                                 format_ip6_address, r6,
-                                 ia->address_length,
-                                 fib6->table_id);
-              }
-            else
-              {
-                vlib_cli_output (vm, "  %U/%d",
-                                 format_ip6_address, r6,
-                                 ia->address_length);
-              }
-          }));
-          /* *INDENT-ON* */
+       foreach_ip_interface_address (lm6, ia, si->sw_if_index,
+                                     1 /* honor unnumbered */,
+        ({
+         ip6_address_t *r6 = ip_interface_address_get_address (lm6, ia);
+         if (fib6->table_id)
+           vlib_cli_output (vm, "  L3 %U/%d ip6 table-id %d fib-idx %d",
+                            format_ip6_address, r6, ia->address_length,
+                            fib6->table_id,
+                            ip6_fib_index_from_table_id (fib6->table_id));
+         else
+           vlib_cli_output (vm, "  L3 %U/%d",
+                            format_ip6_address, r6, ia->address_length);
+        }));
+       /* *INDENT-ON* */
       }
     }
   else
@@ -476,7 +467,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> [..]]]",
+  .short_help = "show interface [address|addr|features|feat] [<interface> [<interface> [..]]] [verbose]",
   .function = show_sw_interfaces,
 };
 /* *INDENT-ON* */
@@ -954,60 +945,32 @@ set_unnumbered (vlib_main_t * vm,
                unformat_input_t * input, vlib_cli_command_t * cmd)
 {
   vnet_main_t *vnm = vnet_get_main ();
-  u32 unnumbered_sw_if_index;
-  u32 inherit_from_sw_if_index;
-  vnet_sw_interface_t *si;
-  int is_set = 0;
-  int is_del = 0;
-  u32 was_unnum;
+  u32 unnumbered_sw_if_index = ~0;
+  u32 inherit_from_sw_if_index = ~0;
+  int enable = 1;
 
   if (unformat (input, "%U use %U",
                unformat_vnet_sw_interface, vnm, &unnumbered_sw_if_index,
                unformat_vnet_sw_interface, vnm, &inherit_from_sw_if_index))
-    is_set = 1;
+    enable = 1;
   else if (unformat (input, "del %U",
                     unformat_vnet_sw_interface, vnm,
                     &unnumbered_sw_if_index))
-    is_del = 1;
+    enable = 0;
   else
     return clib_error_return (0, "parse error '%U'",
                              format_unformat_error, input);
 
-  si = vnet_get_sw_interface (vnm, unnumbered_sw_if_index);
-  was_unnum = (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED);
+  if (~0 == unnumbered_sw_if_index)
+    return clib_error_return (0, "Specify the unnumbered interface");
+  if (enable && ~0 == inherit_from_sw_if_index)
+    return clib_error_return (0, "When enabling unnumberered specify the"
+                             " IP enabled interface that it uses");
 
-  if (is_del)
-    {
-      si->flags &= ~(VNET_SW_INTERFACE_FLAG_UNNUMBERED);
-      si->unnumbered_sw_if_index = (u32) ~ 0;
+  vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
+                                      inherit_from_sw_if_index, enable);
 
-      ip4_main.lookup_main.if_address_pool_index_by_sw_if_index
-       [unnumbered_sw_if_index] = ~0;
-      ip6_main.lookup_main.if_address_pool_index_by_sw_if_index
-       [unnumbered_sw_if_index] = ~0;
-    }
-  else if (is_set)
-    {
-      si->flags |= VNET_SW_INTERFACE_FLAG_UNNUMBERED;
-      si->unnumbered_sw_if_index = inherit_from_sw_if_index;
-
-      ip4_main.lookup_main.if_address_pool_index_by_sw_if_index
-       [unnumbered_sw_if_index] =
-       ip4_main.lookup_main.if_address_pool_index_by_sw_if_index
-       [inherit_from_sw_if_index];
-      ip6_main.lookup_main.if_address_pool_index_by_sw_if_index
-       [unnumbered_sw_if_index] =
-       ip6_main.lookup_main.if_address_pool_index_by_sw_if_index
-       [inherit_from_sw_if_index];
-    }
-
-  if (was_unnum != (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
-    {
-      ip4_sw_interface_enable_disable (unnumbered_sw_if_index, !is_del);
-      ip6_sw_interface_enable_disable (unnumbered_sw_if_index, !is_del);
-    }
-
-  return 0;
+  return (NULL);
 }
 
 /* *INDENT-OFF* */
@@ -1151,13 +1114,17 @@ static clib_error_t *
 mtu_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
 {
   vnet_main_t *vnm = vnet_get_main ();
-  u32 hw_if_index, mtu;
-  u32 flags = ETHERNET_INTERFACE_FLAG_MTU;
+  u32 hw_if_index, sw_if_index, mtu;
   ethernet_main_t *em = &ethernet_main;
+  u32 mtus[VNET_N_MTU] = { 0, 0, 0, 0 };
 
   if (unformat (input, "%d %U", &mtu,
                unformat_vnet_hw_interface, vnm, &hw_if_index))
     {
+      /*
+       * Change physical MTU on interface. Only supported for Ethernet
+       * interfaces
+       */
       vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
       ethernet_interface_t *eif = ethernet_get_interface (em, hw_if_index);
 
@@ -1173,22 +1140,36 @@ mtu_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
        return clib_error_return (0, "Invalid mtu (%d): must be <= (%d)", mtu,
                                  hi->max_supported_packet_bytes);
 
-      if (hi->max_packet_bytes != mtu)
-       {
-         hi->max_packet_bytes = mtu;
-         ethernet_set_flags (vnm, hw_if_index, flags);
-       }
+      vnet_hw_interface_set_mtu (vnm, hw_if_index, mtu);
+      goto done;
     }
+  else if (unformat (input, "packet %d %U", &mtu,
+                    unformat_vnet_sw_interface, vnm, &sw_if_index))
+    /* Set default packet MTU (including L3 header */
+    mtus[VNET_MTU_L3] = mtu;
+  else if (unformat (input, "ip4 %d %U", &mtu,
+                    unformat_vnet_sw_interface, vnm, &sw_if_index))
+    mtus[VNET_MTU_IP4] = mtu;
+  else if (unformat (input, "ip6 %d %U", &mtu,
+                    unformat_vnet_sw_interface, vnm, &sw_if_index))
+    mtus[VNET_MTU_IP6] = mtu;
+  else if (unformat (input, "mpls %d %U", &mtu,
+                    unformat_vnet_sw_interface, vnm, &sw_if_index))
+    mtus[VNET_MTU_MPLS] = mtu;
   else
     return clib_error_return (0, "unknown input `%U'",
                              format_unformat_error, input);
+
+  vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, mtus);
+
+done:
   return 0;
 }
 
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (set_interface_mtu_cmd, static) = {
   .path = "set interface mtu",
-  .short_help = "set interface mtu <value> <interface>",
+  .short_help = "set interface mtu [packet|ip4|ip6|mpls] <value> <interface>",
   .function = mtu_cmd,
 };
 /* *INDENT-ON* */
@@ -1201,7 +1182,7 @@ set_interface_mac_address (vlib_main_t * vm, unformat_input_t * input,
   vnet_sw_interface_t *si = NULL;
   clib_error_t *error = 0;
   u32 sw_if_index = ~0;
-  u64 mac = 0;
+  u8 mac[6] = { 0 };
 
   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     {
@@ -1209,7 +1190,7 @@ set_interface_mac_address (vlib_main_t * vm, unformat_input_t * input,
                                 format_unformat_error, input);
       goto done;
     }
-  if (!unformat_user (input, unformat_ethernet_address, &mac))
+  if (!unformat_user (input, unformat_ethernet_address, mac))
     {
       error = clib_error_return (0, "expected mac address `%U'",
                                 format_unformat_error, input);