#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
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)
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)
{
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;
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;