net: bridge: Add checks for enabling the STP.
authorHoratiu Vultur <horatiu.vultur@microchip.com>
Sun, 26 Apr 2020 13:22:08 +0000 (15:22 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 27 Apr 2020 18:40:25 +0000 (11:40 -0700)
It is not possible to have the MRP and STP running at the same time on the
bridge, therefore add check when enabling the STP to check if MRP is already
enabled. In that case return error.

Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_ioctl.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp.c
net/bridge/br_stp_if.c
net/bridge/br_sysfs_br.c

index ae22d784b88aa6f37411616d75f7ce15b995f377..5e71fc8b826fc310beb00cc7f45e00da335d271f 100644 (file)
@@ -242,8 +242,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
-               br_stp_set_enabled(br, args[1]);
-               ret = 0;
+               ret = br_stp_set_enabled(br, args[1], NULL);
                break;
 
        case BRCTL_SET_BRIDGE_PRIORITY:
index 1a5e681a626a0fcb703d0f44be0b4055b725dd7b..a774e19c41bb1e02d71008de997c555409d02b33 100644 (file)
@@ -1109,7 +1109,9 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
        if (data[IFLA_BR_STP_STATE]) {
                u32 stp_enabled = nla_get_u32(data[IFLA_BR_STP_STATE]);
 
-               br_stp_set_enabled(br, stp_enabled);
+               err = br_stp_set_enabled(br, stp_enabled, extack);
+               if (err)
+                       return err;
        }
 
        if (data[IFLA_BR_PRIORITY]) {
index 5835828320b66cad45e461153533892691064325..c35647cb138a908c04b4e8fcc0f5dab290ade422 100644 (file)
@@ -1283,7 +1283,8 @@ int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time);
 /* br_stp_if.c */
 void br_stp_enable_bridge(struct net_bridge *br);
 void br_stp_disable_bridge(struct net_bridge *br);
-void br_stp_set_enabled(struct net_bridge *br, unsigned long val);
+int br_stp_set_enabled(struct net_bridge *br, unsigned long val,
+                      struct netlink_ext_ack *extack);
 void br_stp_enable_port(struct net_bridge_port *p);
 void br_stp_disable_port(struct net_bridge_port *p);
 bool br_stp_recalculate_bridge_id(struct net_bridge *br);
index 1f14b84553457053479d2019f2ec9d8e6e2c41b1..3e88be7aa2692d8e466cc4e5362c38c7756b469d 100644 (file)
@@ -36,6 +36,12 @@ void br_set_state(struct net_bridge_port *p, unsigned int state)
        };
        int err;
 
+       /* Don't change the state of the ports if they are driven by a different
+        * protocol.
+        */
+       if (p->flags & BR_MRP_AWARE)
+               return;
+
        p->state = state;
        err = switchdev_port_attr_set(p->dev, &attr);
        if (err && err != -EOPNOTSUPP)
index d174d3a566aae9b6892cee764045148cd2adbf93..a42850b7eb9a87d3c2dc6bb1a78eab8634ea86c3 100644 (file)
@@ -196,10 +196,17 @@ static void br_stp_stop(struct net_bridge *br)
        br->stp_enabled = BR_NO_STP;
 }
 
-void br_stp_set_enabled(struct net_bridge *br, unsigned long val)
+int br_stp_set_enabled(struct net_bridge *br, unsigned long val,
+                      struct netlink_ext_ack *extack)
 {
        ASSERT_RTNL();
 
+       if (br_mrp_enabled(br)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "STP can't be enabled if MRP is already enabled\n");
+               return -EINVAL;
+       }
+
        if (val) {
                if (br->stp_enabled == BR_NO_STP)
                        br_stp_start(br);
@@ -207,6 +214,8 @@ void br_stp_set_enabled(struct net_bridge *br, unsigned long val)
                if (br->stp_enabled != BR_NO_STP)
                        br_stp_stop(br);
        }
+
+       return 0;
 }
 
 /* called under bridge lock */
index 9ab0f00b10811fb339b39e8e1b075953a0a35249..7db06e3f642a093a41e22bb72e339d91b854b731 100644 (file)
@@ -126,9 +126,7 @@ static ssize_t stp_state_show(struct device *d,
 
 static int set_stp_state(struct net_bridge *br, unsigned long val)
 {
-       br_stp_set_enabled(br, val);
-
-       return 0;
+       return br_stp_set_enabled(br, val, NULL);
 }
 
 static ssize_t stp_state_store(struct device *d,