mlxsw: spectrum: Sanitize VLAN interface's uppers

Currently, only VRF and macvlan uppers are supported on top of VLAN
device configured over a bridge, so make sure the driver forbids other
uppers.

Note that enslavement to a VRF is handled earlier in the notification
block, so there is no need to check for a VRF upper here.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Ido Schimmel 2018-12-19 06:08:37 +00:00 committed by David S. Miller
parent 055722716c
commit 927d0ef10a

View File

@ -5156,6 +5156,48 @@ static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev,
return 0; return 0;
} }
static int mlxsw_sp_netdevice_bridge_vlan_event(struct net_device *vlan_dev,
struct net_device *br_dev,
unsigned long event, void *ptr,
u16 vid)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
struct netdev_notifier_changeupper_info *info = ptr;
struct netlink_ext_ack *extack;
struct net_device *upper_dev;
if (!mlxsw_sp)
return 0;
extack = netdev_notifier_info_to_extack(&info->info);
switch (event) {
case NETDEV_PRECHANGEUPPER:
upper_dev = info->upper_dev;
if (!netif_is_macvlan(upper_dev)) {
NL_SET_ERR_MSG_MOD(extack, "Unknown upper device type");
return -EOPNOTSUPP;
}
if (!info->linking)
break;
if (netif_is_macvlan(upper_dev) &&
!mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan_dev)) {
NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
return -EOPNOTSUPP;
}
break;
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
if (info->linking)
break;
if (netif_is_macvlan(upper_dev))
mlxsw_sp_rif_macvlan_del(mlxsw_sp, upper_dev);
break;
}
return 0;
}
static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev, static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
@ -5169,6 +5211,9 @@ static int mlxsw_sp_netdevice_vlan_event(struct net_device *vlan_dev,
return mlxsw_sp_netdevice_lag_port_vlan_event(vlan_dev, return mlxsw_sp_netdevice_lag_port_vlan_event(vlan_dev,
real_dev, event, real_dev, event,
ptr, vid); ptr, vid);
else if (netif_is_bridge_master(real_dev))
return mlxsw_sp_netdevice_bridge_vlan_event(vlan_dev, real_dev,
event, ptr, vid);
return 0; return 0;
} }