ip: Replace Sematics for Interface IP addresses
[vpp.git] / src / vnet / bonding / node.c
index 6fc7471..a606d20 100644 (file)
@@ -28,6 +28,7 @@ bond_main_t bond_main;
 #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
@@ -142,31 +143,56 @@ bond_update_next (vlib_main_t * vm, vlib_node_runtime_t * node,
   slave_if_t *sif;
   bond_if_t *bif;
 
+  *next_index = BOND_INPUT_NEXT_DROP;
+  *error = 0;
+
   if (PREDICT_TRUE (*last_slave_sw_if_index == slave_sw_if_index))
-    return;
+    goto next;
 
   *last_slave_sw_if_index = slave_sw_if_index;
-  *next_index = BOND_INPUT_NEXT_DROP;
 
   sif = bond_get_slave_by_sw_if_index (slave_sw_if_index);
-  ASSERT (sif);
+  ALWAYS_ASSERT (sif);
 
   bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
 
-  ASSERT (bif);
+  ALWAYS_ASSERT (bif);
   ASSERT (vec_len (bif->slaves));
 
-  if (PREDICT_TRUE (bif->admin_up == 0))
+  if (PREDICT_FALSE (bif->admin_up == 0))
     {
       *bond_sw_if_index = slave_sw_if_index;
       *error = node->errors[BOND_INPUT_ERROR_IF_DOWN];
     }
 
+  if (PREDICT_FALSE ((bif->mode == BOND_MODE_ACTIVE_BACKUP) &&
+                    vec_len (bif->active_slaves) &&
+                    (slave_sw_if_index != bif->active_slaves[0])))
+    {
+      *bond_sw_if_index = slave_sw_if_index;
+      *error = node->errors[BOND_INPUT_ERROR_PASSIVE_IF];
+      return;
+    }
+
   *bond_sw_if_index = bif->sw_if_index;
-  *error = 0;
+
+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);
+}
+
 VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm,
                                vlib_node_runtime_t * node,
                                vlib_frame_t * frame)
@@ -223,6 +249,22 @@ VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm,
 
       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 slave 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_slave_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)
            {
@@ -394,23 +436,16 @@ bond_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
   sif = bond_get_slave_by_sw_if_index (sw_if_index);
   if (sif)
     {
-      sif->port_enabled = flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP;
       if (sif->lacp_enabled)
        return 0;
 
+      /* port_enabled is both admin up and hw link up */
+      sif->port_enabled = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) &&
+                          vnet_sw_interface_is_link_up (vnm, sw_if_index));
       if (sif->port_enabled == 0)
-       {
-         bond_disable_collecting_distributing (vm, sif);
-       }
+       bond_disable_collecting_distributing (vm, sif);
       else
-       {
-         vnet_main_t *vnm = vnet_get_main ();
-         vnet_hw_interface_t *hw =
-           vnet_get_sup_hw_interface (vnm, sw_if_index);
-
-         if (hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
-           bond_enable_collecting_distributing (vm, sif);
-       }
+       bond_enable_collecting_distributing (vm, sif);
     }
 
   return 0;
@@ -433,14 +468,14 @@ bond_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
       if (sif->lacp_enabled)
        return 0;
 
-      if (!(flags & VNET_HW_INTERFACE_FLAG_LINK_UP))
-       {
-         bond_disable_collecting_distributing (vm, sif);
-       }
-      else if (sif->port_enabled)
-       {
-         bond_enable_collecting_distributing (vm, sif);
-       }
+      /* port_enabled is both admin up and hw link up */
+      sif->port_enabled = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) &&
+                          vnet_sw_interface_is_admin_up (vnm,
+                                                         sw->sw_if_index));
+      if (sif->port_enabled == 0)
+       bond_disable_collecting_distributing (vm, sif);
+      else
+       bond_enable_collecting_distributing (vm, sif);
     }
 
   return 0;