diff options
-rw-r--r-- | src/vnet/bonding/cli.c | 48 | ||||
-rw-r--r-- | src/vnet/bonding/device.c | 43 | ||||
-rw-r--r-- | src/vnet/interface.h | 8 | ||||
-rw-r--r-- | src/vnet/l2/l2_input.c | 7 |
4 files changed, 91 insertions, 15 deletions
diff --git a/src/vnet/bonding/cli.c b/src/vnet/bonding/cli.c index 1768912bf12..3ee99a51b62 100644 --- a/src/vnet/bonding/cli.c +++ b/src/vnet/bonding/cli.c @@ -135,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, @@ -153,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); @@ -406,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); @@ -423,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 = @@ -454,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 @@ -467,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); @@ -490,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) { diff --git a/src/vnet/bonding/device.c b/src/vnet/bonding/device.c index e3c454bbc72..a27524089aa 100644 --- a/src/vnet/bonding/device.c +++ b/src/vnet/bonding/device.c @@ -74,6 +74,48 @@ format_bond_interface_name (u8 * s, va_list * args) } 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) { @@ -640,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, diff --git a/src/vnet/interface.h b/src/vnet/interface.h index c8cda6b7814..7556bc5544e 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -76,6 +76,11 @@ typedef clib_error_t *(vnet_interface_set_rx_mode_function_t) (struct vnet_main_t * vnm, u32 if_index, u32 queue_id, vnet_hw_interface_rx_mode mode); +/* Interface set l2 mode callback. */ +typedef clib_error_t *(vnet_interface_set_l2_mode_function_t) + (struct vnet_main_t * vnm, struct vnet_hw_interface_t * hi, + i32 l2_if_adjust); + typedef enum vnet_interface_function_priority_t_ { VNET_ITF_FUNC_PRIORITY_LOW, @@ -165,6 +170,9 @@ typedef struct _vnet_device_class /* Function to call interface rx mode is changed */ vnet_interface_set_rx_mode_function_t *rx_mode_change_function; + /* Function to call interface l2 mode is changed */ + vnet_interface_set_l2_mode_function_t *set_l2_mode_function; + /* Redistribute flag changes/existence of this interface class. */ u32 redistribute; diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index c2df5acb3b2..d8a0a6bd798 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -564,6 +564,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ l2_bridge_domain_t *bd_config; i32 l2_if_adjust = 0; u32 slot; + vnet_device_class_t *dev_class; hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index); config = l2input_intf_config (sw_if_index); @@ -798,6 +799,12 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ /* Set up the L2/L3 flag in the interface parsing tables */ ethernet_sw_interface_set_l2_mode (vnm, sw_if_index, (mode != MODE_L3)); + dev_class = vnet_get_device_class (vnet_main, hi->dev_class_index); + if (dev_class->set_l2_mode_function) + { + dev_class->set_l2_mode_function (vnet_main, hi, l2_if_adjust); + } + return 0; } |