]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
mlxsw: spectrum_switchdev: Ban PVID change if bridge has a RIF
authorPetr Machata <petrm@mellanox.com>
Mon, 25 Jun 2018 07:48:17 +0000 (10:48 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Jun 2018 09:05:22 +0000 (18:05 +0900)
When traffic passes through a router port, it needs to be assigned a FID
for ASIC to forward correctly. For bridges, this FID used to be the one
corresponding to VLAN 1. In a previous patch, this was changed to
instead use the PVID at the time that the RIF is created. This patch
guards PVID changes after the RIF was introduced.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

index eea5666a86b2ae341524710e678d4caf5776a18b..da94e1eb9e1693bfed9d0cb73827013c1fbea9db 100644 (file)
@@ -1135,6 +1135,39 @@ err_port_vlan_set:
        return err;
 }
 
+static int
+mlxsw_sp_br_ban_rif_pvid_change(struct mlxsw_sp *mlxsw_sp,
+                               const struct net_device *br_dev,
+                               const struct switchdev_obj_port_vlan *vlan)
+{
+       struct mlxsw_sp_rif *rif;
+       struct mlxsw_sp_fid *fid;
+       u16 pvid;
+       u16 vid;
+
+       rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, br_dev);
+       if (!rif)
+               return 0;
+       fid = mlxsw_sp_rif_fid(rif);
+       pvid = mlxsw_sp_fid_8021q_vid(fid);
+
+       for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+               if (vlan->flags & BRIDGE_VLAN_INFO_PVID) {
+                       if (vid != pvid) {
+                               netdev_err(br_dev, "Can't change PVID, it's used by router interface\n");
+                               return -EBUSY;
+                       }
+               } else {
+                       if (vid == pvid) {
+                               netdev_err(br_dev, "Can't remove PVID, it's used by router interface\n");
+                               return -EBUSY;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                                   const struct switchdev_obj_port_vlan *vlan,
                                   struct switchdev_trans *trans)
@@ -1146,8 +1179,18 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
        struct mlxsw_sp_bridge_port *bridge_port;
        u16 vid;
 
-       if (netif_is_bridge_master(orig_dev))
-               return -EOPNOTSUPP;
+       if (netif_is_bridge_master(orig_dev)) {
+               int err = 0;
+
+               if ((vlan->flags & BRIDGE_VLAN_INFO_BRENTRY) &&
+                   br_vlan_enabled(orig_dev) &&
+                   switchdev_trans_ph_prepare(trans))
+                       err = mlxsw_sp_br_ban_rif_pvid_change(mlxsw_sp,
+                                                             orig_dev, vlan);
+               if (!err)
+                       err = -EOPNOTSUPP;
+               return err;
+       }
 
        if (switchdev_trans_ph_prepare(trans))
                return 0;