bond: ping fails between l2 BD [VPP-1238]
[vpp.git] / src / vnet / bonding / device.c
index d4aa4a7..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)
@@ -103,16 +145,19 @@ bond_load_balance_broadcast (vlib_main_t * vm, vlib_node_runtime_t * node,
 {
   vnet_main_t *vnm = vnet_get_main ();
   vlib_buffer_t *c0;
-  int i;
+  int port;
   u32 *to_next = 0;
   u32 sw_if_index;
   vlib_frame_t *f;
+  u16 thread_index = vlib_get_thread_index ();
 
-
-  for (i = 1; i < slave_count; i++)
+  for (port = 1; port < slave_count; port++)
     {
-      sw_if_index = *vec_elt_at_index (bif->active_slaves, i);
-      f = vnet_get_frame_to_sw_interface (vnm, sw_if_index);
+      sw_if_index = *vec_elt_at_index (bif->active_slaves, port);
+      if (bif->per_thread_info[thread_index].frame[port] == 0)
+       bif->per_thread_info[thread_index].frame[port] =
+         vnet_get_frame_to_sw_interface (vnm, sw_if_index);
+      f = bif->per_thread_info[thread_index].frame[port];
       to_next = vlib_frame_vector_args (f);
       to_next += f->n_vectors;
       c0 = vlib_buffer_copy (vm, b0);
@@ -121,7 +166,6 @@ bond_load_balance_broadcast (vlib_main_t * vm, vlib_node_runtime_t * node,
          vnet_buffer (c0)->sw_if_index[VLIB_TX] = sw_if_index;
          to_next[0] = vlib_get_buffer_index (vm, c0);
          f->n_vectors++;
-         vnet_put_frame_to_sw_interface (vnm, sw_if_index, f);
        }
     }
 
@@ -638,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,