net: dsa: Validate hardware support for MST
authorTobias Waldekranz <tobias@waldekranz.com>
Wed, 16 Mar 2022 15:08:52 +0000 (16:08 +0100)
committerJakub Kicinski <kuba@kernel.org>
Thu, 17 Mar 2022 23:49:58 +0000 (16:49 -0700)
When joining a bridge where MST is enabled, we validate that the
proper offloading support is in place, otherwise we fallback to
software bridging.

When then mode is changed on a bridge in which we are members, we
refuse the change if offloading is not supported.

At the moment we only check for configurable learning, but this will
be further restricted as we support more MST related switchdev events.

Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/dsa/dsa_priv.h
net/dsa/port.c
net/dsa/slave.c

index f20bdd8ea0a8373856150c72ac05fd6b12fe2ca0..2aba420696ef0b1f8baf55f0e61cedb7bc4db3e6 100644 (file)
@@ -234,6 +234,8 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
                            struct netlink_ext_ack *extack);
 bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
 int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock);
+int dsa_port_mst_enable(struct dsa_port *dp, bool on,
+                       struct netlink_ext_ack *extack);
 int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
                        bool targeted_match);
 int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
index 58291df14cdb4137300a7c34a58f8f5e39b7962e..02214033cec0675a9fc9e60a277b120d2c573579 100644 (file)
@@ -321,6 +321,11 @@ static void dsa_port_bridge_destroy(struct dsa_port *dp,
        kfree(bridge);
 }
 
+static bool dsa_port_supports_mst(struct dsa_port *dp)
+{
+       return dsa_port_can_configure_learning(dp);
+}
+
 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
                         struct netlink_ext_ack *extack)
 {
@@ -334,6 +339,9 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
        struct net_device *brport_dev;
        int err;
 
+       if (br_mst_enabled(br) && !dsa_port_supports_mst(dp))
+               return -EOPNOTSUPP;
+
        /* Here the interface is already bridged. Reflect the current
         * configuration so that drivers can program their chips accordingly.
         */
@@ -735,6 +743,20 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock)
        return 0;
 }
 
+int dsa_port_mst_enable(struct dsa_port *dp, bool on,
+                       struct netlink_ext_ack *extack)
+{
+       if (!on)
+               return 0;
+
+       if (!dsa_port_supports_mst(dp)) {
+               NL_SET_ERR_MSG_MOD(extack, "Hardware does not support MST");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int dsa_port_pre_bridge_flags(const struct dsa_port *dp,
                              struct switchdev_brport_flags flags,
                              struct netlink_ext_ack *extack)
index d24b6bf845c12e35da8a8f3dba4dbbf99e6e9c45..6393a35c566047edea208e5d6cfe14c7be4837cb 100644 (file)
@@ -464,6 +464,12 @@ static int dsa_slave_port_attr_set(struct net_device *dev, const void *ctx,
 
                ret = dsa_port_ageing_time(dp, attr->u.ageing_time);
                break;
+       case SWITCHDEV_ATTR_ID_BRIDGE_MST:
+               if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev))
+                       return -EOPNOTSUPP;
+
+               ret = dsa_port_mst_enable(dp, attr->u.mst, extack);
+               break;
        case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
                if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev))
                        return -EOPNOTSUPP;