bond: ping fails between l2 BD [VPP-1238] 29/11729/2
authorSteven <sluong@cisco.com>
Fri, 13 Apr 2018 02:36:19 +0000 (19:36 -0700)
committerDamjan Marion <dmarion.lists@gmail.com>
Fri, 13 Apr 2018 08:49:08 +0000 (08:49 +0000)
In dpdk based bonding, when the bond interface is configured for l2,
it automatically sets the bond interface to promiscuous mode and sets rx
redirect to ethernet-input. This allows traffic to be bridged to
non compute node facing interface when it is received from the compute
node interface.

For native vpp bonding, we need to do similar things. When the bond interface
is configured for l2, we set the slave interfaces to promiscuous mode
and set rx redirect to ethernet-input because dpdk does not know anything
about the bond interface. Likewise, when a new interface is enslaved, we also
need to do the same thing if the bond interface has already been configured
for l2.

Change-Id: I7e168008e8a4221be74929b2a20e6db0ce8f3110
Signed-off-by: Steven <sluong@cisco.com>
src/vnet/bonding/cli.c
src/vnet/bonding/device.c
src/vnet/interface.h
src/vnet/l2/l2_input.c

index 1768912..3ee99a5 100644 (file)
@@ -135,7 +135,10 @@ bond_delete_neighbor (vlib_main_t * vm, bond_if_t * bif, slave_if_t * sif)
   bond_main_t *bm = &bond_main;
   vnet_main_t *vnm = vnet_get_main ();
   int i;
-  vnet_hw_interface_t *hw;
+  vnet_hw_interface_t *sif_hw, *bif_hw;
+
+  sif_hw = vnet_get_sup_hw_interface (vnm, sif->sw_if_index);
+  bif_hw = vnet_get_sup_hw_interface (vnm, bif->sw_if_index);
 
   bif->port_number_bitmap =
     clib_bitmap_set (bif->port_number_bitmap,
@@ -153,11 +156,17 @@ bond_delete_neighbor (vlib_main_t * vm, bond_if_t * bif, slave_if_t * sif)
       }
   }
 
+  if (bif_hw->l2_if_count)
+    {
+      ethernet_set_flags (vnm, sif_hw->hw_if_index, 0);
+      /* Allow ip packets to go directly to ip4-input etc */
+      ethernet_set_rx_redirect (vnm, sif_hw, 0);
+    }
+
   bond_disable_collecting_distributing (vm, sif);
 
   /* Put back the old mac */
-  hw = vnet_get_sup_hw_interface (vnm, sif->sw_if_index);
-  vnet_hw_interface_change_mac_address (vnm, hw->hw_if_index,
+  vnet_hw_interface_change_mac_address (vnm, sif_hw->hw_if_index,
                                        sif->persistent_hw_address);
 
   pool_put (bm->neighbors, sif);
@@ -406,7 +415,7 @@ bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args)
   bond_if_t *bif;
   slave_if_t *sif;
   vnet_interface_main_t *im = &vnm->interface_main;
-  vnet_hw_interface_t *hw, *hw2;
+  vnet_hw_interface_t *bif_hw, *sif_hw;
   vnet_sw_interface_t *sw;
 
   bif = bond_get_master_by_sw_if_index (args->group);
@@ -423,8 +432,8 @@ bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args)
       args->error = clib_error_return (0, "interface was already enslaved");
       return;
     }
-  hw = vnet_get_sup_hw_interface (vnm, args->slave);
-  if (hw->dev_class_index == bond_dev_class.index)
+  sif_hw = vnet_get_sup_hw_interface (vnm, args->slave);
+  if (sif_hw->dev_class_index == bond_dev_class.index)
     {
       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
       args->error =
@@ -454,12 +463,14 @@ bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args)
            sif - bm->neighbors);
   vec_add1 (bif->slaves, sif->sw_if_index);
 
-  hw = vnet_get_sup_hw_interface (vnm, sif->sw_if_index);
+  sif_hw = vnet_get_sup_hw_interface (vnm, sif->sw_if_index);
+
   /* Save the old mac */
-  memcpy (sif->persistent_hw_address, hw->hw_address, 6);
+  memcpy (sif->persistent_hw_address, sif_hw->hw_address, 6);
+  bif_hw = vnet_get_sup_hw_interface (vnm, bif->sw_if_index);
   if (bif->use_custom_mac)
     {
-      vnet_hw_interface_change_mac_address (vnm, hw->hw_if_index,
+      vnet_hw_interface_change_mac_address (vnm, sif_hw->hw_if_index,
                                            bif->hw_address);
     }
   else
@@ -467,19 +478,26 @@ bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args)
       // bond interface gets the mac address from the first slave
       if (vec_len (bif->slaves) == 1)
        {
-         memcpy (bif->hw_address, hw->hw_address, 6);
-         hw2 = vnet_get_sup_hw_interface (vnm, bif->sw_if_index);
-         vnet_hw_interface_change_mac_address (vnm, hw2->hw_if_index,
-                                               hw->hw_address);
+         memcpy (bif->hw_address, sif_hw->hw_address, 6);
+         vnet_hw_interface_change_mac_address (vnm, bif_hw->hw_if_index,
+                                               sif_hw->hw_address);
        }
       else
        {
          // subsequent slaves gets the mac address of the bond interface
-         vnet_hw_interface_change_mac_address (vnm, hw->hw_if_index,
+         vnet_hw_interface_change_mac_address (vnm, sif_hw->hw_if_index,
                                                bif->hw_address);
        }
     }
 
+  if (bif_hw->l2_if_count)
+    {
+      ethernet_set_flags (vnm, sif_hw->hw_if_index,
+                         ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);
+      /* ensure all packets go to ethernet-input */
+      ethernet_set_rx_redirect (vnm, sif_hw, 1);
+    }
+
   if ((bif->mode == BOND_MODE_LACP) && bm->lacp_enable_disable)
     {
       (*bm->lacp_enable_disable) (vm, bif, sif, 1);
@@ -490,7 +508,7 @@ bond_enslave (vlib_main_t * vm, bond_enslave_args_t * args)
     }
 
   args->rv = vnet_feature_enable_disable ("device-input", "bond-input",
-                                         hw->hw_if_index, 1, 0, 0);
+                                         sif_hw->hw_if_index, 1, 0, 0);
 
   if (args->rv)
     {
index e3c454b..a275240 100644 (file)
@@ -73,6 +73,48 @@ format_bond_interface_name (u8 * s, va_list * args)
   return s;
 }
 
+static __clib_unused clib_error_t *
+bond_set_l2_mode_function (vnet_main_t * vnm,
+                          struct vnet_hw_interface_t *bif_hw,
+                          i32 l2_if_adjust)
+{
+  bond_if_t *bif;
+  u32 *sw_if_index;
+  struct vnet_hw_interface_t *sif_hw;
+
+  bif = bond_get_master_by_sw_if_index (bif_hw->sw_if_index);
+  if (!bif)
+    return 0;
+
+  if ((bif_hw->l2_if_count == 1) && (l2_if_adjust == 1))
+    {
+      /* Just added first L2 interface on this port */
+      vec_foreach (sw_if_index, bif->slaves)
+      {
+       sif_hw = vnet_get_sup_hw_interface (vnm, *sw_if_index);
+       ethernet_set_flags (vnm, sif_hw->hw_if_index,
+                           ETHERNET_INTERFACE_FLAG_ACCEPT_ALL);
+
+       /* ensure all packets go to ethernet-input */
+       ethernet_set_rx_redirect (vnm, sif_hw, 1);
+      }
+    }
+  else if ((bif_hw->l2_if_count == 0) && (l2_if_adjust == -1))
+    {
+      /* Just removed last L2 subinterface on this port */
+      vec_foreach (sw_if_index, bif->slaves)
+      {
+       sif_hw = vnet_get_sup_hw_interface (vnm, *sw_if_index);
+       ethernet_set_flags (vnm, sif_hw->hw_if_index, 0);
+
+       /* Allow ip packets to go directly to ip4-input etc */
+       ethernet_set_rx_redirect (vnm, sif_hw, 0);
+      }
+    }
+
+  return 0;
+}
+
 static __clib_unused clib_error_t *
 bond_subif_add_del_function (vnet_main_t * vnm, u32 hw_if_index,
                             struct vnet_sw_interface_t *st, int is_add)
@@ -640,6 +682,7 @@ VNET_DEVICE_CLASS (bond_dev_class) = {
   .tx_function_n_errors = BOND_TX_N_ERROR,
   .tx_function_error_strings = bond_tx_error_strings,
   .format_device_name = format_bond_interface_name,
+  .set_l2_mode_function = bond_set_l2_mode_function,
   .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,
index c8cda6b..7556bc5 100644 (file)
@@ -76,6 +76,11 @@ typedef clib_error_t *(vnet_interface_set_rx_mode_function_t)
   (struct vnet_main_t * vnm, u32 if_index, u32 queue_id,
    vnet_hw_interface_rx_mode mode);
 
+/* Interface set l2 mode callback. */
+typedef clib_error_t *(vnet_interface_set_l2_mode_function_t)
+  (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi,
+   i32 l2_if_adjust);
+
 typedef enum vnet_interface_function_priority_t_
 {
   VNET_ITF_FUNC_PRIORITY_LOW,
@@ -165,6 +170,9 @@ typedef struct _vnet_device_class
   /* Function to call interface rx mode is changed */
   vnet_interface_set_rx_mode_function_t *rx_mode_change_function;
 
+  /* Function to call interface l2 mode is changed */
+  vnet_interface_set_l2_mode_function_t *set_l2_mode_function;
+
   /* Redistribute flag changes/existence of this interface class. */
   u32 redistribute;
 
index c2df5ac..d8a0a6b 100644 (file)
@@ -564,6 +564,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /*           */
   l2_bridge_domain_t *bd_config;
   i32 l2_if_adjust = 0;
   u32 slot;
+  vnet_device_class_t *dev_class;
 
   hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);
   config = l2input_intf_config (sw_if_index);
@@ -798,6 +799,12 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main,        /*           */
   /* Set up the L2/L3 flag in the interface parsing tables */
   ethernet_sw_interface_set_l2_mode (vnm, sw_if_index, (mode != MODE_L3));
 
+  dev_class = vnet_get_device_class (vnet_main, hi->dev_class_index);
+  if (dev_class->set_l2_mode_function)
+    {
+      dev_class->set_l2_mode_function (vnet_main, hi, l2_if_adjust);
+    }
+
   return 0;
 }