Enhance CLI/API Support for Bonded Interface 86/686/2
authorJohn Lo <loj@cisco.com>
Tue, 5 Apr 2016 19:47:43 +0000 (15:47 -0400)
committerGerrit Code Review <gerrit@fd.io>
Thu, 7 Apr 2016 14:33:05 +0000 (14:33 +0000)
For interfaces which are slave links to a bounded interface, do not
allow sub-interface creation nor interface state to be changed.
Change "show interface" to display interface state as "bond-slave"
for slave links to a bonded interface.
Change "show hardware" to support a "bond" keyword and display slave
links to a bonded interface.

Change-Id: I4db3cae6985bcb1489ab16a07c72c5ee9b2f2dd3
Signed-off-by: John Lo <loj@cisco.com>
vnet/vnet/api_errno.h
vnet/vnet/devices/dpdk/init.c
vnet/vnet/interface.c
vnet/vnet/interface.h
vnet/vnet/interface_cli.c
vnet/vnet/interface_format.c
vpp/api/api.c

index 69535d3..e59efd7 100644 (file)
@@ -69,7 +69,8 @@ _(TUNNEL_EXIST, -75, "Tunnel already exists")                           \
 _(INVALID_DECAP_NEXT, -76, "Invalid decap-next")                       \
 _(RESPONSE_NOT_READY, -77, "Response not ready")                       \
 _(NOT_CONNECTED, -78, "Not connected to the data plane")                \
-_(IF_ALREADY_EXISTS, -79, "Interface already exists")
+_(IF_ALREADY_EXISTS, -79, "Interface already exists")                   \
+_(BOND_SLAVE_NOT_ALLOWED, -80, "Operation not allowed on slave of BondEthernet")
 
 typedef enum {
 #define _(a,b,c) VNET_API_ERROR_##a = (b),
index e84f0de..822b05d 100644 (file)
@@ -16,6 +16,7 @@
 #include <vppinfra/vec.h>
 #include <vppinfra/error.h>
 #include <vppinfra/format.h>
+#include <vppinfra/bitmap.h>
 
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/devices/dpdk/dpdk.h>
@@ -1622,23 +1623,34 @@ dpdk_process (vlib_main_t * vm,
              u8  slink[16];
              int nlink = rte_eth_bond_slaves_get(i, slink, 16);
              if (nlink > 0) {
-                 vnet_hw_interface_t * hi;
-                 ethernet_interface_t * ei;
+                 vnet_hw_interface_t * bhi;
+                 ethernet_interface_t * bei;
                  /* Get MAC of 1st slave link */
                  rte_eth_macaddr_get(slink[0], (struct ether_addr *)addr);
                  /* Set MAC of bounded interface to that of 1st slave link */
                  rte_eth_bond_mac_address_set(i, (struct ether_addr *)addr);
                  /* Populate MAC of bonded interface in VPP hw tables */
-                 hi = vnet_get_hw_interface (
+                 bhi = vnet_get_hw_interface(
                      vnm, dm->devices[i].vlib_hw_if_index);
-                 ei = pool_elt_at_index (em->interfaces, hi->hw_instance);
-                 memcpy (hi->hw_address, addr, 6);
-                 memcpy (ei->address, addr, 6);
-                 /* Add MAC to other slave links */
-                 while (nlink > 1) {
-                     nlink--;
-                     rte_eth_dev_mac_addr_add(
-                         slink[nlink], (struct ether_addr *)addr, 0);
+                 bei = pool_elt_at_index(em->interfaces, bhi->hw_instance);
+                 memcpy(bhi->hw_address, addr, 6);
+                 memcpy(bei->address, addr, 6);
+                 while (nlink >= 1) { /* for all slave links */
+                     int slave = slink[--nlink];
+                     dpdk_device_t * sdev = &dm->devices[slave];
+                     vnet_hw_interface_t * shi;
+                     vnet_sw_interface_t * ssi;
+                     /* Add MAC to all slave links except the first one */
+                     if (nlink) rte_eth_dev_mac_addr_add(
+                         slave, (struct ether_addr *)addr, 0);
+                     /* Set slaves bitmap for bonded interface */
+                     bhi->bond_info = clib_bitmap_set(
+                         bhi->bond_info, sdev->vlib_hw_if_index, 1);
+                     /* Set slave link flags on slave interface */
+                     shi = vnet_get_hw_interface(vnm, sdev->vlib_hw_if_index);
+                     ssi = vnet_get_sw_interface(vnm, sdev->vlib_sw_if_index);
+                     shi->bond_info = VNET_HW_INTERFACE_BOND_INFO_SLAVE;
+                     ssi->flags |= VNET_SW_INTERFACE_FLAG_BOND_SLAVE;
                  }
              }
          }
index 6c8823f..9189a41 100644 (file)
@@ -363,6 +363,15 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, u32 flag
            }
        }
 
+      /* Donot change state for slave link of bonded interfaces */
+      if (si->flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE)
+        {
+         error = clib_error_return 
+             (0, "not allowed as %U belong to a BondEthernet interface",
+              format_vnet_sw_interface_name, vnm, si);
+         goto done;
+        }
+
       /* Already in the desired state? */
       if ((si->flags & mask) == flags)
        goto done;
index 1ddd259..fdf23a6 100644 (file)
@@ -311,6 +311,15 @@ typedef struct vnet_hw_interface_t {
 
   /* Count of number of L2 subinterfaces */
   u32 l2_if_count;
+
+  /* Bonded interface info -
+     0       - not a bonded interface nor a slave
+     ~0      - slave to a bonded interface
+     others  - A bonded interface with a pointer to bitmap for all slaves */
+  uword *bond_info;
+#define VNET_HW_INTERFACE_BOND_INFO_NONE ((uword *) 0)
+#define VNET_HW_INTERFACE_BOND_INFO_SLAVE ((uword *) ~0)
+
 } vnet_hw_interface_t;
 
 typedef enum {
@@ -364,6 +373,8 @@ typedef struct {
 
 #define VNET_SW_INTERFACE_FLAG_UNNUMBERED (1 << 3)
 
+#define VNET_SW_INTERFACE_FLAG_BOND_SLAVE (1 << 4)
+
   /* Index for this interface. */
   u32 sw_if_index;
 
index 94fb391..3b3da9b 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <vnet/vnet.h>
 #include <vnet/ip/ip.h>
+#include <vppinfra/bitmap.h>
 
 static int compare_interface_names (void *a1, void *a2)
 {
@@ -58,28 +59,21 @@ show_or_clear_hw_interfaces (vlib_main_t * vm,
   vnet_interface_main_t * im = &vnm->interface_main;
   vnet_hw_interface_t * hi;
   u32 hw_if_index, * hw_if_indices = 0;
-  int i, verbose = 1, is_show;
+  int i, verbose = -1, is_show, show_bond = 0;
 
   is_show = strstr (cmd->path, "show") != 0;
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
       /* See if user wants to show a specific interface. */
       if (unformat (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
-       {
          vec_add1 (hw_if_indices, hw_if_index);
-         /* Implies verbose. */
-         verbose = 1;
-       }
+
       /* See if user wants to show an interface with a specific hw_if_index. */
       else if (unformat (input, "%u", &hw_if_index))
-       {
          vec_add1 (hw_if_indices, hw_if_index);
-         /* Implies verbose. */
-         verbose = 1;
-       }
 
       else if (unformat (input, "verbose"))
-       verbose = 1;
+         verbose = 1; /* this is also the default */
 
       else if (unformat (input, "detail"))
        verbose = 2;
@@ -87,6 +81,12 @@ show_or_clear_hw_interfaces (vlib_main_t * vm,
       else if (unformat (input, "brief"))
        verbose = 0;
 
+      else if (unformat (input, "bond"))
+      {
+       show_bond = 1;
+       if (verbose < 0) verbose = 0; /* default to brief for link bonding */
+      }
+
       else
        {
          error = clib_error_return (0, "unknown input `%U'",
@@ -100,6 +100,8 @@ show_or_clear_hw_interfaces (vlib_main_t * vm,
     pool_foreach (hi, im->hw_interfaces,
                  vec_add1 (hw_if_indices, hi - im->hw_interfaces));
 
+  if (verbose < 0) verbose = 1; /* default to verbose (except bond) */
+
   if (is_show)
     {
       /* Sort by name. */
@@ -109,7 +111,23 @@ show_or_clear_hw_interfaces (vlib_main_t * vm,
       for (i = 0; i < vec_len (hw_if_indices); i++)
        {
          hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
-         vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, hi, verbose);
+         if (show_bond == 0) /* show all interfaces */
+             vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, 
+                              hi, verbose);
+         else if ((hi->bond_info) && 
+                  (hi->bond_info != VNET_HW_INTERFACE_BOND_INFO_SLAVE))
+           { /* show only bonded interface and all its slave interfaces */
+             int hw_idx;
+             vnet_hw_interface_t * shi;
+             vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, 
+                              hi, verbose);
+             clib_bitmap_foreach (hw_idx, hi->bond_info,
+               ({
+                 shi = vnet_get_hw_interface(vnm, hw_idx);
+                 vlib_cli_output (vm, "%U\n", 
+                                  format_vnet_hw_interface, vnm, shi, verbose);
+               }));
+           }
        }
     }
   else
@@ -133,7 +151,7 @@ show_or_clear_hw_interfaces (vlib_main_t * vm,
 
 VLIB_CLI_COMMAND (show_hw_interfaces_command, static) = {
   .path = "show hardware-interfaces",
-  .short_help = "show hardware-interfaces [verbose|brief]  [<if-name1> <if-name2> ...]",
+  .short_help = "show hardware-interfaces [brief|verbose|detail] [bond] [<if-name1> <if-name2> ...]",
   .function = show_or_clear_hw_interfaces,
 };
 
@@ -556,6 +574,13 @@ create_sub_interfaces (vlib_main_t * vm,
   */
 
   hi = vnet_get_hw_interface (vnm, hw_if_index);
+
+  if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) {
+    error = clib_error_return (
+       0, "not allowed as %v belong to a BondEthernet interface", hi->name);
+    goto done;
+  }
+
   for (id = id_min; id <= id_max; id++)
     {
       uword * p;
index 1ebbfb1..840e72b 100644 (file)
  */
 
 #include <vnet/vnet.h>
+#include <vppinfra/bitmap.h>
 
 u8 * format_vnet_sw_interface_flags (u8 * s, va_list * args)
 {
   u32 flags = va_arg (*args, u32);
 
-  s = format (s, "%s", (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "down");
-  if (flags & VNET_SW_INTERFACE_FLAG_PUNT)
-    s = format (s, "/punt");
+  if (flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE) 
+    s = format (s, "bond-slave");
+  else 
+    {
+      s = format (s, "%s", 
+                 (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "down");
+      if (flags & VNET_SW_INTERFACE_FLAG_PUNT) 
+       s = format (s, "/punt");
+    }
 
   return s;
 }
@@ -65,14 +72,24 @@ u8 * format_vnet_hw_interface (u8 * s, va_list * args)
 
   indent = format_get_indent (s);
 
-  s = format (s, "%-32v%=6d%=8s",
-             hi->name, hi->hw_if_index,
-             hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP ? "up" : "down");
+  s = format (s, "%-32v%=6d", hi->name, hi->hw_if_index);
+
+  if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
+    s = format (s, "%=8s", "slave");
+  else
+    s = format (s, "%=8s", 
+               hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP ? "up" : "down");
 
   hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
   dev_class = vnet_get_device_class (vnm, hi->dev_class_index);
 
-  if (dev_class->format_device_name)  
+  if (hi->bond_info && (hi->bond_info != VNET_HW_INTERFACE_BOND_INFO_SLAVE)) 
+    {
+      int hw_idx;
+      s = format (s, "Slave-Idx:");
+      clib_bitmap_foreach (hw_idx, hi->bond_info, format(s, " %d", hw_idx));
+    }
+  else if (dev_class->format_device_name)  
     s = format (s, "%U", dev_class->format_device_name, hi->dev_instance);
   else
     s = format (s, "%s%d", dev_class->name, hi->dev_instance);
index 9867b59..aaa4be5 100644 (file)
@@ -1859,6 +1859,11 @@ vl_api_create_subif_t_handler (vl_api_create_subif_t * mp)
     si = vnet_get_sup_sw_interface (vnm, ntohl(mp->sw_if_index));
     hi = vnet_get_sup_hw_interface (vnm, ntohl(mp->sw_if_index));
 
+    if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) {
+         rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED;
+       goto out;
+    }
+
     sw_if_index = si->sw_if_index;
     sub_id = ntohl(mp->sub_id);