From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCD87C433F5 for ; Mon, 14 Mar 2022 09:53:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238138AbiCNJyR (ORCPT ); Mon, 14 Mar 2022 05:54:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37626 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237883AbiCNJyH (ORCPT ); Mon, 14 Mar 2022 05:54:07 -0400 Received: from mail-lj1-x233.google.com (mail-lj1-x233.google.com [IPv6:2a00:1450:4864:20::233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B03DF7663 for ; Mon, 14 Mar 2022 02:52:57 -0700 (PDT) Received: by mail-lj1-x233.google.com with SMTP id r22so20985053ljd.4 for ; Mon, 14 Mar 2022 02:52:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=l62ARJx0QLbPhYzzdPptHODQTnZKvnjX9kCsDNHDY+s=; b=qntbUcYKngPAgJgDZTZYstn0L58jHpyw/ePanIZvaaFWsKN7mv0ToIVPr62hGSK0ZO Y08lh41x9/QBMx1UZNtfn27iG1tHn9u4ONVgx88kq62TZJ1SHzw0jjJqdxbab5LtTtK2 0huEzHz4da4UENOw/iRSNyLQmiRh8Oqf7XVm3z1eFNo/Z6zxbJvz9F26maQR8R/UqtGQ UP4Lqkxm7t/iQHoe/CN+cbInvSYVVpFd5HV/jyD/zhlmoS3LPj/A75pBcN4FJLQJbHWV mIMzM+eYSghpZJ0xKZLlE4xWe7ZzpOtAQnuk5XdsW/FxuNcBDfMrLC4nuAX+N28SOnjk 2doQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=l62ARJx0QLbPhYzzdPptHODQTnZKvnjX9kCsDNHDY+s=; b=gJVE273UgjL1HuOEdyw+k8RGN9gXEkj5EGywoScwnMeXaXioySf9E+o7b46u434PFF G2yFYB93/4Kgr/8yIuEMdGmpc7B5uzupE3uP1P2tUupkK6ahCS0UjPsYBI9aQ4WN0ZNe YRe+dVDcC5mK8TQUm0wJh/z1/I1hGVRUZgtFynqRITNYQEL9A4dub9y4gb+hgfjsV234 Fs8tFphG54zIVA13LdW4iovaJhxwm2HR9LKup8NdTQY+kQmovB5zMNPKeTiJkyhllfm6 rraQpWDtfAMqQmCrX8dct1XwbR5LOWtdfZ5UH7CsujmRbdGiwigJ3XSornQsX4S7aXLN gqWA== X-Gm-Message-State: AOAM532QyhxDVQBGAHCBsnT7tn0n4AQXXs2CzQUMpRQuTSTp5ufKvvi1 ugMOIq4PkYvAZYT+eS0myl43Mw== X-Google-Smtp-Source: ABdhPJy+pr3Jcb9prGLm2OaLKmeFLoBqEhlYFZdS4uCBl9ft3mby4+hNfEDiG4ItHP/n/HHpoERCvw== X-Received: by 2002:a05:651c:4cb:b0:247:fd6b:47ce with SMTP id e11-20020a05651c04cb00b00247fd6b47cemr14218565lji.289.1647251575854; Mon, 14 Mar 2022 02:52:55 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.52.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:52:55 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 01/14] net: bridge: mst: Multiple Spanning Tree (MST) mode Date: Mon, 14 Mar 2022 10:52:18 +0100 Message-Id: <20220314095231.3486931-2-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Allow the user to switch from the current per-VLAN STP mode to an MST mode. Up to this point, per-VLAN STP states where always isolated from each other. This is in contrast to the MSTP standard (802.1Q-2018, Clause 13.5), where VLANs are grouped into MST instances (MSTIs), and the state is managed on a per-MSTI level, rather that at the per-VLAN level. Perhaps due to the prevalence of the standard, many switching ASICs are built after the same model. Therefore, add a corresponding MST mode to the bridge, which we can later add offloading support for in a straight-forward way. For now, all VLANs are fixed to MSTI 0, also called the Common Spanning Tree (CST). That is, all VLANs will follow the port-global state. Upcoming changes will make this actually useful by allowing VLANs to be mapped to arbitrary MSTIs and allow individual MSTI states to be changed. Signed-off-by: Tobias Waldekranz Acked-by: Nikolay Aleksandrov Reported-by: kernel test robot --- include/uapi/linux/if_bridge.h | 1 + net/bridge/Makefile | 2 +- net/bridge/br.c | 5 ++ net/bridge/br_input.c | 17 ++++++- net/bridge/br_mst.c | 84 ++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 27 +++++++++++ net/bridge/br_stp.c | 3 ++ net/bridge/br_vlan.c | 20 +++++++- net/bridge/br_vlan_options.c | 5 ++ 9 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 net/bridge/br_mst.c diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 2711c3522010..30a242195ced 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -759,6 +759,7 @@ struct br_mcast_stats { enum br_boolopt_id { BR_BOOLOPT_NO_LL_LEARN, BR_BOOLOPT_MCAST_VLAN_SNOOPING, + BR_BOOLOPT_MST_ENABLE, BR_BOOLOPT_MAX }; =20 diff --git a/net/bridge/Makefile b/net/bridge/Makefile index 7fb9a021873b..24bd1c0a9a5a 100644 --- a/net/bridge/Makefile +++ b/net/bridge/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_BRIDGE_NETFILTER) +=3D br_netfilter.o =20 bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) +=3D br_multicast.o br_mdb.o br_mult= icast_eht.o =20 -bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) +=3D br_vlan.o br_vlan_tunnel.o br_= vlan_options.o +bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) +=3D br_vlan.o br_vlan_tunnel.o br_= vlan_options.o br_mst.o =20 bridge-$(CONFIG_NET_SWITCHDEV) +=3D br_switchdev.o =20 diff --git a/net/bridge/br.c b/net/bridge/br.c index b1dea3febeea..96e91d69a9a8 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -265,6 +265,9 @@ int br_boolopt_toggle(struct net_bridge *br, enum br_bo= olopt_id opt, bool on, case BR_BOOLOPT_MCAST_VLAN_SNOOPING: err =3D br_multicast_toggle_vlan_snooping(br, on, extack); break; + case BR_BOOLOPT_MST_ENABLE: + err =3D br_mst_set_enabled(br, on, extack); + break; default: /* shouldn't be called with unsupported options */ WARN_ON(1); @@ -281,6 +284,8 @@ int br_boolopt_get(const struct net_bridge *br, enum br= _boolopt_id opt) return br_opt_get(br, BROPT_NO_LL_LEARN); case BR_BOOLOPT_MCAST_VLAN_SNOOPING: return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED); + case BR_BOOLOPT_MST_ENABLE: + return br_opt_get(br, BROPT_MST_ENABLED); default: /* shouldn't be called with unsupported options */ WARN_ON(1); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e0c13fcc50ed..196417859c4a 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -78,13 +78,22 @@ int br_handle_frame_finish(struct net *net, struct sock= *sk, struct sk_buff *skb u16 vid =3D 0; u8 state; =20 - if (!p || p->state =3D=3D BR_STATE_DISABLED) + if (!p) goto drop; =20 br =3D p->br; + + if (br_mst_is_enabled(br)) { + state =3D BR_STATE_FORWARDING; + } else { + if (p->state =3D=3D BR_STATE_DISABLED) + goto drop; + + state =3D p->state; + } + brmctx =3D &p->br->multicast_ctx; pmctx =3D &p->multicast_ctx; - state =3D p->state; if (!br_allowed_ingress(p->br, nbp_vlan_group_rcu(p), skb, &vid, &state, &vlan)) goto out; @@ -370,9 +379,13 @@ static rx_handler_result_t br_handle_frame(struct sk_b= uff **pskb) return RX_HANDLER_PASS; =20 forward: + if (br_mst_is_enabled(p->br)) + goto defer_stp_filtering; + switch (p->state) { case BR_STATE_FORWARDING: case BR_STATE_LEARNING: +defer_stp_filtering: if (ether_addr_equal(p->br->dev->dev_addr, dest)) skb->pkt_type =3D PACKET_HOST; =20 diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c new file mode 100644 index 000000000000..e1ec9d39c660 --- /dev/null +++ b/net/bridge/br_mst.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Bridge Multiple Spanning Tree Support + * + * Authors: + * Tobias Waldekranz + */ + +#include + +#include "br_private.h" + +DEFINE_STATIC_KEY_FALSE(br_mst_used); + +static void br_mst_vlan_set_state(struct net_bridge_port *p, struct net_br= idge_vlan *v, + u8 state) +{ + struct net_bridge_vlan_group *vg =3D nbp_vlan_group(p); + + if (v->state =3D=3D state) + return; + + br_vlan_set_state(v, state); + + if (v->vid =3D=3D vg->pvid) + br_vlan_set_pvid_state(vg, state); +} + +void br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state) +{ + struct net_bridge_vlan_group *vg; + struct net_bridge_vlan *v; + + vg =3D nbp_vlan_group(p); + if (!vg) + return; + + list_for_each_entry(v, &vg->vlan_list, vlist) { + if (v->brvlan->msti !=3D msti) + continue; + + br_mst_vlan_set_state(p, v, state); + } +} + +void br_mst_vlan_init_state(struct net_bridge_vlan *v) +{ + /* VLANs always start out in MSTI 0 (CST) */ + v->msti =3D 0; + + if (br_vlan_is_master(v)) + v->state =3D BR_STATE_FORWARDING; + else + v->state =3D v->port->state; +} + +int br_mst_set_enabled(struct net_bridge *br, bool on, + struct netlink_ext_ack *extack) +{ + struct net_bridge_vlan_group *vg; + struct net_bridge_port *p; + + list_for_each_entry(p, &br->port_list, list) { + vg =3D nbp_vlan_group(p); + + if (!vg->num_vlans) + continue; + + NL_SET_ERR_MSG(extack, + "MST mode can't be changed while VLANs exist"); + return -EBUSY; + } + + if (br_opt_get(br, BROPT_MST_ENABLED) =3D=3D on) + return 0; + + if (on) + static_branch_enable(&br_mst_used); + else + static_branch_disable(&br_mst_used); + + br_opt_toggle(br, BROPT_MST_ENABLED, on); + return 0; +} diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 48bc61ebc211..35b47f6b449a 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -178,6 +178,7 @@ enum { * @br_mcast_ctx: if MASTER flag set, this is the global vlan multicast co= ntext * @port_mcast_ctx: if MASTER flag unset, this is the per-port/vlan multic= ast * context + * @msti: if MASTER flag set, this holds the VLANs MST instance * @vlist: sorted list of VLAN entries * @rcu: used for entry destruction * @@ -210,6 +211,8 @@ struct net_bridge_vlan { struct net_bridge_mcast_port port_mcast_ctx; }; =20 + u16 msti; + struct list_head vlist; =20 struct rcu_head rcu; @@ -445,6 +448,7 @@ enum net_bridge_opts { BROPT_NO_LL_LEARN, BROPT_VLAN_BRIDGE_BINDING, BROPT_MCAST_VLAN_SNOOPING_ENABLED, + BROPT_MST_ENABLED, }; =20 struct net_bridge { @@ -1765,6 +1769,29 @@ static inline bool br_vlan_state_allowed(u8 state, b= ool learn_allow) } #endif =20 +/* br_mst.c */ +#ifdef CONFIG_BRIDGE_VLAN_FILTERING +DECLARE_STATIC_KEY_FALSE(br_mst_used); +static inline bool br_mst_is_enabled(struct net_bridge *br) +{ + return static_branch_unlikely(&br_mst_used) && + br_opt_get(br, BROPT_MST_ENABLED); +} + +void br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state); +void br_mst_vlan_init_state(struct net_bridge_vlan *v); +int br_mst_set_enabled(struct net_bridge *br, bool on, + struct netlink_ext_ack *extack); +#else +static inline bool br_mst_is_enabled(struct net_bridge *br) +{ + return false; +} + +static inline void br_mst_set_state(struct net_bridge_port *p, + u16 msti, u8 state) {} +#endif + struct nf_br_ops { int (*br_dev_xmit_hook)(struct sk_buff *skb); }; diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 1d80f34a139c..82a97a021a57 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -43,6 +43,9 @@ void br_set_state(struct net_bridge_port *p, unsigned int= state) return; =20 p->state =3D state; + if (br_opt_get(p->br, BROPT_MST_ENABLED)) + br_mst_set_state(p, 0, state); + err =3D switchdev_port_attr_set(p->dev, &attr, NULL); if (err && err !=3D -EOPNOTSUPP) br_warn(p->br, "error setting offload STP state on port %u(%s)\n", diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 7557e90b60e1..0f5e75ccac79 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -226,6 +226,24 @@ static void nbp_vlan_rcu_free(struct rcu_head *rcu) kfree(v); } =20 +static void br_vlan_init_state(struct net_bridge_vlan *v) +{ + struct net_bridge *br; + + if (br_vlan_is_master(v)) + br =3D v->br; + else + br =3D v->port->br; + + if (br_opt_get(br, BROPT_MST_ENABLED)) { + br_mst_vlan_init_state(v); + return; + } + + v->state =3D BR_STATE_FORWARDING; + v->msti =3D 0; +} + /* This is the shared VLAN add function which works for both ports and bri= dge * devices. There are four possible calls to this function in terms of the * vlan entry type: @@ -322,7 +340,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 fl= ags, } =20 /* set the state before publishing */ - v->state =3D BR_STATE_FORWARDING; + br_vlan_init_state(v); =20 err =3D rhashtable_lookup_insert_fast(&vg->vlan_hash, &v->vnode, br_vlan_rht_params); diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c index a6382973b3e7..09112b56e79c 100644 --- a/net/bridge/br_vlan_options.c +++ b/net/bridge/br_vlan_options.c @@ -99,6 +99,11 @@ static int br_vlan_modify_state(struct net_bridge_vlan_g= roup *vg, return -EBUSY; } =20 + if (br_opt_get(br, BROPT_MST_ENABLED)) { + NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state directly when MST is= enabled"); + return -EBUSY; + } + if (v->state =3D=3D state) return 0; =20 --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01B52C433EF for ; Mon, 14 Mar 2022 09:53:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238168AbiCNJyX (ORCPT ); Mon, 14 Mar 2022 05:54:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238129AbiCNJyJ (ORCPT ); Mon, 14 Mar 2022 05:54:09 -0400 Received: from mail-lj1-x235.google.com (mail-lj1-x235.google.com [IPv6:2a00:1450:4864:20::235]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 173BCBC09 for ; Mon, 14 Mar 2022 02:52:59 -0700 (PDT) Received: by mail-lj1-x235.google.com with SMTP id q10so20971230ljc.7 for ; Mon, 14 Mar 2022 02:52:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=zPCjEPNM43E5A1SgRuIq+fVuzqtfX/i63TI5Eoft5zg=; b=pi7XAVi79YQyr13XzIYhZXv7ZQnly88qlB/aWbiR6oJ1zJxQ2NdpSWErK2/x1VsqEa /hlxkP3+l/uYVR1y6GqncA3WEF8ltIV8V1z8w6qDCfaBCapxT/JKYxKlr1FGlQ/uqPvU exi+zG/A2GlCDB6Ozkk3pAJWYMigYHGfjWGVdcb7aaRlFhGXSzRhUdUjaGHqGQqR1oXq ET2L0opBU1cOwvA5xPHCfqi8JcKdDs3vBB3DiopXJVLwAVW7ooMJrmSLV5NTS9O0CYpY JwBEzpRPsNaFnOhIzOzzmVndVXJsSsqdY5OWpx2ws9p/mFmmTPW7FvdFRI09YzUoAtYY wbyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=zPCjEPNM43E5A1SgRuIq+fVuzqtfX/i63TI5Eoft5zg=; b=eRdbaBmSE6CdeDbYVB3H2sF8Ur7lyZouWrHVN8ot+cZJ1n5pzd8amLcGd7ILitZ2It GwvaWn6XmGMTM1l6252BQKgxyPxDw/6ItW4X5Qwh/zTTg6UgOpJWF5MufdjKXR7JtDGu JxyZnJjXBu3lSPe0TFU90j+p1G0EmhsZrSJkherB57Ez+AROk1sxbGIqaTi+L461OD+i MY41DGvITKcQhHsV1pIb2gC35/lEvtnpO+p2wr2q6PMUAuV7fNN2aw5U7ISsmdM/GuMI zTfXC5aTkyCUvfTcwiIIpASTm9wl0U2HFwMqKGd3aYwD+6RqivXGfLw5X9aKPfiZo5j9 c0rA== X-Gm-Message-State: AOAM531In4wjc47dLpYqrE6OmUKRoiPXP6gKit/d5pviWnDRxQSQMA3u 1Vbd6mEc4EdR8RcdCsYdAr2Z8Q== X-Google-Smtp-Source: ABdhPJySKNNu6SKq084+j8M7RrpraCM087KYEOhFWhILNO7B0kSpSGZR+BXcrKvt7bqKGCRZdfbybQ== X-Received: by 2002:a2e:6804:0:b0:244:b354:1c99 with SMTP id c4-20020a2e6804000000b00244b3541c99mr13681974lja.79.1647251577343; Mon, 14 Mar 2022 02:52:57 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.52.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:52:56 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 02/14] net: bridge: mst: Allow changing a VLAN's MSTI Date: Mon, 14 Mar 2022 10:52:19 +0100 Message-Id: <20220314095231.3486931-3-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Allow a VLAN to move out of the CST (MSTI 0), to an independent tree. The user manages the VID to MSTI mappings via a global VLAN setting. The proposed iproute2 interface would be: bridge vlan global set dev br0 vid msti Changing the state in non-zero MSTIs is still not supported, but will be addressed in upcoming changes. Signed-off-by: Tobias Waldekranz Acked-by: Nikolay Aleksandrov --- include/uapi/linux/if_bridge.h | 1 + net/bridge/br_mst.c | 42 ++++++++++++++++++++++++++++++++++ net/bridge/br_private.h | 1 + net/bridge/br_vlan_options.c | 15 ++++++++++++ 4 files changed, 59 insertions(+) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 30a242195ced..f60244b747ae 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -564,6 +564,7 @@ enum { BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE, + BRIDGE_VLANDB_GOPTS_MSTI, __BRIDGE_VLANDB_GOPTS_MAX }; #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index e1ec9d39c660..78ef5fea4d2b 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -43,6 +43,48 @@ void br_mst_set_state(struct net_bridge_port *p, u16 mst= i, u8 state) } } =20 +static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti) +{ + struct net_bridge_vlan_group *vg =3D nbp_vlan_group(pv->port); + struct net_bridge_vlan *v; + + list_for_each_entry(v, &vg->vlan_list, vlist) { + /* If this port already has a defined state in this + * MSTI (through some other VLAN membership), inherit + * it. + */ + if (v !=3D pv && v->brvlan->msti =3D=3D msti) { + br_mst_vlan_set_state(pv->port, pv, v->state); + return; + } + } + + /* Otherwise, start out in a new MSTI with all ports disabled. */ + return br_mst_vlan_set_state(pv->port, pv, BR_STATE_DISABLED); +} + +int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti) +{ + struct net_bridge_vlan_group *vg; + struct net_bridge_vlan *pv; + struct net_bridge_port *p; + + if (mv->msti =3D=3D msti) + return 0; + + mv->msti =3D msti; + + list_for_each_entry(p, &mv->br->port_list, list) { + vg =3D nbp_vlan_group(p); + + pv =3D br_vlan_find(vg, mv->vid); + if (pv) + br_mst_vlan_sync_state(pv, msti); + } + + return 0; +} + void br_mst_vlan_init_state(struct net_bridge_vlan *v) { /* VLANs always start out in MSTI 0 (CST) */ diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 35b47f6b449a..b907d389b63a 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1779,6 +1779,7 @@ static inline bool br_mst_is_enabled(struct net_bridg= e *br) } =20 void br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state); +int br_mst_vlan_set_msti(struct net_bridge_vlan *v, u16 msti); void br_mst_vlan_init_state(struct net_bridge_vlan *v); int br_mst_set_enabled(struct net_bridge *br, bool on, struct netlink_ext_ack *extack); diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c index 09112b56e79c..a2724d03278c 100644 --- a/net/bridge/br_vlan_options.c +++ b/net/bridge/br_vlan_options.c @@ -296,6 +296,7 @@ bool br_vlan_global_opts_can_enter_range(const struct n= et_bridge_vlan *v_curr, const struct net_bridge_vlan *r_end) { return v_curr->vid - r_end->vid =3D=3D 1 && + v_curr->msti =3D=3D r_end->msti && ((v_curr->priv_flags ^ r_end->priv_flags) & BR_VLFLAG_GLOBAL_MCAST_ENABLED) =3D=3D 0 && br_multicast_ctx_options_equal(&v_curr->br_mcast_ctx, @@ -384,6 +385,9 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 = vid, u16 vid_range, #endif #endif =20 + if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_MSTI, v_opts->msti)) + goto out_err; + nla_nest_end(skb, nest); =20 return true; @@ -415,6 +419,7 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(const st= ruct net_bridge_vlan *v) + nla_total_size(0) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */ + br_rports_size(&v->br_mcast_ctx) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_P= ORTS */ #endif + + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_MSTI */ + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */ } =20 @@ -564,6 +569,15 @@ static int br_vlan_process_global_one_opts(const struc= t net_bridge *br, } #endif #endif + if (tb[BRIDGE_VLANDB_GOPTS_MSTI]) { + u16 msti; + + msti =3D nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_MSTI]); + err =3D br_mst_vlan_set_msti(v, msti); + if (err) + return err; + *changed =3D true; + } =20 return 0; } @@ -583,6 +597,7 @@ static const struct nla_policy br_vlan_db_gpol[BRIDGE_V= LANDB_GOPTS_MAX + 1] =3D { [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL] =3D { .type =3D NLA_U64 }, [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL] =3D { .type =3D NLA_U64 }, [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL] =3D { .type =3D NLA_U64 = }, + [BRIDGE_VLANDB_GOPTS_MSTI] =3D NLA_POLICY_MAX(NLA_U16, VLAN_N_VID - 1), }; =20 int br_vlan_rtm_process_global_options(struct net_device *dev, --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 02416C433EF for ; Mon, 14 Mar 2022 09:53:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238248AbiCNJyv (ORCPT ); Mon, 14 Mar 2022 05:54:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238146AbiCNJyN (ORCPT ); Mon, 14 Mar 2022 05:54:13 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6243E186F2 for ; Mon, 14 Mar 2022 02:53:00 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id r22so20985216ljd.4 for ; Mon, 14 Mar 2022 02:53:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=s8tE4K6C86r6zAevurFYv9wJNtJ4sSFnWHyHHEDE/R4=; b=Bh4gVTfMc7S09lV2uYPPxLHe7mgzsaJGoJbq60kXuTd/qCDnPlUJAH8hX26nBbUJO8 TxD4WLuqwMSRq7z5dT5Mem0ng/zqiP4pqPiVUPaPWw4z/Yxdn1FIsr77budKJHAsuluC gPa0VXDIV4Ci4b7zIxXD4qntuNG0OjvAFpo69aYXlG/P4HMV6UkBedqiZPvtpg0OvyvO 8U9nRyUNlCx5utLlFrVXWfqO1bD4LYfoETrHW+v7TJj/Qlo6PxhhpwpxehnXOP+j8q2m JXZRoufRI2HAKlZTiwYMlgOf0PXgliI0oCDc6J0TZbskU/Dug+01QdGnRAYrRT/R4jBQ JtNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=s8tE4K6C86r6zAevurFYv9wJNtJ4sSFnWHyHHEDE/R4=; b=Xb6/e9bMlL+bRHvskccQUhs3fKCIeYGnUg4iwieZRFt5uIsjHISrri8Qa+Q6+y7Vap Xz0umNb5otMFL8+3Dh0otP5M9uK3ieAt+PqnarwK5eWD99KgWtxJ1aom6ijxGSwOZHXF zHRh1K+rzzf9a9H3zpNZyzzAJVOemXbnaJyn32X7YiQXTGWQuc5oZVvkDFMPgBfVbJbU /RlcEDk8NSd0JZvmzu9p8JgKrTbFzwp7NfAujUDWtiEIPDWVlsKym7zaSX8qNRBrU2nO soTc+2voLOCD0qTfbhPJxDf906JOCa0gAzy4ZbgmFB4jI9M0K0L9xliXVd4W/AlcfBP3 iAHQ== X-Gm-Message-State: AOAM530k0wpWPM9yOCayyNUvghF/dK0zRJg8qNhxhqR/xvVo4BpQ/1Aq 2bCo3GrlW5V1xy16Jzgh/nAOaQ== X-Google-Smtp-Source: ABdhPJyRX/YvK897Wpk2Sbjn5yAuFabNkpya1Dt4UaghhdP/KwPpj/6gIs1SaX0DgJWaai9+6u6W+w== X-Received: by 2002:a05:651c:a10:b0:247:eb57:23d0 with SMTP id k16-20020a05651c0a1000b00247eb5723d0mr14034365ljq.207.1647251579011; Mon, 14 Mar 2022 02:52:59 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.52.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:52:58 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 03/14] net: bridge: mst: Support setting and reporting MST port states Date: Mon, 14 Mar 2022 10:52:20 +0100 Message-Id: <20220314095231.3486931-4-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Make it possible to change the port state in a given MSTI by extending the bridge port netlink interface (RTM_SETLINK on PF_BRIDGE).The proposed iproute2 interface would be: bridge mst set dev msti state Current states in all applicable MSTIs can also be dumped via a corresponding RTM_GETLINK. The proposed iproute interface looks like this: $ bridge mst port msti vb1 0 state forwarding 100 state disabled vb2 0 state forwarding 100 state forwarding The preexisting per-VLAN states are still valid in the MST mode (although they are read-only), and can be queried as usual if one is interested in knowing a particular VLAN's state without having to care about the VID to MSTI mapping (in this example VLAN 20 and 30 are bound to MSTI 100): $ bridge -d vlan port vlan-id vb1 10 state forwarding mcast_router 1 20 state disabled mcast_router 1 30 state disabled mcast_router 1 40 state forwarding mcast_router 1 vb2 10 state forwarding mcast_router 1 20 state forwarding mcast_router 1 30 state forwarding mcast_router 1 40 state forwarding mcast_router 1 Signed-off-by: Tobias Waldekranz --- include/uapi/linux/if_bridge.h | 17 ++++++ include/uapi/linux/rtnetlink.h | 1 + net/bridge/br_mst.c | 105 +++++++++++++++++++++++++++++++++ net/bridge/br_netlink.c | 32 +++++++++- net/bridge/br_private.h | 15 +++++ 5 files changed, 169 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index f60244b747ae..879dfaef8da0 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -122,6 +122,7 @@ enum { IFLA_BRIDGE_VLAN_TUNNEL_INFO, IFLA_BRIDGE_MRP, IFLA_BRIDGE_CFM, + IFLA_BRIDGE_MST, __IFLA_BRIDGE_MAX, }; #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) @@ -453,6 +454,21 @@ enum { =20 #define IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX (__IFLA_BRIDGE_CFM_CC_PEER_STAT= US_MAX - 1) =20 +enum { + IFLA_BRIDGE_MST_UNSPEC, + IFLA_BRIDGE_MST_ENTRY, + __IFLA_BRIDGE_MST_MAX, +}; +#define IFLA_BRIDGE_MST_MAX (__IFLA_BRIDGE_MST_MAX - 1) + +enum { + IFLA_BRIDGE_MST_ENTRY_UNSPEC, + IFLA_BRIDGE_MST_ENTRY_MSTI, + IFLA_BRIDGE_MST_ENTRY_STATE, + __IFLA_BRIDGE_MST_ENTRY_MAX, +}; +#define IFLA_BRIDGE_MST_ENTRY_MAX (__IFLA_BRIDGE_MST_ENTRY_MAX - 1) + struct bridge_stp_xstats { __u64 transition_blk; __u64 transition_fwd; @@ -786,4 +802,5 @@ enum { __BRIDGE_QUERIER_MAX }; #define BRIDGE_QUERIER_MAX (__BRIDGE_QUERIER_MAX - 1) + #endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index 51530aade46e..83849a37db5b 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -817,6 +817,7 @@ enum { #define RTEXT_FILTER_MRP (1 << 4) #define RTEXT_FILTER_CFM_CONFIG (1 << 5) #define RTEXT_FILTER_CFM_STATUS (1 << 6) +#define RTEXT_FILTER_MST (1 << 7) =20 /* End of information exported to user level */ =20 diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index 78ef5fea4d2b..df65aa7701c1 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -124,3 +124,108 @@ int br_mst_set_enabled(struct net_bridge *br, bool on, br_opt_toggle(br, BROPT_MST_ENABLED, on); return 0; } + +int br_mst_fill_info(struct sk_buff *skb, struct net_bridge_vlan_group *vg) +{ + struct net_bridge_vlan *v; + struct nlattr *nest; + unsigned long *seen; + int err =3D 0; + + seen =3D bitmap_zalloc(VLAN_N_VID, 0); + if (!seen) + return -ENOMEM; + + list_for_each_entry(v, &vg->vlan_list, vlist) { + if (test_bit(v->brvlan->msti, seen)) + continue; + + nest =3D nla_nest_start_noflag(skb, IFLA_BRIDGE_MST_ENTRY); + if (!nest || + nla_put_u16(skb, IFLA_BRIDGE_MST_ENTRY_MSTI, v->brvlan->msti) || + nla_put_u8(skb, IFLA_BRIDGE_MST_ENTRY_STATE, v->state)) { + err =3D -EMSGSIZE; + break; + } + nla_nest_end(skb, nest); + + set_bit(v->brvlan->msti, seen); + } + + kfree(seen); + return err; +} + +static const struct nla_policy br_mst_nl_policy[IFLA_BRIDGE_MST_ENTRY_MAX = + 1] =3D { + [IFLA_BRIDGE_MST_ENTRY_MSTI] =3D NLA_POLICY_RANGE(NLA_U16, + 1, /* 0 reserved for CST */ + VLAN_N_VID - 1), + [IFLA_BRIDGE_MST_ENTRY_STATE] =3D NLA_POLICY_RANGE(NLA_U8, + BR_STATE_DISABLED, + BR_STATE_BLOCKING), +}; + +static int br_mst_parse_one(struct net_bridge_port *p, + const struct nlattr *attr, + struct netlink_ext_ack *extack) +{ + struct nlattr *tb[IFLA_BRIDGE_MST_ENTRY_MAX + 1]; + u16 msti; + u8 state; + int err; + + err =3D nla_parse_nested(tb, IFLA_BRIDGE_MST_ENTRY_MAX, attr, + br_mst_nl_policy, extack); + if (err) + return err; + + if (!tb[IFLA_BRIDGE_MST_ENTRY_MSTI]) { + NL_SET_ERR_MSG_MOD(extack, "MSTI not specified"); + return -EINVAL; + } + + if (!tb[IFLA_BRIDGE_MST_ENTRY_STATE]) { + NL_SET_ERR_MSG_MOD(extack, "State not specified"); + return -EINVAL; + } + + msti =3D nla_get_u16(tb[IFLA_BRIDGE_MST_ENTRY_MSTI]); + state =3D nla_get_u8(tb[IFLA_BRIDGE_MST_ENTRY_STATE]); + + br_mst_set_state(p, msti, state); + return 0; +} + +int br_mst_parse(struct net_bridge_port *p, struct nlattr *mst_attr, + struct netlink_ext_ack *extack) +{ + struct nlattr *attr; + int err, msts =3D 0; + int rem; + + if (!br_opt_get(p->br, BROPT_MST_ENABLED)) { + NL_SET_ERR_MSG_MOD(extack, "Can't modify MST state when MST is disabled"= ); + return -EBUSY; + } + + nla_for_each_nested(attr, mst_attr, rem) { + switch (nla_type(attr)) { + case IFLA_BRIDGE_MST_ENTRY: + err =3D br_mst_parse_one(p, attr, extack); + break; + default: + continue; + } + + msts++; + if (err) + break; + } + + if (!msts) { + NL_SET_ERR_MSG_MOD(extack, "Found no MST entries to process"); + err =3D -EINVAL; + } + + return err; +} diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 7d4432ca9a20..d2b4550f30d6 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -485,7 +485,8 @@ static int br_fill_ifinfo(struct sk_buff *skb, RTEXT_FILTER_BRVLAN_COMPRESSED | RTEXT_FILTER_MRP | RTEXT_FILTER_CFM_CONFIG | - RTEXT_FILTER_CFM_STATUS)) { + RTEXT_FILTER_CFM_STATUS | + RTEXT_FILTER_MST)) { af =3D nla_nest_start_noflag(skb, IFLA_AF_SPEC); if (!af) goto nla_put_failure; @@ -564,7 +565,28 @@ static int br_fill_ifinfo(struct sk_buff *skb, nla_nest_end(skb, cfm_nest); } =20 + if ((filter_mask & RTEXT_FILTER_MST) && + br_opt_get(br, BROPT_MST_ENABLED) && port) { + struct net_bridge_vlan_group *vg =3D nbp_vlan_group(port); + struct nlattr *mst_nest; + int err; + + if (!vg || !vg->num_vlans) + goto done; + + mst_nest =3D nla_nest_start(skb, IFLA_BRIDGE_MST); + if (!mst_nest) + goto nla_put_failure; + + err =3D br_mst_fill_info(skb, vg); + if (err) + goto nla_put_failure; + + nla_nest_end(skb, mst_nest); + } + done: + if (af) nla_nest_end(skb, af); nlmsg_end(skb, nlh); @@ -803,6 +825,14 @@ static int br_afspec(struct net_bridge *br, if (err) return err; break; + case IFLA_BRIDGE_MST: + if (cmd !=3D RTM_SETLINK || !p) + return -EINVAL; + + err =3D br_mst_parse(p, attr, extack); + if (err) + return err; + break; } } =20 diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b907d389b63a..08d82578bd97 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1783,6 +1783,9 @@ int br_mst_vlan_set_msti(struct net_bridge_vlan *v, u= 16 msti); void br_mst_vlan_init_state(struct net_bridge_vlan *v); int br_mst_set_enabled(struct net_bridge *br, bool on, struct netlink_ext_ack *extack); +int br_mst_fill_info(struct sk_buff *skb, struct net_bridge_vlan_group *vg= ); +int br_mst_parse(struct net_bridge_port *p, struct nlattr *mst_attr, + struct netlink_ext_ack *extack); #else static inline bool br_mst_is_enabled(struct net_bridge *br) { @@ -1791,6 +1794,18 @@ static inline bool br_mst_is_enabled(struct net_brid= ge *br) =20 static inline void br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state) {} +static inline int br_mst_fill_info(struct sk_buff *skb, + struct net_bridge_vlan_group *vg) +{ + return -EOPNOTSUPP; +} + +static inline int br_mst_parse(struct net_bridge_port *p, + struct nlattr *mst_attr, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} #endif =20 struct nf_br_ops { --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 421DDC433EF for ; Mon, 14 Mar 2022 09:53:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238226AbiCNJy2 (ORCPT ); Mon, 14 Mar 2022 05:54:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238143AbiCNJyN (ORCPT ); Mon, 14 Mar 2022 05:54:13 -0400 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6310F186FB for ; Mon, 14 Mar 2022 02:53:02 -0700 (PDT) Received: by mail-lf1-x133.google.com with SMTP id bt26so26071173lfb.3 for ; Mon, 14 Mar 2022 02:53:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=GeXldrFeKrg0lPEJeX36xArmy/BPfNOm6qSBt2als+U=; b=DKul0GoktIJYgeWN/vKEMB2Tl2BU9os12gPMPighZ8mD8fFcNR87HfHHI2F/IR8ZPX JQRVP79pgzygTgg4KdeLJLId8VPrflVhPOsZuQcqf32sAqEkO0Ob/sfXaCjwW+qaoEs/ jbMeNYVIJGZ3MWczoYQWqtWWtMWFR3jy48Aemgu2taAjJuW2OqgkX0B5E2nB+3+p8EvV /86ziW09PX4BFvj4EE8Btuy1yaIwsV4HHAXZdAbGGO3qfTNYf7DRHhvCJYgDrZRhzI1x gRsGiOd+YV3D9eYM0mwmHyaJMfd0oqvlHJZrlFkX0Fv73XI64p73QySRQvfInaO0b9Co is4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=GeXldrFeKrg0lPEJeX36xArmy/BPfNOm6qSBt2als+U=; b=yK+D/So+INsc2ay6aYET8Dmd1mV1bhBflOrWhR2jCysQFhIfNcgW+90g7Sboh1nr1D pcDhKDHrfcP3QLW0AzqUmXLrPJLmfF9LSWXBYW3y1GeNp21oMPdZX9DgvpUSYIR2Z6DE 3HmQeoIl9gqUg9gQmaQVszku8ET+qvBY2PKv5kXNFwqZ0Nwim6vaeNsFJ7fvwl7FyCrB ulohnonczuPfh2rDhZzP/ef92mFRIH0cgbO7/ejr+gZMw8UR2K+weYXLhxCKOf60VoLF Y4SIo04cCyQhiIsHlucmcPiOFBZI8+BDb4aoTGhKVn+m6dBYhGxIONUYez046nwmt3aY QtMg== X-Gm-Message-State: AOAM533bI/8S4XWLPAhh81VqiQzGizjEagsrY54lp5d1kQdGOEO/WJhn dMcYF6UK5Yf2KUZts4D1nrwn+A== X-Google-Smtp-Source: ABdhPJzgMmRpX9yWlD5LazxVThYtYIG18o4vNMr2kLKI16CAak4ZvoZ+VKnDtA7CIE+h24TBxsSm2A== X-Received: by 2002:a05:6512:1084:b0:448:42b8:f45c with SMTP id j4-20020a056512108400b0044842b8f45cmr13157008lfg.13.1647251580665; Mon, 14 Mar 2022 02:53:00 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.52.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:00 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 04/14] net: bridge: mst: Notify switchdev drivers of MST mode changes Date: Mon, 14 Mar 2022 10:52:21 +0100 Message-Id: <20220314095231.3486931-5-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Trigger a switchdev event whenever the bridge's MST mode is enabled/disabled. This allows constituent ports to either perform any required hardware config, or refuse the change if it not supported. Signed-off-by: Tobias Waldekranz --- include/net/switchdev.h | 2 ++ net/bridge/br_mst.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 3e424d40fae3..85dd004dc9ad 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -27,6 +27,7 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED, SWITCHDEV_ATTR_ID_BRIDGE_MROUTER, + SWITCHDEV_ATTR_ID_BRIDGE_MST, SWITCHDEV_ATTR_ID_MRP_PORT_ROLE, }; =20 @@ -48,6 +49,7 @@ struct switchdev_attr { clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ u16 vlan_protocol; /* BRIDGE_VLAN_PROTOCOL */ + bool mst; /* BRIDGE_MST */ bool mc_disabled; /* MC_DISABLED */ u8 mrp_port_role; /* MRP_PORT_ROLE */ } u; diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index df65aa7701c1..39057585c302 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -99,8 +99,14 @@ void br_mst_vlan_init_state(struct net_bridge_vlan *v) int br_mst_set_enabled(struct net_bridge *br, bool on, struct netlink_ext_ack *extack) { + struct switchdev_attr attr =3D { + .id =3D SWITCHDEV_ATTR_ID_BRIDGE_MST, + .orig_dev =3D br->dev, + .u.mst =3D on, + }; struct net_bridge_vlan_group *vg; struct net_bridge_port *p; + int err; =20 list_for_each_entry(p, &br->port_list, list) { vg =3D nbp_vlan_group(p); @@ -116,6 +122,10 @@ int br_mst_set_enabled(struct net_bridge *br, bool on, if (br_opt_get(br, BROPT_MST_ENABLED) =3D=3D on) return 0; =20 + err =3D switchdev_port_attr_set(br->dev, &attr, extack); + if (err && err !=3D -EOPNOTSUPP) + return err; + if (on) static_branch_enable(&br_mst_used); else --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28223C433F5 for ; Mon, 14 Mar 2022 09:53:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238232AbiCNJyf (ORCPT ); Mon, 14 Mar 2022 05:54:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238156AbiCNJyQ (ORCPT ); Mon, 14 Mar 2022 05:54:16 -0400 Received: from mail-lj1-x22c.google.com (mail-lj1-x22c.google.com [IPv6:2a00:1450:4864:20::22c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 37D0E2A72F for ; Mon, 14 Mar 2022 02:53:04 -0700 (PDT) Received: by mail-lj1-x22c.google.com with SMTP id z26so20967186lji.8 for ; Mon, 14 Mar 2022 02:53:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=lrKfwBXTRpFqEwpXR2ITLOR2hSsnB+amSwBGJQoamgU=; b=yKGGUkLktagWPzrcBccI4hG2eJ6S4yP13kPRpcr0Jd/5pOHSUj5NuGuCBC/10uS2Ta 4Lf9JoKNS2dgcvvbncN4Oimk2+UdTH0FD7DbTJvow57jPOnbTJEDzBtbUhPel9seNFtm 3tOHLm7I/BjD8x7r2QaHMRDSvysHnVNc4B9Rl3IWJMqEPKqsQlU75Y/G/MYKT6P4w+TW 3zaTX5JROYXm+PUywUsBdD0fYH9y+ZecOS/YBWN0yP3eECMHk/y7qJGXLG00z4LU1ndf 7Tr8LWDTI9YaOD6tYT3VOxQQR+GXS3RFdJAmmCj9T7mkQcUuSQsNYLMynJi0+GWKGqZf sHog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=lrKfwBXTRpFqEwpXR2ITLOR2hSsnB+amSwBGJQoamgU=; b=c1hUHSTw7VhRCxbWSPhEZ9Kwb21Kl7iRJH5Dr21hv/as/dvpKYq2mGUkq7Wvl4MKyO geasme8FmHO9XVmZAsmCwMV1ghkeiCfQKMahFQ7my2L/OBOhJlV95STLV+gTSMlM6eER HJVLeQN3Xm0es1itokSg1i+Wnc255XgSI0xVLHflDToj5B/J/qKL6GdQe4sVtK06lwdf /RN8rssKu5lqsqZ/qVmoZEMwUDDpGRKhgg8sbd0ptRvWqbYuThxwBbUkRMRH1LcsFGss C/EbJl+6wANhKbnU9Qr9pXVdHV2StOZM3VHuLZac5frm0QWmjBXt7bVv5XtHHeLhFuMY yZAQ== X-Gm-Message-State: AOAM531VlKCfu5KWeUxFGj9tBXcgqBUM2bWp+iqW0EjYkt8V0NLg39Ra 7ijS7eYuSZUa1fih8+LwT6vodA== X-Google-Smtp-Source: ABdhPJyvrn1qFCc5J6uOiIUk7xq9KgyhihqE/2PsJeflX5WHytSKOUPmcmGfni0XraZoA/Gxz07Few== X-Received: by 2002:a05:651c:1245:b0:247:e2af:3574 with SMTP id h5-20020a05651c124500b00247e2af3574mr13962129ljh.137.1647251582414; Mon, 14 Mar 2022 02:53:02 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:01 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 05/14] net: bridge: mst: Notify switchdev drivers of VLAN MSTI migrations Date: Mon, 14 Mar 2022 10:52:22 +0100 Message-Id: <20220314095231.3486931-6-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Whenever a VLAN moves to a new MSTI, send a switchdev notification so that switchdevs can track a bridge's VID to MSTI mappings. Signed-off-by: Tobias Waldekranz --- include/net/switchdev.h | 7 ++++++ net/bridge/br_mst.c | 14 ++++++++++++ net/bridge/br_switchdev.c | 46 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 85dd004dc9ad..53dfa0f7cf5b 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -29,6 +29,7 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_BRIDGE_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_MST, SWITCHDEV_ATTR_ID_MRP_PORT_ROLE, + SWITCHDEV_ATTR_ID_VLAN_MSTI, }; =20 struct switchdev_brport_flags { @@ -36,6 +37,11 @@ struct switchdev_brport_flags { unsigned long mask; }; =20 +struct switchdev_vlan_msti { + u16 vid; + u16 msti; +}; + struct switchdev_attr { struct net_device *orig_dev; enum switchdev_attr_id id; @@ -52,6 +58,7 @@ struct switchdev_attr { bool mst; /* BRIDGE_MST */ bool mc_disabled; /* MC_DISABLED */ u8 mrp_port_role; /* MRP_PORT_ROLE */ + struct switchdev_vlan_msti vlan_msti; /* VLAN_MSTI */ } u; }; =20 diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index 39057585c302..2f761d27d69e 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -7,6 +7,7 @@ */ =20 #include +#include =20 #include "br_private.h" =20 @@ -65,13 +66,26 @@ static void br_mst_vlan_sync_state(struct net_bridge_vl= an *pv, u16 msti) =20 int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti) { + struct switchdev_attr attr =3D { + .id =3D SWITCHDEV_ATTR_ID_VLAN_MSTI, + .orig_dev =3D mv->br->dev, + .u.vlan_msti =3D { + .vid =3D mv->vid, + .msti =3D msti, + }, + }; struct net_bridge_vlan_group *vg; struct net_bridge_vlan *pv; struct net_bridge_port *p; + int err; =20 if (mv->msti =3D=3D msti) return 0; =20 + err =3D switchdev_port_attr_set(mv->br->dev, &attr, NULL); + if (err && err !=3D -EOPNOTSUPP) + return err; + mv->msti =3D msti; =20 list_for_each_entry(p, &mv->br->port_list, list) { diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index 6f6a70121a5e..8cc44c367231 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -331,6 +331,46 @@ br_switchdev_fdb_replay(const struct net_device *br_de= v, const void *ctx, return err; } =20 +static int br_switchdev_vlan_attr_replay(struct net_device *br_dev, + const void *ctx, + struct notifier_block *nb, + struct netlink_ext_ack *extack) +{ + struct switchdev_notifier_port_attr_info attr_info =3D { + .info =3D { + .dev =3D br_dev, + .extack =3D extack, + .ctx =3D ctx, + }, + }; + struct net_bridge *br =3D netdev_priv(br_dev); + struct net_bridge_vlan_group *vg; + struct switchdev_attr attr; + struct net_bridge_vlan *v; + int err; + + attr_info.attr =3D &attr; + attr.orig_dev =3D br_dev; + + vg =3D br_vlan_group(br); + + list_for_each_entry(v, &vg->vlan_list, vlist) { + if (v->msti) { + attr.id =3D SWITCHDEV_ATTR_ID_VLAN_MSTI; + attr.u.vlan_msti.vid =3D v->vid; + attr.u.vlan_msti.msti =3D v->msti; + + err =3D nb->notifier_call(nb, SWITCHDEV_PORT_ATTR_SET, + &attr_info); + err =3D notifier_to_errno(err); + if (err) + return err; + } + } + + return 0; +} + static int br_switchdev_vlan_replay_one(struct notifier_block *nb, struct net_device *dev, @@ -425,6 +465,12 @@ static int br_switchdev_vlan_replay(struct net_device = *br_dev, return err; } =20 + if (adding) { + err =3D br_switchdev_vlan_attr_replay(br_dev, ctx, nb, extack); + if (err) + return err; + } + return 0; } =20 --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A734EC433F5 for ; Mon, 14 Mar 2022 09:53:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238239AbiCNJyq (ORCPT ); Mon, 14 Mar 2022 05:54:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238160AbiCNJyR (ORCPT ); Mon, 14 Mar 2022 05:54:17 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9589131510 for ; Mon, 14 Mar 2022 02:53:05 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id w12so26014256lfr.9 for ; Mon, 14 Mar 2022 02:53:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=EeUCfL1HTNVPenenIH8gFWE4yOM9UF0+zCq9TTJ9Rdk=; b=t49cngTtGoE+LnVS21dPKUidRKWEt6BaZrK9GTPcPLHL7ZPbqyfNLTxJylt9s4ttWf anQIXe8JIpcQVLB2gB+qqadP4MOfh78MeIOtm3gAmZy3TUm+BMSJFIwn9hdw207ZiN/D 3pCMdpEh+9m0ol3eNjqY9Sg9zs2oWFJuceKXTFBsLCOttH8vSlpsALstwg9R5bdBXV4X ziUwkoYEyUNIRo8mzmV27sQHTOWiN6VpoG+2/0f2EggzKyR3NBThipG7JEftaoTwLAmJ e7VNldyzsZepW+mOfQ5miKORBNFelLjcWEQFxUAw69WMl0vrsjf38Uus8EMSG+Wz29aJ vpag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=EeUCfL1HTNVPenenIH8gFWE4yOM9UF0+zCq9TTJ9Rdk=; b=mgLnEPvnyJGUUHQ5RiusQUmVmtMnUDZtGpiFNqNjGsEilACdefsTqz6zexopbJc5rR +Femxof1VlgruUWSgbX8l2af7pSpRQe9iO/M197JRJROtmaqXPWjIUnwfBs9QqjUtbny BxWngmWYvqQmOKWKVQtCQ6aQKg6hF82czB8G/g+aaRlcryUqlsuvA2wR3bCMpj3tmYx4 5Rt9xWW3jI45V7KfqPlDyq8SCp2O21qR61nmJjf/+a0SyLF6vr0WciXyj5Pd2AM5CCgr VQ6/SQpI9khEIsM3yKBo2EKKpY46jiHZrgjA7FUqMOtPQo5jWDqj+fRAO96wzxAtN4ta zzUg== X-Gm-Message-State: AOAM530RYX4JF8xy+JO46JECdZpxlLYz6ToEexmvfQCgsMw7r+/OPDaf X0+ISIJ3IfJkoJ9Yq0a1xGFcVQ== X-Google-Smtp-Source: ABdhPJw1ln9CM0a9E9yikaIvUI1LgBpKv3kPhVhHwoM7W25cFfsIB12m8B8/EGKfHErLxg1d+EPZaw== X-Received: by 2002:ac2:4c4c:0:b0:448:a156:504b with SMTP id o12-20020ac24c4c000000b00448a156504bmr338899lfk.99.1647251583471; Mon, 14 Mar 2022 02:53:03 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:03 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 06/14] net: bridge: mst: Notify switchdev drivers of MST state changes Date: Mon, 14 Mar 2022 10:52:23 +0100 Message-Id: <20220314095231.3486931-7-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Generate a switchdev notification whenever an MST state changes. This notification is keyed by the VLANs MSTI rather than the VID, since multiple VLANs may share the same MST instance. Signed-off-by: Tobias Waldekranz --- include/net/switchdev.h | 7 +++++++ net/bridge/br_mst.c | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 53dfa0f7cf5b..aa0171d5786d 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -19,6 +19,7 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, SWITCHDEV_ATTR_ID_PORT_STP_STATE, + SWITCHDEV_ATTR_ID_PORT_MST_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_MROUTER, @@ -32,6 +33,11 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_VLAN_MSTI, }; =20 +struct switchdev_mst_state { + u16 msti; + u8 state; +}; + struct switchdev_brport_flags { unsigned long val; unsigned long mask; @@ -50,6 +56,7 @@ struct switchdev_attr { void (*complete)(struct net_device *dev, int err, void *priv); union { u8 stp_state; /* PORT_STP_STATE */ + struct switchdev_mst_state mst_state; /* PORT_MST_STATE */ struct switchdev_brport_flags brport_flags; /* PORT_BRIDGE_FLAGS */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index 2f761d27d69e..7d16926a3a31 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -29,8 +29,17 @@ static void br_mst_vlan_set_state(struct net_bridge_port= *p, struct net_bridge_v =20 void br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state) { + struct switchdev_attr attr =3D { + .id =3D SWITCHDEV_ATTR_ID_PORT_MST_STATE, + .orig_dev =3D p->dev, + .u.mst_state =3D { + .msti =3D msti, + .state =3D state, + }, + }; struct net_bridge_vlan_group *vg; struct net_bridge_vlan *v; + int err; =20 vg =3D nbp_vlan_group(p); if (!vg) @@ -42,6 +51,17 @@ void br_mst_set_state(struct net_bridge_port *p, u16 mst= i, u8 state) =20 br_mst_vlan_set_state(p, v, state); } + + if (!msti) + /* MSTI 0 (CST) state changes are notified via the + * regular SWITCHDEV_ATTR_ID_PORT_STP_STATE. + */ + return; + + err =3D switchdev_port_attr_set(p->dev, &attr, NULL); + if (err && err !=3D -EOPNOTSUPP) + br_warn(p->br, "unable to offload MST state on %s in MSTI %u", + netdev_name(p->dev), msti); } =20 static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti) --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DAB09C433EF for ; Mon, 14 Mar 2022 09:53:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238255AbiCNJyy (ORCPT ); Mon, 14 Mar 2022 05:54:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238170AbiCNJyT (ORCPT ); Mon, 14 Mar 2022 05:54:19 -0400 Received: from mail-lj1-x22e.google.com (mail-lj1-x22e.google.com [IPv6:2a00:1450:4864:20::22e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F2E417E18 for ; Mon, 14 Mar 2022 02:53:07 -0700 (PDT) Received: by mail-lj1-x22e.google.com with SMTP id s25so20997330lji.5 for ; Mon, 14 Mar 2022 02:53:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=O8maULfjhyJR+IE8gj0IaXrGz2EfvemPnJwdNZ90D7o=; b=28vfELY4sLfx291r+KHjYUMVh4slEJAFpwd7s/KlUQxFnVAmbFaSwtOm3OKf3C1eSn sReh7nzukVteaRSK8ERsMSUREpQNso80rGWQCwHQjx5XE7WqK0iMrxCOp5WSMJXNoz/w IYJ8Lj5rU5uzdffqWkqyVd/lQeBWL9JLDoRcNwQ/htlc7YRU0IrrtTkxU8FZqVwZejyb YOJ/lbaq0fRsm6cnLC7UuOkZx/OgPbXrPJuXqE/SqEBCqpJlAcSy5BudQ2NA4oZIvxLJ NydZNST5RP+7rV9CSaZ/FjrrnwluUv0oJpeQn0sTmc0GpU35RTWjogDI/xw+pVp6iXNh NVqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=O8maULfjhyJR+IE8gj0IaXrGz2EfvemPnJwdNZ90D7o=; b=TJjl5HRafszdome1a2UtJOuIQtXm0Uej7iPZDply4a3F5p2yznjgkO9N1xrffGO52C FQsXjRhDEsxZlCFHnHHZVKi1wNyAxgojjEA57D5kod4iOrVKaaDyyIdjFKTLO6DCjgC2 OtHn57NmelJq42Q5nPM/1+6TmwuPGs3Iwq/WXLZ2/P0OPXNWe9oXJO4SK9c1hgW7/3g+ Y5/+xKdr0Z1mWnJeQqLs4Lhgij7r+VHY17+asG+IknzUO31Ba4XatS4+8jNmALSD8tLa MgVz87pk94+/aKsIBi20/pRet/tMHvU/oDybgsojhkV1qAoHldgSg94pqPWIcnuU5dKV 5qlQ== X-Gm-Message-State: AOAM530YI4MKlf8HOT7abyNS6LZvV31RLQskVJE1aUZaZPsW0hIHkgPE A3LPOf7soQiBBDznsKvU5qAWzw== X-Google-Smtp-Source: ABdhPJxYupU6c8PZ/GgL2NJ3edWebJC3iRJvPMPbhZyHLmF3r7fiPzJCP94eJb6WrsSxGUeNyid6Eg== X-Received: by 2002:a05:651c:1503:b0:244:c075:2103 with SMTP id e3-20020a05651c150300b00244c0752103mr13520132ljf.442.1647251584949; Mon, 14 Mar 2022 02:53:04 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:04 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 07/14] net: bridge: mst: Add helper to map an MSTI to a VID set Date: Mon, 14 Mar 2022 10:52:24 +0100 Message-Id: <20220314095231.3486931-8-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" br_mst_get_info answers the question: "On this bridge, which VIDs are mapped to the given MSTI?" This is useful in switchdev drivers, which might have to fan-out operations, relating to an MSTI, per VLAN. An example: When a port's MST state changes from forwarding to blocking, a driver may choose to flush the dynamic FDB entries on that port to get faster reconvergence of the network, but this should only be done in the VLANs that are managed by the MSTI in question. Signed-off-by: Tobias Waldekranz --- include/linux/if_bridge.h | 6 ++++++ net/bridge/br_mst.c | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 3aae023a9353..46e6327fef06 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -119,6 +119,7 @@ int br_vlan_get_info(const struct net_device *dev, u16 = vid, struct bridge_vlan_info *p_vinfo); int br_vlan_get_info_rcu(const struct net_device *dev, u16 vid, struct bridge_vlan_info *p_vinfo); +int br_mst_get_info(struct net_device *dev, u16 msti, unsigned long *vids); #else static inline bool br_vlan_enabled(const struct net_device *dev) { @@ -151,6 +152,11 @@ static inline int br_vlan_get_info_rcu(const struct ne= t_device *dev, u16 vid, { return -EINVAL; } +static inline int br_mst_get_info(struct net_device *dev, u16 msti, + unsigned long *vids) +{ + return -EINVAL; +} #endif =20 #if IS_ENABLED(CONFIG_BRIDGE) diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index 7d16926a3a31..eb18dbd5838f 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -13,6 +13,32 @@ =20 DEFINE_STATIC_KEY_FALSE(br_mst_used); =20 +int br_mst_get_info(struct net_device *dev, u16 msti, unsigned long *vids) +{ + struct net_bridge_vlan_group *vg; + struct net_bridge_vlan *v; + struct net_bridge *br; + + ASSERT_RTNL(); + + if (!netif_is_bridge_master(dev)) + return -EINVAL; + + br =3D netdev_priv(dev); + if (!br_opt_get(br, BROPT_MST_ENABLED)) + return -EINVAL; + + vg =3D br_vlan_group(br); + + list_for_each_entry(v, &vg->vlan_list, vlist) { + if (v->msti =3D=3D msti) + set_bit(v->vid, vids); + } + + return 0; +} +EXPORT_SYMBOL(br_mst_get_info); + static void br_mst_vlan_set_state(struct net_bridge_port *p, struct net_br= idge_vlan *v, u8 state) { --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 24465C433EF for ; Mon, 14 Mar 2022 09:53:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238261AbiCNJy5 (ORCPT ); Mon, 14 Mar 2022 05:54:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238164AbiCNJyT (ORCPT ); Mon, 14 Mar 2022 05:54:19 -0400 Received: from mail-lj1-x22e.google.com (mail-lj1-x22e.google.com [IPv6:2a00:1450:4864:20::22e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 17EAE34B9E for ; Mon, 14 Mar 2022 02:53:08 -0700 (PDT) Received: by mail-lj1-x22e.google.com with SMTP id r22so20985701ljd.4 for ; Mon, 14 Mar 2022 02:53:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=7lHeWPXEXWrCYgRFwcHwT0FA/DPhlUmoROl0FMGvSmk=; b=odLD55IR7r4dldGhulofhapMI5jrMDOi5q3CTbdcs8RDrs6wRN+BGPhnHaUKb6e22F 5T/KPRXcIqll0h+XN7kOP7NTJ+FcAu2741kVFIUHFc/MI/XMqGo2HWPLlIzALElpDQ1F Mm02O7POmyISL2X167BSom71A92PoigsuxFKBoZbi/rGd6xnJHDeiZvSsFKufA2Is8Jd edmH4YijZ+M6MsQPcX/RJeW0yjJB1KUThuEF34pbsNfLHBPuo6NB+yBLgL9zri/CR5jz zwtw9yb0Sd56tBr9EtRjMM99jeKPUvlHsEpM0/k4NlpP8yJFCLmfsSPyOhRSBV0YIN/S Ieww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=7lHeWPXEXWrCYgRFwcHwT0FA/DPhlUmoROl0FMGvSmk=; b=6+EQVhISmzHD/p5MEm42+izNHyJxrpIf3sHSoOhmgkbn3qSxb/DQ2Gfd4nGtGOu0xY 5ojlkT8CoFEiY/lP6NSq1/QY8lygc7y6VGRcyiYy0Hl9mlMs4cz0urYu6GHGMmJ8br4o ONWIx9Ym8d259cXhbkLsqBsdEvYvXG+Nu1qv+IhQu8kS1Y0Ff7Ee8jzseUzusF9GGg77 pB6FTC4JLvbzAPVSu/kaUEDzJe2oQOulQIlm36a0wx2lGhA/8Lg2oqIaU/A3w12Ogkxa Cy+Q1MPL5BmMiqP6D7251/+X5WmbAk1TvROgO8qotioN7V1g2Ek0i9ce5V7WgaaBDvAT kQ4w== X-Gm-Message-State: AOAM531HQyfe2PKJGOxY1WFFkdJkDB3H6Z0aCNTrzPqDTFGGGLdAHmH2 tMWoz08LfBX5pQWpsskcbVJzvg== X-Google-Smtp-Source: ABdhPJz1zlZc0EJq0fH1zUvvHQpnL1KiaYGOHaxUVmjz61r/PA6V4A+s1LKf2GzSFRNmZ3zS4kqUpA== X-Received: by 2002:a05:651c:2dc:b0:247:e451:48ae with SMTP id f28-20020a05651c02dc00b00247e45148aemr13813200ljo.248.1647251586691; Mon, 14 Mar 2022 02:53:06 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:06 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 08/14] net: bridge: mst: Add helper to check if MST is enabled Date: Mon, 14 Mar 2022 10:52:25 +0100 Message-Id: <20220314095231.3486931-9-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This is useful for switchdev drivers that might want to refuse to join a bridge where MST is enabled, if the hardware can't support it. Signed-off-by: Tobias Waldekranz --- include/linux/if_bridge.h | 5 +++++ net/bridge/br_mst.c | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 46e6327fef06..5dbab0a280a6 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -119,6 +119,7 @@ int br_vlan_get_info(const struct net_device *dev, u16 = vid, struct bridge_vlan_info *p_vinfo); int br_vlan_get_info_rcu(const struct net_device *dev, u16 vid, struct bridge_vlan_info *p_vinfo); +bool br_mst_enabled(struct net_device *dev); int br_mst_get_info(struct net_device *dev, u16 msti, unsigned long *vids); #else static inline bool br_vlan_enabled(const struct net_device *dev) @@ -152,6 +153,10 @@ static inline int br_vlan_get_info_rcu(const struct ne= t_device *dev, u16 vid, { return -EINVAL; } +static inline bool br_mst_enabled(struct net_device *dev) +{ + return false; +} static inline int br_mst_get_info(struct net_device *dev, u16 msti, unsigned long *vids) { diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c index eb18dbd5838f..e5ab2ce451c2 100644 --- a/net/bridge/br_mst.c +++ b/net/bridge/br_mst.c @@ -13,6 +13,15 @@ =20 DEFINE_STATIC_KEY_FALSE(br_mst_used); =20 +bool br_mst_enabled(struct net_device *dev) +{ + if (!netif_is_bridge_master(dev)) + return false; + + return br_opt_get(netdev_priv(dev), BROPT_MST_ENABLED); +} +EXPORT_SYMBOL(br_mst_enabled); + int br_mst_get_info(struct net_device *dev, u16 msti, unsigned long *vids) { struct net_bridge_vlan_group *vg; --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A265C433EF for ; Mon, 14 Mar 2022 09:53:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238265AbiCNJzB (ORCPT ); Mon, 14 Mar 2022 05:55:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238198AbiCNJyV (ORCPT ); Mon, 14 Mar 2022 05:54:21 -0400 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 682AC36316 for ; Mon, 14 Mar 2022 02:53:10 -0700 (PDT) Received: by mail-lf1-x12b.google.com with SMTP id w7so26061808lfd.6 for ; Mon, 14 Mar 2022 02:53:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=aX/tyKTTlC2fOBLF30DbEmug8lr4QMJWtdHHEsfB8ls=; b=6h+9N7Unq/C54UTeMTcGlVIoOSDDtrPDrd/GLYB+4EbFvaq3keKFdDepoPvlkE6OZC bQUwb8H/65AybyOLa2SXoECYsX/TcJYj8H9dUUTagAHpQDrkeoUkip6c6gvG1iWuc842 DlLAT4X+6dSQSG5O/dYp41qL/KzfQqougxmfU8SfSuX2FIluLvRdjmRoChbYXVJFLrOb 5nmYZSve3jhbTTGpznlkwPAdoG0NtaAd9yppN+ncTbeTkB01WfSZ48dPOcwyGjCSnJeZ ZipHSxFvcPapWKBhrucgczZMip5jCvKkxWuHCai5SFQiIyP+GpnciyhsUSaYw6qw4VM3 SWAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=aX/tyKTTlC2fOBLF30DbEmug8lr4QMJWtdHHEsfB8ls=; b=kMx1A2HfaiGwT6aVSBRH+jd6Gsfpz64Aht/fSsuf2LtK4MVOC4YAprxPJPweFGMSfB 2dVDQ+eBPqpKtD8bBi170nlF71EQ3drXuAeucv9k/JD/2sbXnDyceYK+dtzICSCHItG1 RYjciBmNyyHBq9VyC9mWhSiuIiV4tMrej9b+Jy4Eplkyxk2/Jrn5PKPLi3LEDRdy0S/S 90jRyTFG0ZBip56Xr18oAKKovcn000NvnIJzanap4UTllXyhukHdKdKdNJyyCr1+I/OP 9UF0xkqU8jUaw4wTi8CDKYWzc3EwpelKfsXTJSokjxL7QWapLU/bAq/kTWuGOKUaQVGn lTRg== X-Gm-Message-State: AOAM533TCs1qei7EwjlrHtVzGP6olt6icdMTZZucl6q9HEdNR/pFPGpy r9bvek10voVP6Xc7btlgAGdTFw== X-Google-Smtp-Source: ABdhPJyPiLr9FUGydQZpohRHqknpYmmbfxvdUg7o3WlDFO2inSS46l+nCZzb3aCjSbHOak56mpZQ2g== X-Received: by 2002:a05:6512:ba6:b0:448:9f0b:bc25 with SMTP id b38-20020a0565120ba600b004489f0bbc25mr898011lfv.256.1647251588383; Mon, 14 Mar 2022 02:53:08 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:07 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 09/14] net: dsa: Validate hardware support for MST Date: Mon, 14 Mar 2022 10:52:26 +0100 Message-Id: <20220314095231.3486931-10-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 --- net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 20 ++++++++++++++++++++ net/dsa/slave.c | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index f20bdd8ea0a8..2aba420696ef 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -234,6 +234,8 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool v= lan_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, diff --git a/net/dsa/port.c b/net/dsa/port.c index 58291df14cdb..1a17a0efa2fa 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -240,6 +240,10 @@ static int dsa_port_switchdev_sync_attrs(struct dsa_po= rt *dp, if (err && err !=3D -EOPNOTSUPP) return err; =20 + err =3D dsa_port_mst_enable(dp, br_mst_enabled(br), extack); + if (err && err !=3D -EOPNOTSUPP) + return err; + return 0; } =20 @@ -735,6 +739,22 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t = ageing_clock) return 0; } =20 +int dsa_port_mst_enable(struct dsa_port *dp, bool on, + struct netlink_ext_ack *extack) +{ + struct dsa_switch *ds =3D dp->ds; + + if (!on) + return 0; + + if (!dsa_port_can_configure_learning(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) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index a61a7c54af20..333f5702ea4f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -463,6 +463,12 @@ static int dsa_slave_port_attr_set(struct net_device *= dev, const void *ctx, =20 ret =3D 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 =3D 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; --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBB50C433EF for ; Mon, 14 Mar 2022 09:54:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238242AbiCNJzM (ORCPT ); Mon, 14 Mar 2022 05:55:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238200AbiCNJyX (ORCPT ); Mon, 14 Mar 2022 05:54:23 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2B2FB369F2 for ; Mon, 14 Mar 2022 02:53:11 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id bu29so26180545lfb.0 for ; Mon, 14 Mar 2022 02:53:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=Xug1BH6fNokmYBfp1m7lmzVoHZRMKG6TmFS0A8AYQqI=; b=gvIFP34YAnZboyufyNgDvH4eWj9u+O+mpEkbj54ZArxII18gk06pWhM3nAr+JpQlOH c92qb9/6wGIGougMYSfZScMD7p/yyVvPutR3IlorBAGy4vZxZmrg7NnVWHRmqym/v3b+ /9Nk4PRVz2twJrbxzq38jyUi3RmXqWkJuJKgMJvGuYGNQHSleNl7+bx2kqHJEjGkVeSH /y6BXoJK+LC3BR08K/77mH/rFZ08sdqBf+G936o3TWZBEp3kPOwm7/nIPOJpOWqqntWX q94NluUPApIEYrJsL1O6wRP0HTFlJey3CTdPz4Z7Jkkkzf4GhasZG22EUb6UnerSrKrM aykA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=Xug1BH6fNokmYBfp1m7lmzVoHZRMKG6TmFS0A8AYQqI=; b=Z2eK20D98jrFQurdb+xDj5enwQgEHMi6nU2LaMIqhO4RiWVIPSJwcNrbrLShs+QQ86 zDR0Ej34Jyb74FGIIKIxfty4oJmzI/FnQx7WF+fDlUWzbjw84vTiUvfNy7CA8Vl/G1Xz 17pJ+DcefQWqR5Pdjeo6K/8U3QWpRyQf05iPvWmTzzhc0Hs4cXFK99QvA6zYxCKW2MMb uTAQrgvpgMzjtHY78p3nbSF7Vq7Gt92T0z76WkqotCKlUZbb+WTKXogiG/hQmqAf9L0l /9/jSHo8eckqbkRygifn7stPUzut0InbaFVjBmM+9W2YOGJ65Q90Y2JdoFyvagnmE4gm jKPA== X-Gm-Message-State: AOAM531JeKoz3y6YH3CnX1BcgctBubIvnHqBskIDktveo3Vz6Kb0S7MN 1V7BacseVMBJ8O8PL9/JHYSzKQ== X-Google-Smtp-Source: ABdhPJwU0M50Tvhi2qkouOipvP6AfZbTBMjqM+CPa4vA9VHX45AOikwvdLBQ0Afw88UlWhcEmJnHtw== X-Received: by 2002:a05:6512:b03:b0:448:1e7c:8859 with SMTP id w3-20020a0565120b0300b004481e7c8859mr13565935lfu.110.1647251589737; Mon, 14 Mar 2022 02:53:09 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:09 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 10/14] net: dsa: Pass VLAN MSTI migration notifications to driver Date: Mon, 14 Mar 2022 10:52:27 +0100 Message-Id: <20220314095231.3486931-11-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add the usual trampoline functionality from the generic DSA layer down to the drivers for VLAN MSTI migrations. Signed-off-by: Tobias Waldekranz Reviewed-by: Vladimir Oltean --- include/net/dsa.h | 3 +++ net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 14 +++++++++++++- net/dsa/slave.c | 6 ++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 9d16505fc0e2..1ddaa2cc5842 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -964,6 +964,9 @@ struct dsa_switch_ops { struct netlink_ext_ack *extack); int (*port_vlan_del)(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan); + int (*vlan_msti_set)(struct dsa_switch *ds, struct dsa_bridge bridge, + const struct switchdev_vlan_msti *msti); + /* * Forwarding database */ diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 2aba420696ef..d90b4cf0c9d2 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -236,6 +236,8 @@ 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_vlan_msti(struct dsa_port *dp, + const struct switchdev_vlan_msti *msti); 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, diff --git a/net/dsa/port.c b/net/dsa/port.c index 1a17a0efa2fa..f6a822d854cc 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -747,7 +747,8 @@ int dsa_port_mst_enable(struct dsa_port *dp, bool on, if (!on) return 0; =20 - if (!dsa_port_can_configure_learning(dp)) { + if (!(ds->ops->vlan_msti_set && + dsa_port_can_configure_learning(dp))) { NL_SET_ERR_MSG_MOD(extack, "Hardware does not support MST"); return -EINVAL; } @@ -798,6 +799,17 @@ int dsa_port_bridge_flags(struct dsa_port *dp, return 0; } =20 +int dsa_port_vlan_msti(struct dsa_port *dp, + const struct switchdev_vlan_msti *msti) +{ + struct dsa_switch *ds =3D dp->ds; + + if (!ds->ops->vlan_msti_set) + return -EOPNOTSUPP; + + return ds->ops->vlan_msti_set(ds, *dp->bridge, msti); +} + int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu, bool targeted_match) { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 333f5702ea4f..cd2c57de9592 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -482,6 +482,12 @@ static int dsa_slave_port_attr_set(struct net_device *= dev, const void *ctx, =20 ret =3D dsa_port_bridge_flags(dp, attr->u.brport_flags, extack); break; + case SWITCHDEV_ATTR_ID_VLAN_MSTI: + if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) + return -EOPNOTSUPP; + + ret =3D dsa_port_vlan_msti(dp, &attr->u.vlan_msti); + break; default: ret =3D -EOPNOTSUPP; break; --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 114C1C433EF for ; Mon, 14 Mar 2022 09:54:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238244AbiCNJzQ (ORCPT ); Mon, 14 Mar 2022 05:55:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38506 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238204AbiCNJyY (ORCPT ); Mon, 14 Mar 2022 05:54:24 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0D32637A1A for ; Mon, 14 Mar 2022 02:53:12 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id 25so20964995ljv.10 for ; Mon, 14 Mar 2022 02:53:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=VPLokXA4rF+Ts9mahvqoV5g64lUVB9slMC7n8bkBW54=; b=bH1DOEyhDcXKVXTGes3loODY1GfjMVrj4RxhB/iKfZway5BT2B9E8m8HQWPG1FOOAf 6equ1WQhPhgVR9L5QKWSL4I2FOdapCl+1FAa8eBDjmID9mQ/afE7AEHwmY3vUYYk5z1b gEM/9JQyU8M7RiZi8y1u7MCBBgG1JufO8U7503knrQEWLcR8EVgi+j4WRIIppeF6lgP2 PBQMpWVcOfRBDKCVYZimYiktD24yEQAwC2OzbTO2I0Z55z5/MlGs1vZEF22BVDPDAJsr XIYkjZnxw4e3ZDinllrX68D9limDJv52+UvwSplyrIvlJTR5OrCtyQ2BjQL8skWxskUR qKXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=VPLokXA4rF+Ts9mahvqoV5g64lUVB9slMC7n8bkBW54=; b=AeGBUL2TXEn709EkoyTX6I2+U5vx1I4AR6kBRfnO59ljnCEN7aZwsH0Bhz7acY0I6K FPoG06PuJtWeDFpk4VMHQVktorD8+IMvZmY6QIpywvwrEge0sg06nU5IrLE3TkkAe7QN fxkY//0lMEq+ZebwnsnkalF8YIeOqrTa9nc+GBhUIhIKM50EhaHBvITx/8WbQoNaFUsc 6cWwydJT0SXx3Zl093pxFXNgCLOfBFE1JqiKzWG9bADapu6t3eDrlVBwrMmiMlMNMPUA 34QdxRTNiW3Gx4m4idBTteRV3e7MCNckiC2akErudGpJCXbMdJyo0b5ccuYHU7cIPTow Ia1Q== X-Gm-Message-State: AOAM531wfy2i7lTpZxgoluw4RX4M6aaMRcOKXfz91rLbaAReD/aDC7jq 4wmH+zV8roNA4k2Oon/FP7upWg== X-Google-Smtp-Source: ABdhPJxzTSBGBt9AW4I+k113a2N35M81EjEMeBOc7jhCSHs3u0PEqjzqqLOLyDSl0I78RbNq5EyqVw== X-Received: by 2002:a2e:9197:0:b0:246:35d1:36c5 with SMTP id f23-20020a2e9197000000b0024635d136c5mr13470980ljg.512.1647251591284; Mon, 14 Mar 2022 02:53:11 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:10 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 11/14] net: dsa: Handle MST state changes Date: Mon, 14 Mar 2022 10:52:28 +0100 Message-Id: <20220314095231.3486931-12-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add the usual trampoline functionality from the generic DSA layer down to the drivers for MST state changes. When a state changes to disabled/blocking/listening, make sure to fast age any dynamic entries in the affected VLANs (those controlled by the MSTI in question). Signed-off-by: Tobias Waldekranz --- include/net/dsa.h | 3 +++ net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 67 +++++++++++++++++++++++++++++++++++++++++++--- net/dsa/slave.c | 6 +++++ 4 files changed, 74 insertions(+), 4 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 1ddaa2cc5842..a171e7cdb3fe 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -945,7 +945,10 @@ struct dsa_switch_ops { struct dsa_bridge bridge); void (*port_stp_state_set)(struct dsa_switch *ds, int port, u8 state); + int (*port_mst_state_set)(struct dsa_switch *ds, int port, + const struct switchdev_mst_state *state); void (*port_fast_age)(struct dsa_switch *ds, int port); + void (*port_vlan_fast_age)(struct dsa_switch *ds, int port, u16 vid); int (*port_pre_bridge_flags)(struct dsa_switch *ds, int port, struct switchdev_brport_flags flags, struct netlink_ext_ack *extack); diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index d90b4cf0c9d2..2ae8996cf7c8 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -215,6 +215,8 @@ static inline struct net_device *dsa_master_find_slave(= struct net_device *dev, void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp, const struct dsa_device_ops *tag_ops); int dsa_port_set_state(struct dsa_port *dp, u8 state, bool do_fast_age); +int dsa_port_set_mst_state(struct dsa_port *dp, + const struct switchdev_mst_state *state); int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy); int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy); void dsa_port_disable_rt(struct dsa_port *dp); diff --git a/net/dsa/port.c b/net/dsa/port.c index f6a822d854cc..223681e03321 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -30,12 +30,11 @@ static int dsa_port_notify(const struct dsa_port *dp, u= nsigned long e, void *v) return dsa_tree_notify(dp->ds->dst, e, v); } =20 -static void dsa_port_notify_bridge_fdb_flush(const struct dsa_port *dp) +static void dsa_port_notify_bridge_fdb_flush(const struct dsa_port *dp, u1= 6 vid) { struct net_device *brport_dev =3D dsa_port_to_bridge_port(dp); struct switchdev_notifier_fdb_info info =3D { - /* flush all VLANs */ - .vid =3D 0, + .vid =3D vid, }; =20 /* When the port becomes standalone it has already left the bridge. @@ -57,7 +56,39 @@ static void dsa_port_fast_age(const struct dsa_port *dp) =20 ds->ops->port_fast_age(ds, dp->index); =20 - dsa_port_notify_bridge_fdb_flush(dp); + dsa_port_notify_bridge_fdb_flush(dp, 0); +} + +static void dsa_port_vlan_fast_age(const struct dsa_port *dp, u16 vid) +{ + struct dsa_switch *ds =3D dp->ds; + + if (!ds->ops->port_vlan_fast_age) + return; + + ds->ops->port_vlan_fast_age(ds, dp->index, vid); + + dsa_port_notify_bridge_fdb_flush(dp, vid); +} + +static void dsa_port_msti_fast_age(const struct dsa_port *dp, u16 msti) +{ + unsigned long *vids; + int vid; + + vids =3D bitmap_zalloc(VLAN_N_VID, 0); + if (!vids) + return; + + if (br_mst_get_info(dsa_port_bridge_dev_get(dp), msti, vids)) + goto out_free; + + for_each_set_bit(vid, vids, VLAN_N_VID) { + dsa_port_vlan_fast_age(dp, vid); + } + +out_free: + kfree(vids); } =20 static bool dsa_port_can_configure_learning(struct dsa_port *dp) @@ -118,6 +149,32 @@ static void dsa_port_set_state_now(struct dsa_port *dp= , u8 state, pr_err("DSA: failed to set STP state %u (%d)\n", state, err); } =20 +int dsa_port_set_mst_state(struct dsa_port *dp, + const struct switchdev_mst_state *state) +{ + struct dsa_switch *ds =3D dp->ds; + int err; + + if (!ds->ops->port_mst_state_set) + return -EOPNOTSUPP; + + err =3D ds->ops->port_mst_state_set(ds, dp->index, state); + if (err) + return err; + + if (dp->learning) { + switch (state->state) { + case BR_STATE_DISABLED: + case BR_STATE_BLOCKING: + case BR_STATE_LISTENING: + dsa_port_msti_fast_age(dp, state->msti); + break; + } + } + + return 0; +} + int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy) { struct dsa_switch *ds =3D dp->ds; @@ -748,6 +805,8 @@ int dsa_port_mst_enable(struct dsa_port *dp, bool on, return 0; =20 if (!(ds->ops->vlan_msti_set && + ds->ops->port_mst_state_set && + ds->ops->port_vlan_fast_age && dsa_port_can_configure_learning(dp))) { NL_SET_ERR_MSG_MOD(extack, "Hardware does not support MST"); return -EINVAL; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index cd2c57de9592..106b177ad1eb 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -450,6 +450,12 @@ static int dsa_slave_port_attr_set(struct net_device *= dev, const void *ctx, =20 ret =3D dsa_port_set_state(dp, attr->u.stp_state, true); break; + case SWITCHDEV_ATTR_ID_PORT_MST_STATE: + if (!dsa_port_offloads_bridge_port(dp, attr->orig_dev)) + return -EOPNOTSUPP; + + ret =3D dsa_port_set_mst_state(dp, &attr->u.mst_state); + break; case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING: if (!dsa_port_offloads_bridge_dev(dp, attr->orig_dev)) return -EOPNOTSUPP; --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA411C433EF for ; Mon, 14 Mar 2022 09:54:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238358AbiCNJza (ORCPT ); Mon, 14 Mar 2022 05:55:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238277AbiCNJzK (ORCPT ); Mon, 14 Mar 2022 05:55:10 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 46AF0387B8 for ; Mon, 14 Mar 2022 02:53:14 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id s25so26024012lfs.10 for ; Mon, 14 Mar 2022 02:53:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=bNDwoR5UyYVkMq4l68oZNNn7ga9pQEMw2kh4eXRN9FQ=; b=eviQCslMudPRm//5KDqhR9HLLYRQnoH8l8SG/+grXAZbDGcYZ7SRjyzWi1mx9lpca3 q/VsaPq/bxlSReCizrOb7dCvSe9wgSJqdDGQFq5wGAMpfYljyMLFMstCmQQVI05XjC3N 88Ss/G6XbwIWhWiUBmI/w84wlpCxTvdQPe2+1BFUBuaPTOo5YgJklg9fNYr7HA8SGF0d BO8nasvyChlaqijFFIoSZVZhZTaeR7PrJG2blP7M2Tf94hV8DQCecCpQYvgrTrxHYkMd Q8UV3dcYVed9L5UN+nfRvHtvemaXwRm76dXDyEwJ7oHh+m1PDC7yr66r+1gQQ2xdVdrb 7s/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=bNDwoR5UyYVkMq4l68oZNNn7ga9pQEMw2kh4eXRN9FQ=; b=v92ICeVD+I1J7VFuaMZAw7aLYos1vL4UMmC4pQuRExnQmhjh3lFIoLY07b7Uws9czK yEM8V0bZhu9ynHHLz/tkobZrVzXUYQR3btfEU79HM2t4zfEG8HQkk9hw0igI60wJifdA axv37cJcm53u7htDEvfwr7DlZm1IHZSV6ubohHAmAD98Agv0A5yCN8QDfqFMch4h+2Em 8hfH3EnuMbzG8Rn60VkxRuvbSpFGE7gx8VGGN3dkdTN3CvBvM1SAgfRVXuoWrWjmiIfz oK0jNIK+Po5sNj3GEYynNUdZu+73dvKCkLafGZDiDGFwNnCAICStlCtYDHTIKiD3nQ+x 3e9g== X-Gm-Message-State: AOAM532LwttMiSsRBxhIrR1+V0sB5XLX6GGp5gvx4PmTq5qOSCbTAMiO kIxyBe9G3iM/bj8ACUNpyxMoCA== X-Google-Smtp-Source: ABdhPJxCpAL1ppmtXMPW9MEc8JbQB2l5Ld02Jkb91dOBAlN0ki3tJEMMTQGEGj1FMN387yTAArK3iw== X-Received: by 2002:a05:6512:1105:b0:448:8f4e:d5d0 with SMTP id l5-20020a056512110500b004488f4ed5d0mr3798708lfg.182.1647251592847; Mon, 14 Mar 2022 02:53:12 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:12 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 12/14] net: dsa: mv88e6xxx: Disentangle STU from VTU Date: Mon, 14 Mar 2022 10:52:29 +0100 Message-Id: <20220314095231.3486931-13-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" In early LinkStreet silicon (e.g. 6095/6185), the per-VLAN STP states were kept in the VTU - there was no concept of a SID. Later, the information was split into two tables, where the VTU only tracked memberships and deferred the STP state tracking to the STU via a pointer (SID). This meant that a group of VLANs could share the same STU entry. Most likely, this was done to align with MSTP (802.1Q-2018, Clause 13), which is built on this principle. While the VTU is still 4k lines on most devices, the STU is capped at 64 entries. This means that the current stategy, updating STU info whenever a VTU entry is updated, can not easily support MSTP because: - The maximum number of VIDs would also be capped at 64, as we would have to allocate one SID for every VTU entry - even if many VLANs would effectively share the same MST. - MSTP updates would be unnecessarily slow as you would have to iterate over all VLANs that share the same MST. In order to support MSTP offloading in the future, manage the STU as a separate entity from the VTU. Only add support for newer hardware with separate VTU and STU. VTU-only devices can also be supported, but essentially this requires a software implementation of an STU (fanning out state changed to all VLANs tied to the same MST). Signed-off-by: Tobias Waldekranz --- drivers/net/dsa/mv88e6xxx/chip.c | 54 ++++ drivers/net/dsa/mv88e6xxx/chip.h | 24 ++ drivers/net/dsa/mv88e6xxx/global1.h | 10 + drivers/net/dsa/mv88e6xxx/global1_vtu.c | 311 ++++++++++++++---------- 4 files changed, 264 insertions(+), 135 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/c= hip.c index 84b90fc36c58..c14a62aa6a6c 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1791,6 +1791,33 @@ static int mv88e6xxx_atu_new(struct mv88e6xxx_chip *= chip, u16 *fid) return mv88e6xxx_g1_atu_flush(chip, *fid, true); } =20 +static int mv88e6xxx_stu_loadpurge(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry) +{ + if (!chip->info->ops->stu_loadpurge) + return -EOPNOTSUPP; + + return chip->info->ops->stu_loadpurge(chip, entry); +} + +static int mv88e6xxx_stu_setup(struct mv88e6xxx_chip *chip) +{ + struct mv88e6xxx_stu_entry stu =3D { + .valid =3D true, + .sid =3D 0 + }; + + if (!mv88e6xxx_has_stu(chip)) + return 0; + + /* Make sure that SID 0 is always valid. This is used by VTU + * entries that do not make use of the STU, e.g. when creating + * a VLAN upper on a port that is also part of a VLAN + * filtering bridge. + */ + return mv88e6xxx_stu_loadpurge(chip, &stu); +} + static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, u16 vid) { @@ -3427,6 +3454,13 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; =20 + /* Must be called after mv88e6xxx_vtu_setup (which flushes the + * VTU, thereby also flushing the STU). + */ + err =3D mv88e6xxx_stu_setup(chip); + if (err) + goto unlock; + /* Setup Switch Port Registers */ for (i =3D 0; i < mv88e6xxx_num_ports(chip); i++) { if (dsa_is_unused_port(ds, i)) @@ -3882,6 +3916,8 @@ static const struct mv88e6xxx_ops mv88e6097_ops =3D { .vtu_getnext =3D mv88e6352_g1_vtu_getnext, .vtu_loadpurge =3D mv88e6352_g1_vtu_loadpurge, .phylink_get_caps =3D mv88e6095_phylink_get_caps, + .stu_getnext =3D mv88e6352_g1_stu_getnext, + .stu_loadpurge =3D mv88e6352_g1_stu_loadpurge, .set_max_frame_size =3D mv88e6185_g1_set_max_frame_size, }; =20 @@ -4968,6 +5004,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops =3D { .atu_set_hash =3D mv88e6165_g1_atu_set_hash, .vtu_getnext =3D mv88e6352_g1_vtu_getnext, .vtu_loadpurge =3D mv88e6352_g1_vtu_loadpurge, + .stu_getnext =3D mv88e6352_g1_stu_getnext, + .stu_loadpurge =3D mv88e6352_g1_stu_loadpurge, .serdes_get_lane =3D mv88e6352_serdes_get_lane, .serdes_pcs_get_state =3D mv88e6352_serdes_pcs_get_state, .serdes_pcs_config =3D mv88e6352_serdes_pcs_config, @@ -5033,6 +5071,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops =3D { .atu_set_hash =3D mv88e6165_g1_atu_set_hash, .vtu_getnext =3D mv88e6390_g1_vtu_getnext, .vtu_loadpurge =3D mv88e6390_g1_vtu_loadpurge, + .stu_getnext =3D mv88e6390_g1_stu_getnext, + .stu_loadpurge =3D mv88e6390_g1_stu_loadpurge, .serdes_power =3D mv88e6390_serdes_power, .serdes_get_lane =3D mv88e6390_serdes_get_lane, /* Check status register pause & lpa register */ @@ -5098,6 +5138,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops =3D { .atu_set_hash =3D mv88e6165_g1_atu_set_hash, .vtu_getnext =3D mv88e6390_g1_vtu_getnext, .vtu_loadpurge =3D mv88e6390_g1_vtu_loadpurge, + .stu_getnext =3D mv88e6390_g1_stu_getnext, + .stu_loadpurge =3D mv88e6390_g1_stu_loadpurge, .serdes_power =3D mv88e6390_serdes_power, .serdes_get_lane =3D mv88e6390x_serdes_get_lane, .serdes_pcs_get_state =3D mv88e6390_serdes_pcs_get_state, @@ -5166,6 +5208,8 @@ static const struct mv88e6xxx_ops mv88e6393x_ops =3D { .atu_set_hash =3D mv88e6165_g1_atu_set_hash, .vtu_getnext =3D mv88e6390_g1_vtu_getnext, .vtu_loadpurge =3D mv88e6390_g1_vtu_loadpurge, + .stu_getnext =3D mv88e6390_g1_stu_getnext, + .stu_loadpurge =3D mv88e6390_g1_stu_loadpurge, .serdes_power =3D mv88e6393x_serdes_power, .serdes_get_lane =3D mv88e6393x_serdes_get_lane, .serdes_pcs_get_state =3D mv88e6393x_serdes_pcs_get_state, @@ -5234,6 +5278,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, .num_internal_phys =3D 8, .max_vid =3D 4095, + .max_sid =3D 63, .port_base_addr =3D 0x10, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5487,6 +5532,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 9, .num_gpio =3D 16, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5510,6 +5556,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 9, .num_gpio =3D 16, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5532,6 +5579,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5554,6 +5602,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5576,6 +5625,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5815,6 +5865,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 5, .num_gpio =3D 15, .max_vid =3D 4095, + .max_sid =3D 63, .port_base_addr =3D 0x10, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5839,6 +5890,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 9, .num_gpio =3D 16, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5863,6 +5915,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 9, .num_gpio =3D 16, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, @@ -5886,6 +5939,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .max_vid =3D 8191, + .max_sid =3D 63, .port_base_addr =3D 0x0, .phy_base_addr =3D 0x0, .global1_addr =3D 0x1b, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/c= hip.h index 30b92a265613..be654be69982 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -20,6 +20,7 @@ =20 #define EDSA_HLEN 8 #define MV88E6XXX_N_FID 4096 +#define MV88E6XXX_N_SID 64 =20 #define MV88E6XXX_FID_STANDALONE 0 #define MV88E6XXX_FID_BRIDGED 1 @@ -130,6 +131,7 @@ struct mv88e6xxx_info { unsigned int num_internal_phys; unsigned int num_gpio; unsigned int max_vid; + unsigned int max_sid; unsigned int port_base_addr; unsigned int phy_base_addr; unsigned int global1_addr; @@ -181,6 +183,12 @@ struct mv88e6xxx_vtu_entry { bool valid; bool policy; u8 member[DSA_MAX_PORTS]; + u8 state[DSA_MAX_PORTS]; /* Older silicon has no STU */ +}; + +struct mv88e6xxx_stu_entry { + u8 sid; + bool valid; u8 state[DSA_MAX_PORTS]; }; =20 @@ -602,6 +610,12 @@ struct mv88e6xxx_ops { int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry); =20 + /* Spanning Tree Unit operations */ + int (*stu_getnext)(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); + int (*stu_loadpurge)(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); + /* GPIO operations */ const struct mv88e6xxx_gpio_ops *gpio_ops; =20 @@ -700,6 +714,11 @@ struct mv88e6xxx_hw_stat { int type; }; =20 +static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip) +{ + return chip->info->max_sid > 0; +} + static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip) { return chip->info->pvt; @@ -730,6 +749,11 @@ static inline unsigned int mv88e6xxx_max_vid(struct mv= 88e6xxx_chip *chip) return chip->info->max_vid; } =20 +static inline unsigned int mv88e6xxx_max_sid(struct mv88e6xxx_chip *chip) +{ + return chip->info->max_sid; +} + static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip) { return GENMASK((s32)mv88e6xxx_num_ports(chip) - 1, 0); diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xx= x/global1.h index 2c1607c858a1..65958b2a0d3a 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.h +++ b/drivers/net/dsa/mv88e6xxx/global1.h @@ -348,6 +348,16 @@ int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *ch= ip, int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry); int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip); +int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); +int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); +int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); +int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); +int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry); int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip); void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip); int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid); diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88= e6xxx/global1_vtu.c index b1bd9274a562..38e18f5811bf 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c @@ -44,8 +44,7 @@ static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_ch= ip *chip, =20 /* Offset 0x03: VTU SID Register */ =20 -static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) +static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, u8 *sid) { u16 val; int err; @@ -54,15 +53,14 @@ static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_c= hip *chip, if (err) return err; =20 - entry->sid =3D val & MV88E6352_G1_VTU_SID_MASK; + *sid =3D val & MV88E6352_G1_VTU_SID_MASK; =20 return 0; } =20 -static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) +static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, u8 sid) { - u16 val =3D entry->sid & MV88E6352_G1_VTU_SID_MASK; + u16 val =3D sid & MV88E6352_G1_VTU_SID_MASK; =20 return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val); } @@ -91,7 +89,7 @@ static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chi= p, u16 op) /* Offset 0x06: VTU VID Register */ =20 static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) + bool *valid, u16 *vid) { u16 val; int err; @@ -100,25 +98,28 @@ static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_= chip *chip, if (err) return err; =20 - entry->vid =3D val & 0xfff; + if (vid) { + *vid =3D val & 0xfff; =20 - if (val & MV88E6390_G1_VTU_VID_PAGE) - entry->vid |=3D 0x1000; + if (val & MV88E6390_G1_VTU_VID_PAGE) + *vid |=3D 0x1000; + } =20 - entry->valid =3D !!(val & MV88E6XXX_G1_VTU_VID_VALID); + if (valid) + *valid =3D !!(val & MV88E6XXX_G1_VTU_VID_VALID); =20 return 0; } =20 static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) + bool valid, u16 vid) { - u16 val =3D entry->vid & 0xfff; + u16 val =3D vid & 0xfff; =20 - if (entry->vid & 0x1000) + if (vid & 0x1000) val |=3D MV88E6390_G1_VTU_VID_PAGE; =20 - if (entry->valid) + if (valid) val |=3D MV88E6XXX_G1_VTU_VID_VALID; =20 return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val); @@ -147,7 +148,7 @@ static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6= xxx_chip *chip, } =20 static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) + u8 *member, u8 *state) { u16 regs[3]; int err; @@ -160,36 +161,20 @@ static int mv88e6185_g1_vtu_data_read(struct mv88e6xx= x_chip *chip, /* Extract MemberTag data */ for (i =3D 0; i < mv88e6xxx_num_ports(chip); ++i) { unsigned int member_offset =3D (i % 4) * 4; + unsigned int state_offset =3D member_offset + 2; =20 - entry->member[i] =3D (regs[i / 4] >> member_offset) & 0x3; - } - - return 0; -} - -static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) -{ - u16 regs[3]; - int err; - int i; - - err =3D mv88e6185_g1_vtu_stu_data_read(chip, regs); - if (err) - return err; + if (member) + member[i] =3D (regs[i / 4] >> member_offset) & 0x3; =20 - /* Extract PortState data */ - for (i =3D 0; i < mv88e6xxx_num_ports(chip); ++i) { - unsigned int state_offset =3D (i % 4) * 4 + 2; - - entry->state[i] =3D (regs[i / 4] >> state_offset) & 0x3; + if (state) + state[i] =3D (regs[i / 4] >> state_offset) & 0x3; } =20 return 0; } =20 static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) + u8 *member, u8 *state) { u16 regs[3] =3D { 0 }; int i; @@ -199,8 +184,11 @@ static int mv88e6185_g1_vtu_data_write(struct mv88e6xx= x_chip *chip, unsigned int member_offset =3D (i % 4) * 4; unsigned int state_offset =3D member_offset + 2; =20 - regs[i / 4] |=3D (entry->member[i] & 0x3) << member_offset; - regs[i / 4] |=3D (entry->state[i] & 0x3) << state_offset; + if (member) + regs[i / 4] |=3D (member[i] & 0x3) << member_offset; + + if (state) + regs[i / 4] |=3D (state[i] & 0x3) << state_offset; } =20 /* Write all 3 VTU/STU Data registers */ @@ -268,48 +256,6 @@ static int mv88e6390_g1_vtu_data_write(struct mv88e6xx= x_chip *chip, u8 *data) =20 /* VLAN Translation Unit Operations */ =20 -static int mv88e6xxx_g1_vtu_stu_getnext(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) -{ - int err; - - err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry); - if (err) - return err; - - err =3D mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT); - if (err) - return err; - - err =3D mv88e6xxx_g1_vtu_sid_read(chip, entry); - if (err) - return err; - - return mv88e6xxx_g1_vtu_vid_read(chip, entry); -} - -static int mv88e6xxx_g1_vtu_stu_get(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *vtu) -{ - struct mv88e6xxx_vtu_entry stu; - int err; - - err =3D mv88e6xxx_g1_vtu_sid_read(chip, vtu); - if (err) - return err; - - stu.sid =3D vtu->sid - 1; - - err =3D mv88e6xxx_g1_vtu_stu_getnext(chip, &stu); - if (err) - return err; - - if (stu.sid !=3D vtu->sid || !stu.valid) - return -EINVAL; - - return 0; -} - int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip, struct mv88e6xxx_vtu_entry *entry) { @@ -327,7 +273,7 @@ int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chi= p, * write the VID only once, when the entry is given as invalid. */ if (!entry->valid) { - err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_vid_write(chip, false, entry->vid); if (err) return err; } @@ -336,7 +282,7 @@ int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chi= p, if (err) return err; =20 - return mv88e6xxx_g1_vtu_vid_read(chip, entry); + return mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, &entry->vid); } =20 int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, @@ -350,11 +296,7 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *ch= ip, return err; =20 if (entry->valid) { - err =3D mv88e6185_g1_vtu_data_read(chip, entry); - if (err) - return err; - - err =3D mv88e6185_g1_stu_data_read(chip, entry); + err =3D mv88e6185_g1_vtu_data_read(chip, entry->member, entry->state); if (err) return err; =20 @@ -384,7 +326,7 @@ int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chi= p, return err; =20 if (entry->valid) { - err =3D mv88e6185_g1_vtu_data_read(chip, entry); + err =3D mv88e6185_g1_vtu_data_read(chip, entry->member, NULL); if (err) return err; =20 @@ -392,12 +334,7 @@ int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *ch= ip, if (err) return err; =20 - /* Fetch VLAN PortState data from the STU */ - err =3D mv88e6xxx_g1_vtu_stu_get(chip, entry); - if (err) - return err; - - err =3D mv88e6185_g1_stu_data_read(chip, entry); + err =3D mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid); if (err) return err; } @@ -420,16 +357,11 @@ int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *c= hip, if (err) return err; =20 - /* Fetch VLAN PortState data from the STU */ - err =3D mv88e6xxx_g1_vtu_stu_get(chip, entry); - if (err) - return err; - - err =3D mv88e6390_g1_vtu_data_read(chip, entry->state); + err =3D mv88e6xxx_g1_vtu_fid_read(chip, entry); if (err) return err; =20 - err =3D mv88e6xxx_g1_vtu_fid_read(chip, entry); + err =3D mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid); if (err) return err; } @@ -447,12 +379,12 @@ int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip = *chip, if (err) return err; =20 - err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid); if (err) return err; =20 if (entry->valid) { - err =3D mv88e6185_g1_vtu_data_write(chip, entry); + err =3D mv88e6185_g1_vtu_data_write(chip, entry->member, entry->state); if (err) return err; =20 @@ -479,27 +411,21 @@ int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip = *chip, if (err) return err; =20 - err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid); if (err) return err; =20 if (entry->valid) { - /* Write MemberTag and PortState data */ - err =3D mv88e6185_g1_vtu_data_write(chip, entry); - if (err) - return err; - - err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry); + /* Write MemberTag data */ + err =3D mv88e6185_g1_vtu_data_write(chip, entry->member, NULL); if (err) return err; =20 - /* Load STU entry */ - err =3D mv88e6xxx_g1_vtu_op(chip, - MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE); + err =3D mv88e6xxx_g1_vtu_fid_write(chip, entry); if (err) return err; =20 - err =3D mv88e6xxx_g1_vtu_fid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); if (err) return err; } @@ -517,41 +443,113 @@ int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip= *chip, if (err) return err; =20 - err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid); if (err) return err; =20 if (entry->valid) { - /* Write PortState data */ - err =3D mv88e6390_g1_vtu_data_write(chip, entry->state); + /* Write MemberTag data */ + err =3D mv88e6390_g1_vtu_data_write(chip, entry->member); if (err) return err; =20 - err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_fid_write(chip, entry); if (err) return err; =20 - /* Load STU entry */ - err =3D mv88e6xxx_g1_vtu_op(chip, - MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE); + err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); if (err) return err; + } =20 - /* Write MemberTag data */ - err =3D mv88e6390_g1_vtu_data_write(chip, entry->member); + /* Load/Purge VTU entry */ + return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE); +} + +int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip) +{ + int err; + + err =3D mv88e6xxx_g1_vtu_op_wait(chip); + if (err) + return err; + + return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL); +} + +/* Spanning Tree Unit Operations */ + +int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry) +{ + int err; + + err =3D mv88e6xxx_g1_vtu_op_wait(chip); + if (err) + return err; + + /* To get the next higher active SID, the STU GetNext operation can be + * started again without setting the SID registers since it already + * contains the last SID. + * + * To save a few hardware accesses and abstract this to the caller, + * write the SID only once, when the entry is given as invalid. + */ + if (!entry->valid) { + err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); if (err) return err; + } =20 - err =3D mv88e6xxx_g1_vtu_fid_write(chip, entry); + err =3D mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT); + if (err) + return err; + + err =3D mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL); + if (err) + return err; + + if (entry->valid) { + err =3D mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid); if (err) return err; } =20 - /* Load/Purge VTU entry */ - return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE); + return 0; } =20 -int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip) +int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry) +{ + int err; + + err =3D mv88e6xxx_g1_stu_getnext(chip, entry); + if (err) + return err; + + if (!entry->valid) + return 0; + + return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state); +} + +int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry) +{ + int err; + + err =3D mv88e6xxx_g1_stu_getnext(chip, entry); + if (err) + return err; + + if (!entry->valid) + return 0; + + return mv88e6390_g1_vtu_data_read(chip, entry->state); +} + +int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry) { int err; =20 @@ -559,16 +557,59 @@ int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chi= p) if (err) return err; =20 - return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL); + err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0); + if (err) + return err; + + err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); + if (err) + return err; + + if (entry->valid) { + err =3D mv88e6185_g1_vtu_data_write(chip, NULL, entry->state); + if (err) + return err; + } + + /* Load/Purge STU entry */ + return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE); +} + +int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_stu_entry *entry) +{ + int err; + + err =3D mv88e6xxx_g1_vtu_op_wait(chip); + if (err) + return err; + + err =3D mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0); + if (err) + return err; + + err =3D mv88e6xxx_g1_vtu_sid_write(chip, entry->sid); + if (err) + return err; + + if (entry->valid) { + err =3D mv88e6390_g1_vtu_data_write(chip, entry->state); + if (err) + return err; + } + + /* Load/Purge STU entry */ + return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE); } =20 +/* VTU Violation Management */ + static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_= id) { struct mv88e6xxx_chip *chip =3D dev_id; - struct mv88e6xxx_vtu_entry entry; + u16 val, vid; int spid; int err; - u16 val; =20 mv88e6xxx_reg_lock(chip); =20 @@ -580,7 +621,7 @@ static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(= int irq, void *dev_id) if (err) goto out; =20 - err =3D mv88e6xxx_g1_vtu_vid_read(chip, &entry); + err =3D mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid); if (err) goto out; =20 @@ -588,13 +629,13 @@ static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_f= n(int irq, void *dev_id) =20 if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) { dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source = port %d\n", - entry.vid, spid); + vid, spid); chip->ports[spid].vtu_member_violation++; } =20 if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) { dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source po= rt %d\n", - entry.vid, spid); + vid, spid); chip->ports[spid].vtu_miss_violation++; } =20 --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21CA9C433EF for ; Mon, 14 Mar 2022 09:54:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238204AbiCNJzd (ORCPT ); Mon, 14 Mar 2022 05:55:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238287AbiCNJzL (ORCPT ); Mon, 14 Mar 2022 05:55:11 -0400 Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [IPv6:2a00:1450:4864:20::229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6796338BFD for ; Mon, 14 Mar 2022 02:53:16 -0700 (PDT) Received: by mail-lj1-x229.google.com with SMTP id q5so20948283ljb.11 for ; Mon, 14 Mar 2022 02:53:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=9aG6JPCK/sc9cnjNg+7v1niwfwPA6zUyJ/dRYHoXrdI=; b=0I5otOva0fgSx49BQflmsCPnGUJrVHjKnU72vcF+1AWbTFvdnA89IqhKncpiV/xfnQ kXihmTgg3WCZsfWwO5v58CAIYLmsztDmHAB9VuuU5UZ1N/GI4z8d5g8yBBlx/H06sU1O mds4GLBdXcRcIAj9Xz2y17Cac6crwXXtnYnPSiyiPirItTIekL1NzdEyRNaGNvlp9wdM 9HTucRP+V3VAwSYTQXBH2OFi5yFC+sdVnJot6QznxJwl8WuaHmYJ63ocCqwGoBYPipZV ScPP/N+GOMPv6nKkY0F63fvaAa4ZCFQBlzX9h3oRsroty0GY8ZujqnmSSnrSFY52OOsj CPLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=9aG6JPCK/sc9cnjNg+7v1niwfwPA6zUyJ/dRYHoXrdI=; b=Kb0WavbU+JCEteE4SzYJlw+u4bDoZaI0y44sHl8HFlgivPMd1wygKHS3uAMVUWoCyj qUyDPUX+84hFEaYtcr4BiEa0Cf26vqfRGqZQ9QR2MZXcbjn159sluw28DBSi4v9e6HxB 5EHnkUxgnkSTgf58OM4w9CGx1SI14o3Gd6FCqkpjSZlhJRiC1vtAgDetJZ+7b5pps/uT hrpRZqyH/aieIqpseuZ4ct6iQBDGsvFCUmf5AkEB0uZl8FNUshoPsK7fNYsQJidIhtyG NAijfId0cPhZ1eL1LIaMKxn+OXh7isNUZ9mejdtBn8TnPgytI2Jz5WRX84b06zoFQ6fM Ca3w== X-Gm-Message-State: AOAM533h34tBpBzoo9qNvJQscysaWYBLjXPyR6QwarZLPR6l+ttg9Tos /KQF9ouS1sUCiA2qbDivRH13Kl0ry52j11Yb X-Google-Smtp-Source: ABdhPJyhAB1AYSWqcXzWFsWoNHm93zY/FGMkEPWDNDQVt+VUG1TbyTV2cwcpxKhQrjxhb2HcJ7VIVQ== X-Received: by 2002:a2e:9997:0:b0:247:ec9c:8efb with SMTP id w23-20020a2e9997000000b00247ec9c8efbmr13474171lji.297.1647251594668; Mon, 14 Mar 2022 02:53:14 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:14 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 13/14] net: dsa: mv88e6xxx: Export STU as devlink region Date: Mon, 14 Mar 2022 10:52:30 +0100 Message-Id: <20220314095231.3486931-14-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Export the raw STU data in a devlink region so that it can be inspected from userspace and compared to the current bridge configuration. Signed-off-by: Tobias Waldekranz --- drivers/net/dsa/mv88e6xxx/chip.h | 1 + drivers/net/dsa/mv88e6xxx/devlink.c | 94 +++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/c= hip.h index be654be69982..6d4daa24d3e5 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -287,6 +287,7 @@ enum mv88e6xxx_region_id { MV88E6XXX_REGION_GLOBAL2, MV88E6XXX_REGION_ATU, MV88E6XXX_REGION_VTU, + MV88E6XXX_REGION_STU, MV88E6XXX_REGION_PVT, =20 _MV88E6XXX_REGION_MAX, diff --git a/drivers/net/dsa/mv88e6xxx/devlink.c b/drivers/net/dsa/mv88e6xx= x/devlink.c index 381068395c63..1266eabee086 100644 --- a/drivers/net/dsa/mv88e6xxx/devlink.c +++ b/drivers/net/dsa/mv88e6xxx/devlink.c @@ -503,6 +503,85 @@ static int mv88e6xxx_region_vtu_snapshot(struct devlin= k *dl, return 0; } =20 +/** + * struct mv88e6xxx_devlink_stu_entry - Devlink STU entry + * @sid: Global1/3: SID, unknown filters and learning. + * @vid: Global1/6: Valid bit. + * @data: Global1/7-9: Membership data and priority override. + * @resvd: Reserved. In case we forgot something. + * + * The STU entry format varies between chipset generations. Peridot + * and Amethyst packs the STU data into Global1/7-8. Older silicon + * spreads the information across all three VTU data registers - + * inheriting the layout of even older hardware that had no STU at + * all. Since this is a low-level debug interface, copy all data + * verbatim and defer parsing to the consumer. + */ +struct mv88e6xxx_devlink_stu_entry { + u16 sid; + u16 vid; + u16 data[3]; + u16 resvd; +}; + +static int mv88e6xxx_region_stu_snapshot(struct devlink *dl, + const struct devlink_region_ops *ops, + struct netlink_ext_ack *extack, + u8 **data) +{ + struct mv88e6xxx_devlink_stu_entry *table, *entry; + struct dsa_switch *ds =3D dsa_devlink_to_ds(dl); + struct mv88e6xxx_chip *chip =3D ds->priv; + struct mv88e6xxx_stu_entry stu; + int err; + + table =3D kcalloc(mv88e6xxx_max_sid(chip) + 1, + sizeof(struct mv88e6xxx_devlink_stu_entry), + GFP_KERNEL); + if (!table) + return -ENOMEM; + + entry =3D table; + stu.sid =3D mv88e6xxx_max_sid(chip); + stu.valid =3D false; + + mv88e6xxx_reg_lock(chip); + + do { + err =3D mv88e6xxx_g1_stu_getnext(chip, &stu); + if (err) + break; + + if (!stu.valid) + break; + + err =3D err ? : mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, + &entry->sid); + err =3D err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, + &entry->vid); + err =3D err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1, + &entry->data[0]); + err =3D err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA2, + &entry->data[1]); + err =3D err ? : mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA3, + &entry->data[2]); + if (err) + break; + + entry++; + } while (stu.sid < mv88e6xxx_max_sid(chip)); + + mv88e6xxx_reg_unlock(chip); + + if (err) { + kfree(table); + return err; + } + + *data =3D (u8 *)table; + return 0; +} + static int mv88e6xxx_region_pvt_snapshot(struct devlink *dl, const struct devlink_region_ops *ops, struct netlink_ext_ack *extack, @@ -605,6 +684,12 @@ static struct devlink_region_ops mv88e6xxx_region_vtu_= ops =3D { .destructor =3D kfree, }; =20 +static struct devlink_region_ops mv88e6xxx_region_stu_ops =3D { + .name =3D "stu", + .snapshot =3D mv88e6xxx_region_stu_snapshot, + .destructor =3D kfree, +}; + static struct devlink_region_ops mv88e6xxx_region_pvt_ops =3D { .name =3D "pvt", .snapshot =3D mv88e6xxx_region_pvt_snapshot, @@ -640,6 +725,11 @@ static struct mv88e6xxx_region mv88e6xxx_regions[] =3D= { .ops =3D &mv88e6xxx_region_vtu_ops /* calculated at runtime */ }, + [MV88E6XXX_REGION_STU] =3D { + .ops =3D &mv88e6xxx_region_stu_ops, + .cond =3D mv88e6xxx_has_stu, + /* calculated at runtime */ + }, [MV88E6XXX_REGION_PVT] =3D { .ops =3D &mv88e6xxx_region_pvt_ops, .size =3D MV88E6XXX_MAX_PVT_ENTRIES * sizeof(u16), @@ -706,6 +796,10 @@ int mv88e6xxx_setup_devlink_regions_global(struct dsa_= switch *ds) size =3D (mv88e6xxx_max_vid(chip) + 1) * sizeof(struct mv88e6xxx_devlink_vtu_entry); break; + case MV88E6XXX_REGION_STU: + size =3D (mv88e6xxx_max_sid(chip) + 1) * + sizeof(struct mv88e6xxx_devlink_stu_entry); + break; } =20 region =3D dsa_devlink_region_create(ds, ops, 1, size); --=20 2.25.1 From nobody Tue Jun 23 01:16:20 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05203C433FE for ; Mon, 14 Mar 2022 09:54:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238296AbiCNJze (ORCPT ); Mon, 14 Mar 2022 05:55:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41814 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238288AbiCNJzL (ORCPT ); Mon, 14 Mar 2022 05:55:11 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C2C938D8F for ; Mon, 14 Mar 2022 02:53:18 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id s25so20997960lji.5 for ; Mon, 14 Mar 2022 02:53:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=waldekranz-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:organization:content-transfer-encoding; bh=EhqGuJqqtp9wtuhSiVXt/o5grLaHVr4b0QqzceZCUO8=; b=RJa3/5K5cCDl6EjFcQwfzqk/UcKzuV733YpHO1tIlGr8G8TfvlqiLBaFw5o8IGW6Gc cqjOSwteauUJ5Hkth30AhD7p3H0YTs1M/kkCVVVoT2t1S0FUwVxa80JVNjNENM6dmrlq QIe6ZiQ1MnjuDlJ9+sjvF3I/KIV0yarwG2f0OFT3St2q7QMAX+vJE2CZuh8remUW8zT9 sjZCJuwa65WRGm4AL6RvOiBKuKPDsgWE38hao2IROUxuHkD1v2PA7aHF/uQDwMrimK6i kM+/knTp4IbzmlAwqwy53A9aW/b6Ph+Sd484UGqQJ/Abn08QumzCTKznDrNi2VzWv7x9 pc1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:organization:content-transfer-encoding; bh=EhqGuJqqtp9wtuhSiVXt/o5grLaHVr4b0QqzceZCUO8=; b=kmdr4F8wkpgmfTzM96nQ/Hc/DfW8GxkJaUnkoYagZlsSwuHtgvfMv9zFRcKx/50Bra +xYWWqS3HrtizTGDa597E9PPK3Xz38/IiIql/gCYqUjIt89tDJE/LybRK3k0zROxyOTp 12mF6z12duc1nHLvkMRA15AFQcdYYFhXd0dy8FL7txnZV4SYX4SCUxOo2bKuGtXieWK5 oPE/q65jC7h8p66NMbJTwADl4pcOcY9Ql3t82QpKh1kHwz1mfVB/pYqECbJL2nPALrPO tOD/zc3hY32qqbjmoHUnaB8JfUH8lYJPkeKCx7tgs8eNe/Xyyce3gFPnygnbLoldY/TV tMdQ== X-Gm-Message-State: AOAM5321ndH66shV5C6p1leRQy0HT4ATduEfh7kxJk8omB9b9tv7BJA4 +sEk08qXXIxFnpbrxycjj1kvZA== X-Google-Smtp-Source: ABdhPJx+Bm2nE+m0aEApfu+ftVJZhVBFOe9kvxEBDqF4k0QtCWa1a+gyVpQdN7tqFeWdRzVG9Wdosg== X-Received: by 2002:a2e:aa0b:0:b0:249:1e19:67f8 with SMTP id bf11-20020a2eaa0b000000b002491e1967f8mr9448720ljb.390.1647251596605; Mon, 14 Mar 2022 02:53:16 -0700 (PDT) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id b3-20020a056512304300b004488e49f2fasm984870lfb.129.2022.03.14.02.53.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Mar 2022 02:53:16 -0700 (PDT) From: Tobias Waldekranz To: davem@davemloft.net, kuba@kernel.org Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Vladimir Oltean , Jiri Pirko , Ivan Vecera , Roopa Prabhu , Nikolay Aleksandrov , Russell King , Ido Schimmel , Petr Machata , Cooper Lees , Matt Johnston , linux-kernel@vger.kernel.org, netdev@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [PATCH v3 net-next 14/14] net: dsa: mv88e6xxx: MST Offloading Date: Mon, 14 Mar 2022 10:52:31 +0100 Message-Id: <20220314095231.3486931-15-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220314095231.3486931-1-tobias@waldekranz.com> References: <20220314095231.3486931-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Allocate a SID in the STU for each MSTID in use by a bridge and handle the mapping of MSTIDs to VLANs using the SID field of each VTU entry. Signed-off-by: Tobias Waldekranz --- drivers/net/dsa/mv88e6xxx/chip.c | 251 ++++++++++++++++++++++++++++++- drivers/net/dsa/mv88e6xxx/chip.h | 13 ++ 2 files changed, 257 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/c= hip.c index c14a62aa6a6c..c23dbf37aeec 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1667,24 +1667,32 @@ static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chi= p *chip) return 0; } =20 -static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) +static void mv88e6xxx_port_fast_age_fid(struct mv88e6xxx_chip *chip, int p= ort, + u16 fid) { - struct mv88e6xxx_chip *chip =3D ds->priv; int err; =20 - if (dsa_to_port(ds, port)->lag) + if (dsa_to_port(chip->ds, port)->lag) /* Hardware is incapable of fast-aging a LAG through a * regular ATU move operation. Until we have something * more fancy in place this is a no-op. */ return; =20 - mv88e6xxx_reg_lock(chip); - err =3D mv88e6xxx_g1_atu_remove(chip, 0, port, false); - mv88e6xxx_reg_unlock(chip); + err =3D mv88e6xxx_g1_atu_remove(chip, fid, port, false); =20 if (err) - dev_err(ds->dev, "p%d: failed to flush ATU\n", port); + dev_err(chip->ds->dev, "p%d: failed to flush ATU (FID %u)\n", + port, fid); +} + +static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) +{ + struct mv88e6xxx_chip *chip =3D ds->priv; + + mv88e6xxx_reg_lock(chip); + mv88e6xxx_port_fast_age_fid(chip, port, 0); + mv88e6xxx_reg_unlock(chip); } =20 static int mv88e6xxx_vtu_setup(struct mv88e6xxx_chip *chip) @@ -1818,6 +1826,159 @@ static int mv88e6xxx_stu_setup(struct mv88e6xxx_chi= p *chip) return mv88e6xxx_stu_loadpurge(chip, &stu); } =20 +static int mv88e6xxx_sid_get(struct mv88e6xxx_chip *chip, u8 *sid) +{ + DECLARE_BITMAP(busy, MV88E6XXX_N_SID) =3D { 0 }; + struct mv88e6xxx_mst *mst; + + set_bit(0, busy); + + list_for_each_entry(mst, &chip->msts, node) { + set_bit(mst->stu.sid, busy); + } + + *sid =3D find_first_zero_bit(busy, MV88E6XXX_N_SID); + + return (*sid >=3D mv88e6xxx_max_sid(chip)) ? -ENOSPC : 0; +} + +static int mv88e6xxx_mst_put(struct mv88e6xxx_chip *chip, u8 sid) +{ + struct mv88e6xxx_mst *mst, *tmp; + int err; + + if (!sid) + return 0; + + list_for_each_entry_safe(mst, tmp, &chip->msts, node) { + if (mst->stu.sid !=3D sid) + continue; + + if (!refcount_dec_and_test(&mst->refcnt)) + return 0; + + mst->stu.valid =3D false; + err =3D mv88e6xxx_stu_loadpurge(chip, &mst->stu); + if (err) + return err; + + list_del(&mst->node); + kfree(mst); + return 0; + } + + return -ENOENT; +} + +static int mv88e6xxx_mst_get(struct mv88e6xxx_chip *chip, struct net_devic= e *br, + u16 msti, u8 *sid) +{ + struct mv88e6xxx_mst *mst; + int err, i; + + if (!mv88e6xxx_has_stu(chip)) { + err =3D -EOPNOTSUPP; + goto err; + } + + if (!msti) { + *sid =3D 0; + return 0; + } + + list_for_each_entry(mst, &chip->msts, node) { + if (mst->br =3D=3D br && mst->msti =3D=3D msti) { + refcount_inc(&mst->refcnt); + *sid =3D mst->stu.sid; + return 0; + } + } + + err =3D mv88e6xxx_sid_get(chip, sid); + if (err) + goto err; + + mst =3D kzalloc(sizeof(*mst), GFP_KERNEL); + if (!mst) { + err =3D -ENOMEM; + goto err; + } + + INIT_LIST_HEAD(&mst->node); + refcount_set(&mst->refcnt, 1); + mst->br =3D br; + mst->msti =3D msti; + mst->stu.valid =3D true; + mst->stu.sid =3D *sid; + + /* The bridge starts out all ports in the disabled state. But + * a STU state of disabled means to go by the port-global + * state. So we set all user port's initial state to blocking, + * to match the bridge's behavior. + */ + for (i =3D 0; i < mv88e6xxx_num_ports(chip); i++) + mst->stu.state[i] =3D dsa_is_user_port(chip->ds, i) ? + MV88E6XXX_PORT_CTL0_STATE_BLOCKING : + MV88E6XXX_PORT_CTL0_STATE_DISABLED; + + err =3D mv88e6xxx_stu_loadpurge(chip, &mst->stu); + if (err) + goto err_free; + + list_add_tail(&mst->node, &chip->msts); + return 0; + +err_free: + kfree(mst); +err: + return err; +} + +static int mv88e6xxx_port_mst_state_set(struct dsa_switch *ds, int port, + const struct switchdev_mst_state *st) +{ + struct dsa_port *dp =3D dsa_to_port(ds, port); + struct mv88e6xxx_chip *chip =3D ds->priv; + struct mv88e6xxx_mst *mst; + u8 state; + int err; + + if (!mv88e6xxx_has_stu(chip)) + return -EOPNOTSUPP; + + switch (st->state) { + case BR_STATE_DISABLED: + case BR_STATE_BLOCKING: + case BR_STATE_LISTENING: + state =3D MV88E6XXX_PORT_CTL0_STATE_BLOCKING; + break; + case BR_STATE_LEARNING: + state =3D MV88E6XXX_PORT_CTL0_STATE_LEARNING; + break; + case BR_STATE_FORWARDING: + state =3D MV88E6XXX_PORT_CTL0_STATE_FORWARDING; + break; + default: + return -EINVAL; + } + + list_for_each_entry(mst, &chip->msts, node) { + if (mst->br =3D=3D dsa_port_bridge_dev_get(dp) && + mst->msti =3D=3D st->msti) { + if (mst->stu.state[port] =3D=3D state) + return 0; + + mst->stu.state[port] =3D state; + mv88e6xxx_reg_lock(chip); + err =3D mv88e6xxx_stu_loadpurge(chip, &mst->stu); + mv88e6xxx_reg_unlock(chip); + return err; + } + } + + return -ENOENT; +} + static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, u16 vid) { @@ -2437,6 +2598,12 @@ static int mv88e6xxx_port_vlan_leave(struct mv88e6xx= x_chip *chip, if (err) return err; =20 + if (!vlan.valid && vlan.sid) { + err =3D mv88e6xxx_mst_put(chip, vlan.sid); + if (err) + return err; + } + return mv88e6xxx_g1_atu_remove(chip, vlan.fid, port, false); } =20 @@ -2482,6 +2649,72 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch= *ds, int port, return err; } =20 +static void mv88e6xxx_port_vlan_fast_age(struct dsa_switch *ds, int port, = u16 vid) +{ + struct mv88e6xxx_chip *chip =3D ds->priv; + struct mv88e6xxx_vtu_entry vlan; + int err; + + mv88e6xxx_reg_lock(chip); + + err =3D mv88e6xxx_vtu_get(chip, vid, &vlan); + if (err) + goto unlock; + + mv88e6xxx_port_fast_age_fid(chip, port, vlan.fid); + +unlock: + mv88e6xxx_reg_unlock(chip); + + if (err) + dev_err(ds->dev, "p%d: failed to flush ATU in VID %u\n", + port, vid); +} + +static int mv88e6xxx_vlan_msti_set(struct dsa_switch *ds, + struct dsa_bridge bridge, + const struct switchdev_vlan_msti *msti) +{ + struct mv88e6xxx_chip *chip =3D ds->priv; + struct mv88e6xxx_vtu_entry vlan; + u8 old_sid, new_sid; + int err; + + mv88e6xxx_reg_lock(chip); + + err =3D mv88e6xxx_vtu_get(chip, msti->vid, &vlan); + if (err) + goto unlock; + + if (!vlan.valid) { + err =3D -EINVAL; + goto unlock; + } + + old_sid =3D vlan.sid; + + err =3D mv88e6xxx_mst_get(chip, bridge.dev, msti->msti, &new_sid); + if (err) + goto unlock; + + if (new_sid !=3D old_sid) { + vlan.sid =3D new_sid; + + err =3D mv88e6xxx_vtu_loadpurge(chip, &vlan); + if (err) { + mv88e6xxx_mst_put(chip, new_sid); + goto unlock; + } + } + + if (old_sid) + err =3D mv88e6xxx_mst_put(chip, old_sid); + +unlock: + mv88e6xxx_reg_unlock(chip); + return err; +} + static int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, struct dsa_db db) @@ -6008,6 +6241,7 @@ static struct mv88e6xxx_chip *mv88e6xxx_alloc_chip(st= ruct device *dev) mutex_init(&chip->reg_lock); INIT_LIST_HEAD(&chip->mdios); idr_init(&chip->policies); + INIT_LIST_HEAD(&chip->msts); =20 return chip; } @@ -6540,10 +6774,13 @@ static const struct dsa_switch_ops mv88e6xxx_switch= _ops =3D { .port_pre_bridge_flags =3D mv88e6xxx_port_pre_bridge_flags, .port_bridge_flags =3D mv88e6xxx_port_bridge_flags, .port_stp_state_set =3D mv88e6xxx_port_stp_state_set, + .port_mst_state_set =3D mv88e6xxx_port_mst_state_set, .port_fast_age =3D mv88e6xxx_port_fast_age, + .port_vlan_fast_age =3D mv88e6xxx_port_vlan_fast_age, .port_vlan_filtering =3D mv88e6xxx_port_vlan_filtering, .port_vlan_add =3D mv88e6xxx_port_vlan_add, .port_vlan_del =3D mv88e6xxx_port_vlan_del, + .vlan_msti_set =3D mv88e6xxx_vlan_msti_set, .port_fdb_add =3D mv88e6xxx_port_fdb_add, .port_fdb_del =3D mv88e6xxx_port_fdb_del, .port_fdb_dump =3D mv88e6xxx_port_fdb_dump, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/c= hip.h index 6d4daa24d3e5..6a0b66354e1d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -297,6 +297,16 @@ struct mv88e6xxx_region_priv { enum mv88e6xxx_region_id id; }; =20 +struct mv88e6xxx_mst { + struct list_head node; + + refcount_t refcnt; + struct net_device *br; + u16 msti; + + struct mv88e6xxx_stu_entry stu; +}; + struct mv88e6xxx_chip { const struct mv88e6xxx_info *info; =20 @@ -397,6 +407,9 @@ struct mv88e6xxx_chip { =20 /* devlink regions */ struct devlink_region *regions[_MV88E6XXX_REGION_MAX]; + + /* Bridge MST to SID mappings */ + struct list_head msts; }; =20 struct mv88e6xxx_bus_ops { --=20 2.25.1