Received: by 2002:a05:6a10:7420:0:0:0:0 with SMTP id hk32csp875921pxb; Wed, 16 Feb 2022 06:20:30 -0800 (PST) X-Google-Smtp-Source: ABdhPJxAI4FlnrVzdGgFSjui3H/THoMXdc+hPhN3Ss1+sYMcCXU4eoLFhxZZPFdPzMmIBRqLtzBQ X-Received: by 2002:a17:902:e5c2:b0:14b:702:4c5d with SMTP id u2-20020a170902e5c200b0014b07024c5dmr3159637plf.88.1645021230164; Wed, 16 Feb 2022 06:20:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1645021230; cv=none; d=google.com; s=arc-20160816; b=z9DD6L1Fz8JHfShxAb0PJB7M4b2AAJ5nMx2q0H1j9Zmgr3iLmx0dEDRmETWpuqqDg1 1lzOd3hU7ddjEGtjcQYjB0p0QEDRm8qme2Vkzkv0LjwXlI8vaarNgv99+WoJYQwi3auC /jXyCtpISCWyneNNWiZphSvZeMp6NNDvXOUTwsarKYpBLFc+wUuyrnsQ9VFoAvCDZyQu ntgZI7HbMBDoKgLHgs+Sb81ydX2Y3MOLK1uGJ3npACelS5/BvALnr36o5LBpeac6Pb5I DKQ61qha+L+M8Ije4NzX37WxHHNIg0Cn5UuU+SAp0eaBZlXTLPcdt6mScmAjjoqF6hgF H84A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:organization :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=1CB4EUxFKWWI52Kz17aW6jZZJSTVpsgoKc4ur1YzcMA=; b=UuG5r4qArgRjlhDHKix8Q5+qgekYdpDrF0vsmIWepn4KuGudmLDOIZiSh0HnMXPY7t d+4I0MasNflDaVhL7gZBvwc8mUtUqWT01IYJl2T1L61inZc9+XLL+KygfOjlb1VBOqtv xForauXL/epZLmVlzgPhj9WG+pcV4+0i6SnaSrVfdeSVApSACdmSbuKE8SBaUDGjDgxG N11vSwZC75XAx1UcEJfN7/6pfp4coBtFsnxdpEUh1bQ6IljpSImnJhttqdiUO484U82N qUwEeC1oCNEwi1s3IIFwqDDxD1Z/C4s/NvSbTHtuZALBwpQF2m4HHeVRCtRzOwg+C6fv tMJQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@waldekranz-com.20210112.gappssmtp.com header.s=20210112 header.b="w73/uLp7"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id w17si17149779plp.85.2022.02.16.06.20.10; Wed, 16 Feb 2022 06:20:30 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@waldekranz-com.20210112.gappssmtp.com header.s=20210112 header.b="w73/uLp7"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234429AbiBPNaq (ORCPT + 99 others); Wed, 16 Feb 2022 08:30:46 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:42730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234329AbiBPNaj (ORCPT ); Wed, 16 Feb 2022 08:30:39 -0500 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 4A285171291 for ; Wed, 16 Feb 2022 05:30:27 -0800 (PST) Received: by mail-lj1-x22d.google.com with SMTP id bx31so3389132ljb.0 for ; Wed, 16 Feb 2022 05:30:27 -0800 (PST) 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=1CB4EUxFKWWI52Kz17aW6jZZJSTVpsgoKc4ur1YzcMA=; b=w73/uLp75Ob6mZY/GoZBQ3VdlKKx9uIt18VnJKjs81yvPTh9ma3bhetUB54GlatmyX SsBkqnp6YpcF+bQDQCGABlyboYCJ2NNE23QK3WZ4Dg+EdT7lhcnY5ZKWCV3gubXke/Ci atzgu+eHBNDOisygn9mYk3qhkfPA5BZZJ0nwLif5cBY5VeBqb6cb9CafTtvrh5fFWRf/ NO9CR3HZxwLQoSEoU3nQuzsKLggOxHkCYbZZVaTtiXUrcv3htFUu3LsbeOS692zNkVKd v95/7aOAMP1QIebU/pjCLxqmQgFazCSSSjuE3z20kknQSOdfM4QrVIJLJwgk7at2FJK1 EE/A== 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=1CB4EUxFKWWI52Kz17aW6jZZJSTVpsgoKc4ur1YzcMA=; b=yn03PGNV1Kg6jAZsgTbiCeYwNFnDus96dXAH7sRPTdt7ClKQmqmnJkdZ8urLmqNcio pBK29TVhqOndpvlhUpl+6GO7PsPrcVkRASgw9tsw5ieuNQNvC8rR2784hKksZrbP6omW rC2IowhLwUk23+WyPO3J3u8ohEW6MgWI+HvmCwoiO2XGHzbBAfyIUfeHAG1bhLRQpE+l H4EDr9DneCxHUWfPBdxJGUn0G8N7Xes8xi9+8oiArJTr5K3PXaicfeOe2WhGfGfBY81Z Q4W6O3v7ucvOtkSoHlbmSblpWOusZINdUAzndkJBUG2NvcytOpLk3kUQNKVSICNglene mGLA== X-Gm-Message-State: AOAM531LtfUljygu0cghf31fKWK/eOTXE0V0dz8K1MRa6VRvvyPUFBaV eaplWPm/LEFlG12ZYcbDfTsohw== X-Received: by 2002:a2e:8e7b:0:b0:246:355:fbc0 with SMTP id t27-20020a2e8e7b000000b002460355fbc0mr2069502ljk.356.1645018225644; Wed, 16 Feb 2022 05:30:25 -0800 (PST) Received: from veiron.westermo.com (static-193-12-47-89.cust.tele2.se. [193.12.47.89]) by smtp.gmail.com with ESMTPSA id v6sm234780ljd.86.2022.02.16.05.30.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Feb 2022 05:30:24 -0800 (PST) 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 , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, bridge@lists.linux-foundation.org Subject: [RFC net-next 2/9] net: bridge: vlan: Allow multiple VLANs to be mapped to a single MST Date: Wed, 16 Feb 2022 14:29:27 +0100 Message-Id: <20220216132934.1775649-3-tobias@waldekranz.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220216132934.1775649-1-tobias@waldekranz.com> References: <20220216132934.1775649-1-tobias@waldekranz.com> MIME-Version: 1.0 Organization: Westermo Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Allow a VLAN to change its MSTID. In particular, allow multiple VLANs to use the same MSTID. This is a global VLAN setting, i.e. any VLANs bound to the same MSTID will share their per-VLAN STP states on all bridge ports. Example: By default, each VLAN is placed in a separate MSTID: root@coronet:~# ip link add dev br0 type bridge vlan_filtering 1 root@coronet:~# ip link set dev eth1 master br0 root@coronet:~# bridge vlan add dev eth1 vid 2 pvid untagged root@coronet:~# bridge vlan add dev eth1 vid 3 root@coronet:~# bridge vlan global port vlan-id br0 1 mcast_snooping 1 mca_interval 1000 mstid 1 2 mcast_snooping 1 mca_interval 1000 mstid 2 3 mcast_snooping 1 mca_interval 1000 mstid 3 Once two or more VLANs are bound to the same MSTID, their states move in lockstep, independent of which VID is used to access the state: root@coronet:~# bridge vlan global set dev br0 vid 2 mstid 10 root@coronet:~# bridge vlan global set dev br0 vid 3 mstid 10 root@coronet:~# bridge -d vlan global port vlan-id br0 1 mcast_snooping 1 mca_interval 1000 mstid 1 2-3 mcast_snooping 1 mca_interval 1000 mstid 10 root@coronet:~# bridge vlan set dev eth1 vid 2 state blocking root@coronet:~# bridge -d vlan port vlan-id eth1 1 Egress Untagged state forwarding mcast_router 1 2 PVID Egress Untagged state blocking mcast_router 1 3 state blocking mcast_router 1 br0 1 PVID Egress Untagged state forwarding mcast_router 1 root@coronet:~# bridge vlan set dev eth1 vid 3 state forwarding root@coronet:~# bridge -d vlan port vlan-id eth1 1 Egress Untagged state forwarding mcast_router 1 2 PVID Egress Untagged state forwarding mcast_router 1 3 state forwarding mcast_router 1 br0 1 PVID Egress Untagged state forwarding mcast_router 1 Signed-off-by: Tobias Waldekranz --- include/uapi/linux/if_bridge.h | 1 + net/bridge/br_private.h | 3 ++ net/bridge/br_vlan.c | 53 ++++++++++++++++++++++++++-------- net/bridge/br_vlan_options.c | 17 ++++++++++- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 2711c3522010..4a971b419d9f 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_MSTID, __BRIDGE_VLANDB_GOPTS_MAX }; #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 7781e7a4449b..5b121cf7aabe 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1759,6 +1759,9 @@ static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state) mst->state = state; } +u16 br_vlan_mstid_get(const struct net_bridge_vlan *v); +int br_vlan_mstid_set(struct net_bridge_vlan *v, u16 mstid); + static inline u8 br_vlan_get_pvid_state(const struct net_bridge_vlan_group *vg) { return READ_ONCE(vg->pvid_state); diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index b0383ec6cc91..459e84a7354d 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -41,10 +41,8 @@ static void br_vlan_mst_rcu_free(struct rcu_head *rcu) kfree(mst); } -static void br_vlan_mst_put(struct net_bridge_vlan *v) +static void br_vlan_mst_put(struct br_vlan_mst *mst) { - struct br_vlan_mst *mst = rtnl_dereference(v->mst); - if (refcount_dec_and_test(&mst->refcnt)) call_rcu(&mst->rcu, br_vlan_mst_rcu_free); } @@ -153,13 +151,17 @@ static struct br_vlan_mst *br_vlan_group_mst_get(struct net_bridge_vlan_group *v static int br_vlan_mst_migrate(struct net_bridge_vlan *v, u16 mstid) { + struct br_vlan_mst *mst, *old_mst; struct net_bridge_vlan_group *vg; - struct br_vlan_mst *mst; + struct net_bridge *br; - if (br_vlan_is_master(v)) - vg = br_vlan_group(v->br); - else + if (br_vlan_is_master(v)) { + br = v->br; + vg = br_vlan_group(br); + } else { + br = v->port->br; vg = nbp_vlan_group(v->port); + } mst = br_vlan_group_mst_get(vg, mstid); if (!mst) { @@ -168,10 +170,37 @@ static int br_vlan_mst_migrate(struct net_bridge_vlan *v, u16 mstid) return -ENOMEM; } - if (rtnl_dereference(v->mst)) - br_vlan_mst_put(v); - + old_mst = rtnl_dereference(v->mst); rcu_assign_pointer(v->mst, mst); + + if (old_mst) + br_vlan_mst_put(old_mst); + + return 0; +} + +int br_vlan_mstid_set(struct net_bridge_vlan *v, u16 mstid) +{ + struct net_bridge *br = v->br; + struct net_bridge_port *p; + int err; + + err = br_vlan_mst_migrate(v, mstid); + if (err) + return err; + + list_for_each_entry(p, &br->port_list, list) { + struct net_bridge_vlan_group *vg = nbp_vlan_group(p); + struct net_bridge_vlan *portv; + + portv = br_vlan_lookup(&vg->vlan_hash, v->vid); + if (!portv) + continue; + + err = br_vlan_mst_migrate(portv, mstid); + if (err) + return err; + } return 0; } @@ -501,7 +530,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags, return err; out_mst_init: - br_vlan_mst_put(v); + br_vlan_mst_put(rtnl_dereference(v->mst)); out_fdb_insert: if (br_vlan_should_use(v)) { @@ -570,7 +599,7 @@ static int __vlan_del(struct net_bridge_vlan *v) call_rcu(&v->rcu, nbp_vlan_rcu_free); } - br_vlan_mst_put(v); + br_vlan_mst_put(rtnl_dereference(v->mst)); br_vlan_put_master(masterv); out: return err; diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c index 0b1099709d4b..1c0fd55fe6c9 100644 --- a/net/bridge/br_vlan_options.c +++ b/net/bridge/br_vlan_options.c @@ -380,6 +380,9 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range, #endif #endif + if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_MSTID, br_vlan_mstid_get(v_opts))) + goto out_err; + nla_nest_end(skb, nest); return true; @@ -411,7 +414,9 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(const struct 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_PORTS */ #endif - + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */ + + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_RANGE */ + + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_MSTID */ + + 0; } static void br_vlan_global_opts_notify(const struct net_bridge *br, @@ -560,6 +565,15 @@ static int br_vlan_process_global_one_opts(const struct net_bridge *br, } #endif #endif + if (tb[BRIDGE_VLANDB_GOPTS_MSTID]) { + u16 mstid; + + mstid = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_MSTID]); + err = br_vlan_mstid_set(v, mstid); + if (err) + return err; + *changed = true; + } return 0; } @@ -579,6 +593,7 @@ static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = { [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL] = { .type = NLA_U64 }, [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 }, [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 }, + [BRIDGE_VLANDB_GOPTS_MSTID] = NLA_POLICY_RANGE(NLA_U16, 1, 4094), }; int br_vlan_rtm_process_global_options(struct net_device *dev, -- 2.25.1