summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vnet/bonding/cli.c48
-rw-r--r--src/vnet/bonding/device.c43
-rw-r--r--src/vnet/interface.h8
-rw-r--r--src/vnet/l2/l2_input.c7
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;
}