bonding: add/del secondary mac address callback 36/23436/5
authorMatthew Smith <mgsmith@netgate.com>
Thu, 14 Nov 2019 16:36:02 +0000 (10:36 -0600)
committerMatthew Smith <mgsmith@netgate.com>
Mon, 2 Dec 2019 18:20:24 +0000 (18:20 +0000)
Type: feature

Add a callback to the bond device class which allows a secondary
mac address to be added/deleted.

The desired operation is performed on all the hardware interfaces
which belong to the bond interface. This allows virtual MAC
addresses to be used on bond interfaces without requiring the
hardware interfaces to have promiscuous mode enabled.

When a hardware interface is added or removed from a bond, if there
are any secondary MAC addresses configured on the bond, they are
added or removed from the hardware interface.

Change-Id: If9488078b4d7869ecc56ef6853f3cc9891211860
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
src/vnet/bonding/cli.c
src/vnet/bonding/device.c

index 7e29d1d..554ffe9 100644 (file)
@@ -261,6 +261,31 @@ bond_dump_slave_ifs (slave_interface_details_t ** out_slaveifs,
   return 0;
 }
 
+/*
+ * Manage secondary mac addresses when attaching/detaching a slave.
+ * If adding, copies any secondary addresses from master to slave
+ * If deleting, deletes the master's secondary addresses from the slave
+ *
+ */
+static void
+bond_slave_add_del_mac_addrs (bond_if_t * bif, u32 sif_sw_if_index, u8 is_add)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  ethernet_interface_t *b_ei;
+  mac_address_t *sec_mac;
+  vnet_hw_interface_t *s_hwif;
+
+  b_ei = ethernet_get_interface (&ethernet_main, bif->hw_if_index);
+  if (!b_ei || !b_ei->secondary_addrs)
+    return;
+
+  s_hwif = vnet_get_sup_hw_interface (vnm, sif_sw_if_index);
+
+  vec_foreach (sec_mac, b_ei->secondary_addrs)
+    vnet_hw_interface_add_del_mac_address (vnm, s_hwif->hw_if_index,
+                                          sec_mac->bytes, is_add);
+}
+
 static void
 bond_delete_neighbor (vlib_main_t * vm, bond_if_t * bif, slave_if_t * sif)
 {
@@ -296,6 +321,10 @@ bond_delete_neighbor (vlib_main_t * vm, bond_if_t * bif, slave_if_t * sif)
   vnet_hw_interface_change_mac_address (vnm, sif_hw->hw_if_index,
                                        sif->persistent_hw_address);
 
+  /* delete the bond's secondary/virtual mac addrs from the slave */
+  bond_slave_add_del_mac_addrs (bif, sif->sw_if_index, 0 /* is_add */ );
+
+
   if ((bif->mode == BOND_MODE_LACP) && bm->lacp_enable_disable)
     (*bm->lacp_enable_disable) (vm, bif, sif, 0);
 
@@ -665,6 +694,9 @@ bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args)
        }
     }
 
+  /* if there are secondary/virtual mac addrs, propagate to the slave */
+  bond_slave_add_del_mac_addrs (bif, sif->sw_if_index, 1 /* is_add */ );
+
   if (bif_hw->l2_if_count)
     {
       ethernet_set_flags (vnm, sif_hw->hw_if_index,
index 21bbcb5..57f2806 100644 (file)
@@ -142,6 +142,50 @@ bond_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
   return 0;
 }
 
+static clib_error_t *
+bond_add_del_mac_address (vnet_hw_interface_t * hi, const u8 * address,
+                         u8 is_add)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  bond_if_t *bif;
+  clib_error_t *error = 0;
+  vnet_hw_interface_t *s_hi;
+  int i;
+
+
+  bif = bond_get_master_by_sw_if_index (hi->sw_if_index);
+  if (!bif)
+    {
+      return clib_error_return (0, "No bond master found for sw_if_index %u",
+                               hi->sw_if_index);
+    }
+
+  /* Add/del address on each slave hw intf, they control the hardware */
+  vec_foreach_index (i, bif->slaves)
+  {
+    s_hi = vnet_get_sup_hw_interface (vnm, vec_elt (bif->slaves, i));
+    error = vnet_hw_interface_add_del_mac_address (vnm, s_hi->hw_if_index,
+                                                  address, is_add);
+
+    if (error)
+      {
+       int j;
+
+       /* undo any that were completed before the failure */
+       for (j = i - 1; j > -1; j--)
+         {
+           s_hi = vnet_get_sup_hw_interface (vnm, vec_elt (bif->slaves, j));
+           vnet_hw_interface_add_del_mac_address (vnm, s_hi->hw_if_index,
+                                                  address, !(is_add));
+         }
+
+       return error;
+      }
+  }
+
+  return 0;
+}
+
 static_always_inline void
 bond_tx_add_to_queue (bond_per_thread_data_t * ptd, u32 port, u32 bi)
 {
@@ -807,6 +851,7 @@ VNET_DEVICE_CLASS (bond_dev_class) = {
   .admin_up_down_function = bond_interface_admin_up_down,
   .subif_add_del_function = bond_subif_add_del_function,
   .format_tx_trace = format_bond_tx_trace,
+  .mac_addr_add_del_function = bond_add_del_mac_address,
 };
 
 /* *INDENT-ON* */