Skip to content

Commit 2c5ffe8

Browse files
pmachatadavem330
authored andcommitted
mlxsw: spectrum: Permit enslavement to netdevices with uppers
Enslaving of front panel ports (and their uppers) to netdevices that already have uppers is currently forbidden. In the previous patches, a number of replays have been added. Those ensure that various bits of state, such as next hops or switchdev objects, are offloaded when they become relevant due to a mlxsw lower being introduced into the topology. However the act of actually, for example, enslaving a front-panel port to a bridge with uppers, has been vetoed so far. In this patch, remove the vetoes and permit the operation. mlxsw currently validates creation of "interesting" uppers. Thus creating VLAN netdevices on top of 802.1ad bridges is forbidden if the bridge has an mlxsw lower, but permitted in general. This validation code never gets run when a port is introduced as a lower of an existing netdevice structure. Thus when enslaving an mlxsw netdevice to netdevices with uppers, invoke the PRECHANGEUPPER event handler for each netdevice above the one that the front panel port is being enslaved to. This way the tower of netdevices above the attachment point is validated. Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Danielle Ratson <danieller@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 4560cf4 commit 2c5ffe8

1 file changed

Lines changed: 62 additions & 4 deletions

File tree

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4735,6 +4735,58 @@ static bool mlxsw_sp_bridge_vxlan_is_valid(struct net_device *br_dev,
47354735
return true;
47364736
}
47374737

4738+
static bool mlxsw_sp_netdev_is_master(struct net_device *upper_dev,
4739+
struct net_device *dev)
4740+
{
4741+
return upper_dev == netdev_master_upper_dev_get(dev);
4742+
}
4743+
4744+
static int __mlxsw_sp_netdevice_event(struct mlxsw_sp *mlxsw_sp,
4745+
unsigned long event, void *ptr,
4746+
bool process_foreign);
4747+
4748+
static int mlxsw_sp_netdevice_validate_uppers(struct mlxsw_sp *mlxsw_sp,
4749+
struct net_device *dev,
4750+
struct netlink_ext_ack *extack)
4751+
{
4752+
struct net_device *upper_dev;
4753+
struct list_head *iter;
4754+
int err;
4755+
4756+
netdev_for_each_upper_dev_rcu(dev, upper_dev, iter) {
4757+
struct netdev_notifier_changeupper_info info = {
4758+
.info = {
4759+
.dev = dev,
4760+
.extack = extack,
4761+
},
4762+
.master = mlxsw_sp_netdev_is_master(upper_dev, dev),
4763+
.upper_dev = upper_dev,
4764+
.linking = true,
4765+
4766+
/* upper_info is relevant for LAG devices. But we would
4767+
* only need this if LAG were a valid upper above
4768+
* another upper (e.g. a bridge that is a member of a
4769+
* LAG), and that is never a valid configuration. So we
4770+
* can keep this as NULL.
4771+
*/
4772+
.upper_info = NULL,
4773+
};
4774+
4775+
err = __mlxsw_sp_netdevice_event(mlxsw_sp,
4776+
NETDEV_PRECHANGEUPPER,
4777+
&info, true);
4778+
if (err)
4779+
return err;
4780+
4781+
err = mlxsw_sp_netdevice_validate_uppers(mlxsw_sp, upper_dev,
4782+
extack);
4783+
if (err)
4784+
return err;
4785+
}
4786+
4787+
return 0;
4788+
}
4789+
47384790
static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
47394791
struct net_device *dev,
47404792
unsigned long event, void *ptr,
@@ -4776,8 +4828,11 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
47764828
(!netif_is_bridge_master(upper_dev) ||
47774829
!mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp,
47784830
upper_dev))) {
4779-
NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported");
4780-
return -EINVAL;
4831+
err = mlxsw_sp_netdevice_validate_uppers(mlxsw_sp,
4832+
upper_dev,
4833+
extack);
4834+
if (err)
4835+
return err;
47814836
}
47824837
if (netif_is_lag_master(upper_dev) &&
47834838
!mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev,
@@ -5008,8 +5063,11 @@ static int mlxsw_sp_netdevice_port_vlan_event(struct net_device *vlan_dev,
50085063
(!netif_is_bridge_master(upper_dev) ||
50095064
!mlxsw_sp_bridge_device_is_offloaded(mlxsw_sp,
50105065
upper_dev))) {
5011-
NL_SET_ERR_MSG_MOD(extack, "Enslaving a port to a device that already has an upper device is not supported");
5012-
return -EINVAL;
5066+
err = mlxsw_sp_netdevice_validate_uppers(mlxsw_sp,
5067+
upper_dev,
5068+
extack);
5069+
if (err)
5070+
return err;
50135071
}
50145072
break;
50155073
case NETDEV_CHANGEUPPER:

0 commit comments

Comments
 (0)