bond: ping fails between l2 BD [VPP-1238]
[vpp.git] / src / vnet / bonding / cli.c
index b2d66f9..3ee99a5 100644 (file)
@@ -29,6 +29,7 @@ bond_disable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
   uword p;
 
   bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
+  clib_spinlock_lock_if_init (&bif->lockp);
   vec_foreach_index (i, bif->active_slaves)
   {
     p = *vec_elt_at_index (bif->active_slaves, i);
@@ -39,6 +40,7 @@ bond_disable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
        break;
       }
   }
+  clib_spinlock_unlock_if_init (&bif->lockp);
 }
 
 void
@@ -47,12 +49,14 @@ bond_enable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
   bond_if_t *bif;
 
   bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
+  clib_spinlock_lock_if_init (&bif->lockp);
   if (!hash_get (bif->active_slave_by_sw_if_index, sif->sw_if_index))
     {
       hash_set (bif->active_slave_by_sw_if_index, sif->sw_if_index,
                sif->sw_if_index);
       vec_add1 (bif->active_slaves, sif->sw_if_index);
     }
+  clib_spinlock_unlock_if_init (&bif->lockp);
 }
 
 int
@@ -131,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,
@@ -149,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);
@@ -171,6 +184,9 @@ bond_delete_if (vlib_main_t * vm, u32 sw_if_index)
   slave_if_t *sif;
   vnet_hw_interface_t *hw;
   u32 *sif_sw_if_index;
+  u32 thread_index;
+  u32 **s_list = 0;
+  u32 i;
 
   hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
   if (hw == NULL || bond_dev_class.index != hw->dev_class_index)
@@ -180,11 +196,20 @@ bond_delete_if (vlib_main_t * vm, u32 sw_if_index)
 
   vec_foreach (sif_sw_if_index, bif->slaves)
   {
-    sif = bond_get_slave_by_sw_if_index (*sif_sw_if_index);
-    if (sif)
-      bond_delete_neighbor (vm, bif, sif);
+    vec_add1 (s_list, sif_sw_if_index);
   }
 
+  for (i = 0; i < vec_len (s_list); i++)
+    {
+      sif_sw_if_index = s_list[i];
+      sif = bond_get_slave_by_sw_if_index (*sif_sw_if_index);
+      if (sif)
+       bond_delete_neighbor (vm, bif, sif);
+    }
+
+  if (s_list)
+    vec_free (s_list);
+
   /* bring down the interface */
   vnet_hw_interface_set_flags (vnm, bif->hw_if_index, 0);
   vnet_sw_interface_set_flags (vnm, bif->sw_if_index, 0);
@@ -193,6 +218,12 @@ bond_delete_if (vlib_main_t * vm, u32 sw_if_index)
 
   clib_bitmap_free (bif->port_number_bitmap);
   hash_unset (bm->bond_by_sw_if_index, bif->sw_if_index);
+  for (thread_index = 0; thread_index < vlib_get_thread_main ()->n_vlib_mains;
+       thread_index++)
+    {
+      vec_free (bif->per_thread_info[thread_index].frame);
+    }
+  vec_free (bif->per_thread_info);
   memset (bif, 0, sizeof (*bif));
   pool_put (bm->interfaces, bif);
 
@@ -265,6 +296,11 @@ bond_create_if (vlib_main_t * vm, bond_create_if_args_t * args)
   sw = vnet_get_hw_sw_interface (vnm, bif->hw_if_index);
   bif->sw_if_index = sw->sw_if_index;
   bif->group = bif->sw_if_index;
+  vec_validate_aligned (bif->per_thread_info,
+                       vlib_get_thread_main ()->n_vlib_mains - 1,
+                       CLIB_CACHE_LINE_BYTES);
+  if (vlib_get_thread_main ()->n_vlib_mains > 1)
+    clib_spinlock_init (&bif->lockp);
 
   vnet_hw_interface_set_flags (vnm, bif->hw_if_index,
                               VNET_HW_INTERFACE_FLAG_LINK_UP);
@@ -379,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);
@@ -396,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 =
@@ -427,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
@@ -440,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);
@@ -463,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)
     {
@@ -489,12 +534,10 @@ enslave_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
   args.group = ~0;
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
-      if (unformat (line_input, "interface %U",
+      if (unformat (line_input, "%U %U",
+                   unformat_vnet_sw_interface, vnm, &args.group,
                    unformat_vnet_sw_interface, vnm, &args.slave))
        ;
-      else if (unformat (line_input, "to %U", unformat_vnet_sw_interface, vnm,
-                        &args.group))
-       ;
       else if (unformat (line_input, "passive"))
        args.is_passive = 1;
       else if (unformat (line_input, "long-timeout"))
@@ -513,7 +556,7 @@ enslave_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
   if (args.group == ~0)
     return clib_error_return (0, "Missing bond interface");
   if (args.slave == ~0)
-    return clib_error_return (0, "please specify valid interface name");
+    return clib_error_return (0, "please specify valid slave interface name");
 
   bond_enslave (vm, &args);
 
@@ -522,8 +565,9 @@ enslave_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
 
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (enslave_interface_command, static) = {
-  .path = "enslave",
-  .short_help = "enslave interface <interface> to <BondEthernetx> [passive] [long-timeout]",
+  .path = "bond add",
+  .short_help = "bond add <BondEthernetx> <slave-interface> "
+                "[passive] [long-timeout]",
   .function = enslave_interface_command_fn,
 };
 /* *INDENT-ON* */
@@ -560,7 +604,7 @@ detach_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
   args.slave = ~0;
   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     {
-      if (unformat (line_input, "interface %U",
+      if (unformat (line_input, "%U",
                    unformat_vnet_sw_interface, vnm, &args.slave))
        ;
       else
@@ -575,7 +619,7 @@ detach_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
   if (args.error)
     return args.error;
   if (args.slave == ~0)
-    return clib_error_return (0, "please specify valid interface name");
+    return clib_error_return (0, "please specify valid slave interface name");
 
   bond_detach_slave (vm, &args);
 
@@ -584,8 +628,8 @@ detach_interface_command_fn (vlib_main_t * vm, unformat_input_t * input,
 
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (detach_interface_command, static) = {
-  .path = "detach",
-  .short_help = "detach interface <interface>",
+  .path = "bond del",
+  .short_help = "bond del <slave-interface>",
   .function = detach_interface_command_fn,
 };
 /* *INDENT-ON* */