bonding lacp: replace slave string with member
[vpp.git] / src / vnet / bonding / node.c
index df2da5c..d49894f 100644 (file)
 #include <vnet/snap/snap.h>
 #include <vnet/bonding/node.h>
 
+#ifndef CLIB_MARCH_VARIANT
 bond_main_t bond_main;
+#endif /* CLIB_MARCH_VARIANT */
 
 #define foreach_bond_input_error \
   _(NONE, "no error")            \
   _(IF_DOWN, "interface down")   \
+  _(PASSIVE_IF, "traffic received on passive interface")   \
   _(PASS_THRU, "pass through (CDP, LLDP, slow protocols)")
 
 typedef enum
@@ -36,7 +39,6 @@ typedef enum
     BOND_INPUT_N_ERROR,
 } bond_input_error_t;
 
-#ifndef CLIB_MULTIARCH_VARIANT
 static char *bond_input_error_strings[] = {
 #define _(n,s) s,
   foreach_bond_input_error
@@ -60,14 +62,12 @@ format_bond_input_trace (u8 * s, va_list * args)
 
   return s;
 }
-#endif
-
 
 typedef enum
 {
   BOND_INPUT_NEXT_DROP,
   BOND_INPUT_N_NEXT,
-} l2output_next_t;
+} bond_output_next_t;
 
 static_always_inline u8
 packet_is_cdp (ethernet_header_t * eth)
@@ -85,14 +85,17 @@ packet_is_cdp (ethernet_header_t * eth)
           (snap->oui[2] == 0x0C)));
 }
 
-static inline u32
+static inline void
 bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node,
-                       vlib_buffer_t * b, u32 bond_sw_if_index)
+                       vlib_buffer_t * b, u32 bond_sw_if_index,
+                       u32 * n_rx_packets, u32 * n_rx_bytes)
 {
   u16 *ethertype_p, ethertype;
   ethernet_vlan_header_t *vlan;
   ethernet_header_t *eth = (ethernet_header_t *) vlib_buffer_get_current (b);
 
+  (*n_rx_packets)++;
+  *n_rx_bytes += b->current_length;
   ethertype = clib_mem_unaligned (&eth->type, u16);
   if (!ethernet_frame_is_tagged (ntohs (ethertype)))
     {
@@ -103,7 +106,7 @@ bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node,
        {
          /* Change the physical interface to bond interface */
          vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index;
-         return 1;
+         return;
        }
     }
   else
@@ -123,70 +126,87 @@ bond_sw_if_idx_rewrite (vlib_main_t * vm, vlib_node_runtime_t * node,
        {
          /* Change the physical interface to bond interface */
          vnet_buffer (b)->sw_if_index[VLIB_RX] = bond_sw_if_index;
-         return 1;
+         return;
        }
     }
 
   vlib_error_count (vm, node->node_index, BOND_INPUT_ERROR_PASS_THRU, 1);
-  return 0;
+  return;
 }
 
 static inline void
 bond_update_next (vlib_main_t * vm, vlib_node_runtime_t * node,
-                 u32 * last_slave_sw_if_index, u32 slave_sw_if_index,
-                 u32 packet_count,
+                 u32 * last_member_sw_if_index, u32 member_sw_if_index,
                  u32 * bond_sw_if_index, vlib_buffer_t * b,
                  u32 * next_index, vlib_error_t * error)
 {
-  u16 thread_index = vlib_get_thread_index ();
-  slave_if_t *sif;
+  member_if_t *mif;
   bond_if_t *bif;
 
-  if (PREDICT_TRUE (*last_slave_sw_if_index == slave_sw_if_index))
-    return;
+  *next_index = BOND_INPUT_NEXT_DROP;
+  *error = 0;
 
-  if (packet_count)
-    vlib_increment_simple_counter (vnet_main.interface_main.sw_if_counters +
-                                  VNET_INTERFACE_COUNTER_RX, thread_index,
-                                  *last_slave_sw_if_index, packet_count);
+  if (PREDICT_TRUE (*last_member_sw_if_index == member_sw_if_index))
+    goto next;
 
-  *last_slave_sw_if_index = slave_sw_if_index;
-  *next_index = BOND_INPUT_NEXT_DROP;
+  *last_member_sw_if_index = member_sw_if_index;
 
-  sif = bond_get_slave_by_sw_if_index (slave_sw_if_index);
-  ASSERT (sif);
+  mif = bond_get_member_by_sw_if_index (member_sw_if_index);
+  ALWAYS_ASSERT (mif);
 
-  bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
+  bif = bond_get_bond_if_by_dev_instance (mif->bif_dev_instance);
 
-  ASSERT (bif);
-  ASSERT (vec_len (bif->slaves));
+  ALWAYS_ASSERT (bif);
+  ASSERT (vec_len (bif->members));
 
-  if (PREDICT_TRUE (bif->admin_up == 0))
+  if (PREDICT_FALSE (bif->admin_up == 0))
     {
-      *bond_sw_if_index = slave_sw_if_index;
+      *bond_sw_if_index = member_sw_if_index;
       *error = node->errors[BOND_INPUT_ERROR_IF_DOWN];
     }
 
+  if (PREDICT_FALSE ((bif->mode == BOND_MODE_ACTIVE_BACKUP) &&
+                    vec_len (bif->active_members) &&
+                    (member_sw_if_index != bif->active_members[0])))
+    {
+      *bond_sw_if_index = member_sw_if_index;
+      *error = node->errors[BOND_INPUT_ERROR_PASSIVE_IF];
+      return;
+    }
+
   *bond_sw_if_index = bif->sw_if_index;
-  *error = 0;
-  vnet_feature_next ( /* not used */ 0, next_index, b);
+
+next:
+  vnet_feature_next (next_index, b);
+}
+
+static_always_inline void
+bond_update_next_x4 (vlib_buffer_t * b0, vlib_buffer_t * b1,
+                    vlib_buffer_t * b2, vlib_buffer_t * b3)
+{
+  u32 tmp0, tmp1, tmp2, tmp3;
+
+  tmp0 = tmp1 = tmp2 = tmp3 = BOND_INPUT_NEXT_DROP;
+  vnet_feature_next (&tmp0, b0);
+  vnet_feature_next (&tmp1, b1);
+  vnet_feature_next (&tmp2, b2);
+  vnet_feature_next (&tmp3, b3);
 }
 
-uword CLIB_CPU_OPTIMIZED
-CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
-                                  vlib_node_runtime_t * node,
-                                  vlib_frame_t * frame)
+VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm,
+                               vlib_node_runtime_t * node,
+                               vlib_frame_t * frame)
 {
-  u16 thread_index = vlib_get_thread_index ();
+  u16 thread_index = vm->thread_index;
   u32 *from, n_left;
   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
   u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index;
   u16 nexts[VLIB_FRAME_SIZE], *next;
-  u32 last_slave_sw_if_index = ~0;
+  u32 last_member_sw_if_index = ~0;
   u32 bond_sw_if_index = 0;
   vlib_error_t error = 0;
   u32 next_index = 0;
-  u32 cnt = 0;
+  u32 n_rx_bytes = 0, n_rx_packets = 0;
 
   /* Vector of buffer / pkt indices we're supposed to process */
   from = vlib_frame_vector_args (frame);
@@ -206,14 +226,10 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
       /* Prefetch next iteration */
       if (PREDICT_TRUE (n_left >= 16))
        {
-         CLIB_PREFETCH (vlib_buffer_get_current (b[8]),
-                        CLIB_CACHE_LINE_BYTES, LOAD);
-         CLIB_PREFETCH (vlib_buffer_get_current (b[9]),
-                        CLIB_CACHE_LINE_BYTES, LOAD);
-         CLIB_PREFETCH (vlib_buffer_get_current (b[10]),
-                        CLIB_CACHE_LINE_BYTES, LOAD);
-         CLIB_PREFETCH (vlib_buffer_get_current (b[11]),
-                        CLIB_CACHE_LINE_BYTES, LOAD);
+         vlib_prefetch_buffer_data (b[8], LOAD);
+         vlib_prefetch_buffer_data (b[9], LOAD);
+         vlib_prefetch_buffer_data (b[10], LOAD);
+         vlib_prefetch_buffer_data (b[11], LOAD);
 
          vlib_prefetch_buffer_header (b[12], LOAD);
          vlib_prefetch_buffer_header (b[13], LOAD);
@@ -226,13 +242,29 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
       sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_RX];
       sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_RX];
 
-      x |= sw_if_index[0] ^ last_slave_sw_if_index;
-      x |= sw_if_index[1] ^ last_slave_sw_if_index;
-      x |= sw_if_index[2] ^ last_slave_sw_if_index;
-      x |= sw_if_index[3] ^ last_slave_sw_if_index;
+      x |= sw_if_index[0] ^ last_member_sw_if_index;
+      x |= sw_if_index[1] ^ last_member_sw_if_index;
+      x |= sw_if_index[2] ^ last_member_sw_if_index;
+      x |= sw_if_index[3] ^ last_member_sw_if_index;
 
       if (PREDICT_TRUE (x == 0))
        {
+         /*
+          * Optimize to call update_next only if there is a feature arc
+          * after bond-input. Test feature count greater than 1 because
+          * bond-input itself is a feature arc for this member interface.
+          */
+         ASSERT ((vnet_buffer (b[0])->feature_arc_index ==
+                  vnet_buffer (b[1])->feature_arc_index) &&
+                 (vnet_buffer (b[0])->feature_arc_index ==
+                  vnet_buffer (b[2])->feature_arc_index) &&
+                 (vnet_buffer (b[0])->feature_arc_index ==
+                  vnet_buffer (b[3])->feature_arc_index));
+         if (PREDICT_FALSE (vnet_get_feature_count
+                            (vnet_buffer (b[0])->feature_arc_index,
+                             last_member_sw_if_index) > 1))
+           bond_update_next_x4 (b[0], b[1], b[2], b[3]);
+
          next[0] = next[1] = next[2] = next[3] = next_index;
          if (next_index == BOND_INPUT_NEXT_DROP)
            {
@@ -243,54 +275,57 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
            }
          else
            {
-             cnt +=
-               bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index);
-             cnt +=
-               bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index);
-             cnt +=
-               bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index);
-             cnt +=
-               bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index);
+             bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index,
+                                     &n_rx_packets, &n_rx_bytes);
+             bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index,
+                                     &n_rx_packets, &n_rx_bytes);
+             bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index,
+                                     &n_rx_packets, &n_rx_bytes);
+             bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index,
+                                     &n_rx_packets, &n_rx_bytes);
            }
        }
       else
        {
-
-         bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0],
-                           cnt, &bond_sw_if_index, b[0], &next_index,
-                           &error);
+         bond_update_next (vm, node, &last_member_sw_if_index,
+                           sw_if_index[0], &bond_sw_if_index, b[0],
+                           &next_index, &error);
          next[0] = next_index;
          if (next_index == BOND_INPUT_NEXT_DROP)
            b[0]->error = error;
          else
-           cnt += bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index);
+           bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index,
+                                   &n_rx_packets, &n_rx_bytes);
 
-         bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[1],
-                           cnt, &bond_sw_if_index, b[1], &next_index,
-                           &error);
+         bond_update_next (vm, node, &last_member_sw_if_index,
+                           sw_if_index[1], &bond_sw_if_index, b[1],
+                           &next_index, &error);
          next[1] = next_index;
          if (next_index == BOND_INPUT_NEXT_DROP)
            b[1]->error = error;
          else
-           cnt += bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index);
+           bond_sw_if_idx_rewrite (vm, node, b[1], bond_sw_if_index,
+                                   &n_rx_packets, &n_rx_bytes);
 
-         bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[2],
-                           cnt, &bond_sw_if_index, b[2], &next_index,
-                           &error);
+         bond_update_next (vm, node, &last_member_sw_if_index,
+                           sw_if_index[2], &bond_sw_if_index, b[2],
+                           &next_index, &error);
          next[2] = next_index;
          if (next_index == BOND_INPUT_NEXT_DROP)
            b[2]->error = error;
          else
-           cnt += bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index);
+           bond_sw_if_idx_rewrite (vm, node, b[2], bond_sw_if_index,
+                                   &n_rx_packets, &n_rx_bytes);
 
-         bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[3],
-                           cnt, &bond_sw_if_index, b[3], &next_index,
-                           &error);
+         bond_update_next (vm, node, &last_member_sw_if_index,
+                           sw_if_index[3], &bond_sw_if_index, b[3],
+                           &next_index, &error);
          next[3] = next_index;
          if (next_index == BOND_INPUT_NEXT_DROP)
            b[3]->error = error;
          else
-           cnt += bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index);
+           bond_sw_if_idx_rewrite (vm, node, b[3], bond_sw_if_index,
+                                   &n_rx_packets, &n_rx_bytes);
        }
 
       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
@@ -308,13 +343,14 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
   while (n_left)
     {
       sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
-      bond_update_next (vm, node, &last_slave_sw_if_index, sw_if_index[0],
-                       cnt, &bond_sw_if_index, b[0], &next_index, &error);
+      bond_update_next (vm, node, &last_member_sw_if_index, sw_if_index[0],
+                       &bond_sw_if_index, b[0], &next_index, &error);
       next[0] = next_index;
       if (next_index == BOND_INPUT_NEXT_DROP)
        b[0]->error = error;
       else
-       bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index);
+       bond_sw_if_idx_rewrite (vm, node, b[0], bond_sw_if_index,
+                               &n_rx_packets, &n_rx_bytes);
 
       VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b[0]);
 
@@ -330,35 +366,30 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
       n_left = frame->n_vectors;       /* number of packets to process */
       b = bufs;
       sw_if_index = sw_if_indices;
-      next = nexts;
       bond_packet_trace_t *t0;
-      uword n_trace = vlib_get_trace_count (vm, node);
 
-      while (n_left && n_trace)
+      while (n_left)
        {
          if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
            {
-             vlib_trace_buffer (vm, node, next[0], b[0],
-                                0 /* follow_chain */ );
-             vlib_set_trace_count (vm, node, --n_trace);
              t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0));
              t0->sw_if_index = sw_if_index[0];
-             clib_memcpy (&t0->ethernet, vlib_buffer_get_current (b[0]),
-                          sizeof (ethernet_header_t));
+             clib_memcpy_fast (&t0->ethernet, vlib_buffer_get_current (b[0]),
+                               sizeof (ethernet_header_t));
              t0->bond_sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
            }
          /* next */
          n_left--;
          b++;
          sw_if_index++;
-         next++;
        }
     }
 
   /* increase rx counters */
-  vlib_increment_simple_counter
-    (vnet_main.interface_main.sw_if_counters +
-     VNET_INTERFACE_COUNTER_RX, thread_index, bond_sw_if_index, cnt);
+  vlib_increment_combined_counter
+    (vnet_main.interface_main.combined_sw_if_counters +
+     VNET_INTERFACE_COUNTER_RX, thread_index, bond_sw_if_index, n_rx_packets,
+     n_rx_bytes);
 
   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
   vlib_node_increment_counter (vm, bond_input_node.index,
@@ -367,7 +398,6 @@ CLIB_MULTIARCH_FN (bond_input_fn) (vlib_main_t * vm,
   return frame->n_vectors;
 }
 
-#ifndef CLIB_MULTIARCH_VARIANT
 static clib_error_t *
 bond_input_init (vlib_main_t * vm)
 {
@@ -376,7 +406,6 @@ bond_input_init (vlib_main_t * vm)
 
 /* *INDENT-OFF* */
 VLIB_REGISTER_NODE (bond_input_node) = {
-  .function = bond_input_fn,
   .name = "bond-input",
   .vector_size = sizeof (u32),
   .format_buffer = format_ethernet_header_with_length,
@@ -391,20 +420,6 @@ VLIB_REGISTER_NODE (bond_input_node) = {
   }
 };
 
-#if __x86_64__
-vlib_node_function_t __clib_weak bond_input_fn_avx512;
-vlib_node_function_t __clib_weak bond_input_fn_avx2;
-static void __clib_constructor
-bond_input_multiarch_select (void)
-{
-  if (bond_input_fn_avx512 && clib_cpu_supports_avx512f ())
-    bond_input_node.function = bond_input_fn_avx512;
-  else if (bond_input_fn_avx2 && clib_cpu_supports_avx2 ())
-    bond_input_node.function = bond_input_fn_avx2;
-}
-#endif
-
-
 VLIB_INIT_FUNCTION (bond_input_init);
 
 VNET_FEATURE_INIT (bond_input, static) =
@@ -419,27 +434,22 @@ static clib_error_t *
 bond_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
 {
   bond_main_t *bm = &bond_main;
-  slave_if_t *sif;
+  member_if_t *mif;
   vlib_main_t *vm = bm->vlib_main;
 
-  sif = bond_get_slave_by_sw_if_index (sw_if_index);
-  if (sif)
+  mif = bond_get_member_by_sw_if_index (sw_if_index);
+  if (mif)
     {
-      sif->port_enabled = flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP;
-      if (sif->port_enabled == 0)
-       {
-         if (sif->lacp_enabled == 0)
-           {
-             bond_disable_collecting_distributing (vm, sif);
-           }
-       }
+      if (mif->lacp_enabled)
+       return 0;
+
+      /* port_enabled is both admin up and hw link up */
+      mif->port_enabled = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) &&
+                          vnet_sw_interface_is_link_up (vnm, sw_if_index));
+      if (mif->port_enabled == 0)
+       bond_disable_collecting_distributing (vm, mif);
       else
-       {
-         if (sif->lacp_enabled == 0)
-           {
-             bond_enable_collecting_distributing (vm, sif);
-           }
-       }
+       bond_enable_collecting_distributing (vm, mif);
     }
 
   return 0;
@@ -451,35 +461,31 @@ static clib_error_t *
 bond_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
 {
   bond_main_t *bm = &bond_main;
-  slave_if_t *sif;
+  member_if_t *mif;
   vnet_sw_interface_t *sw;
   vlib_main_t *vm = bm->vlib_main;
 
   sw = vnet_get_hw_sw_interface (vnm, hw_if_index);
-  sif = bond_get_slave_by_sw_if_index (sw->sw_if_index);
-  if (sif)
+  mif = bond_get_member_by_sw_if_index (sw->sw_if_index);
+  if (mif)
     {
-      if (!(flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
-       {
-         if (sif->lacp_enabled == 0)
-           {
-             bond_disable_collecting_distributing (vm, sif);
-           }
-       }
+      if (mif->lacp_enabled)
+       return 0;
+
+      /* port_enabled is both admin up and hw link up */
+      mif->port_enabled = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) &&
+                          vnet_sw_interface_is_admin_up (vnm,
+                                                         sw->sw_if_index));
+      if (mif->port_enabled == 0)
+       bond_disable_collecting_distributing (vm, mif);
       else
-       {
-         if (sif->lacp_enabled == 0)
-           {
-             bond_enable_collecting_distributing (vm, sif);
-           }
-       }
+       bond_enable_collecting_distributing (vm, mif);
     }
 
   return 0;
 }
 
 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bond_hw_interface_up_down);
-#endif
 
 /*
  * fd.io coding-style-patch-verification: ON