mlxsw: spectrum: Sanitize VLAN interface's uppers
authorIdo Schimmel <idosch@mellanox.com>
Wed, 19 Dec 2018 06:08:37 +0000 (06:08 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Dec 2018 20:28:07 +0000 (12:28 -0800)
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>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c

index eb8db9fae2373341d2473458323df4bccdaed4e6..891cf099fdd5f784f0e9b71dfacb80a3177357c6 100644 (file)
@@ -5156,6 +5156,48 @@ static int mlxsw_sp_netdevice_lag_port_vlan_event(struct net_device *vlan_dev,
        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,
                                         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,
                                                              real_dev, event,
                                                              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;
 }