Commit 15f8f168 authored by Vlad Buslov's avatar Vlad Buslov Committed by Saeed Mahameed

net/mlx5: Bridge, verify LAG state when adding bond to bridge

Mlx5 LAG is initialized asynchronously on a workqueue which means that for
a brief moment after setting mlx5 UL representors as lower devices of a
bond netdevice the LAG itself is not fully initialized in the driver. When
adding such bond device to a bridge mlx5 bridge code will not consider it
as offload-capable, skip creating necessary bookkeeping and fail any
further bridge offload-related commands with it (setting VLANs, offloading
FDBs, etc.). In order to make the error explicit during bridge
initialization stage implement the code that detects such condition during
NETDEV_PRECHANGEUPPER event and returns an error.

Fixes: ff9b7521 ("net/mlx5: Bridge, support LAG")
Signed-off-by: default avatarVlad Buslov <vladbu@nvidia.com>
Reviewed-by: default avatarRoi Dayan <roid@nvidia.com>
Reviewed-by: default avatarMark Bloch <mbloch@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 27c064ae
...@@ -164,6 +164,36 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr ...@@ -164,6 +164,36 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
return err; return err;
} }
static int
mlx5_esw_bridge_changeupper_validate_netdev(void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct netdev_notifier_changeupper_info *info = ptr;
struct net_device *upper = info->upper_dev;
struct net_device *lower;
struct list_head *iter;
if (!netif_is_bridge_master(upper) || !netif_is_lag_master(dev))
return 0;
netdev_for_each_lower_dev(dev, lower, iter) {
struct mlx5_core_dev *mdev;
struct mlx5e_priv *priv;
if (!mlx5e_eswitch_rep(lower))
continue;
priv = netdev_priv(lower);
mdev = priv->mdev;
if (!mlx5_lag_is_active(mdev))
return -EAGAIN;
if (!mlx5_lag_is_shared_fdb(mdev))
return -EOPNOTSUPP;
}
return 0;
}
static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
...@@ -171,6 +201,7 @@ static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb, ...@@ -171,6 +201,7 @@ static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
switch (event) { switch (event) {
case NETDEV_PRECHANGEUPPER: case NETDEV_PRECHANGEUPPER:
err = mlx5_esw_bridge_changeupper_validate_netdev(ptr);
break; break;
case NETDEV_CHANGEUPPER: case NETDEV_CHANGEUPPER:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment