From patchwork Tue Mar 9 02:16:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12123869 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0181CC433DB for ; Tue, 9 Mar 2021 02:18:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CE781652AC for ; Tue, 9 Mar 2021 02:18:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230386AbhCICRh (ORCPT ); Mon, 8 Mar 2021 21:17:37 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41498 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230387AbhCICRQ (ORCPT ); Mon, 8 Mar 2021 21:17:16 -0500 Received: from mail-ej1-x633.google.com (mail-ej1-x633.google.com [IPv6:2a00:1450:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36FE1C061760 for ; Mon, 8 Mar 2021 18:17:16 -0800 (PST) Received: by mail-ej1-x633.google.com with SMTP id hs11so24474630ejc.1 for ; Mon, 08 Mar 2021 18:17:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hoOCzlwn3C76LoMSQCHa5HBJqmeEYAJ3cF9eabZPt1k=; b=hLIgQdsoC2jLeBDKWaSX742WWEbatlnuE3nkdTc2VEarR7ZFnQLbTwemr1Gl3MUjAl yAmkTgdJqWe6SoxKeGvoziBVtgmSnqLcZlYUu5Jsl+oMyiaU6ThMWW/kv6myLR9+VhcA GhbRktyY2Zwtaq7X1ztUNcFwC3m+Xf/axp9s+knNoHzlpp3+3fed+DvfEK/DsbwZGFxn qYwBHc8OLELoWiwgUuDLw+aKhQTk3+lOh+L2owfXFZWdPG7csLi3/ghfVQTFH++OZMJN LWUWqv/gV2fyXFUyql7RHoV5rgLZqhz4zKbyemcxD98e1PSIyYsogBmosNJcGzF7umxx lsIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hoOCzlwn3C76LoMSQCHa5HBJqmeEYAJ3cF9eabZPt1k=; b=TYPJsohU58S+sU1PdQLEcUZbmdGHkQF0GV8n/bEH20wU5oApwLK0VMR7euYQ5y0yQe 9j2i373yBOReAY42iS9Fu/FLssUXZ8LYfF1GSBaJthwIZ7lNpK5B5b2SdOiUQQYmRbD+ TMPysg1R/rbacu5LSNtS6BA7/TzGLAzS7GAdPMtJgKg97r1OG7uN6wnqRHA2dEVcOMFO CYPDkqm+OD9WZ2xjl/pZ2brhkMGwv8Ge0j+LKtxihn4Fn3s1B7y/vSpiZc4CmCOwKo6j aeoJwM+874KRGP4QfJTPqZvRqZxiPwetN7yOCHs7rVjxFEOE6UrXfWjs6WMirvwuvQJo qVZw== X-Gm-Message-State: AOAM530ZcgpR6DFbpyWVuTfEIxJ6PQp6cobKY0QcrG3gwmTT2d6/4yP7 RpoSkprDF7wAZphrBfF/K2E= X-Google-Smtp-Source: ABdhPJxVEkI7SDw5mHckTUzZ2fgf8l+J2HoLfu01bfOSPdpcDdGuj9RWvtdR8CfurQlimhwNrYkaRQ== X-Received: by 2002:a17:906:a0d3:: with SMTP id bh19mr18225031ejb.199.1615256235009; Mon, 08 Mar 2021 18:17:15 -0800 (PST) Received: from localhost.localdomain ([188.25.219.167]) by smtp.gmail.com with ESMTPSA id bj7sm4364902ejb.28.2021.03.08.18.17.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Mar 2021 18:17:14 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Kurt Kanzenbach , Tobias Waldekranz , Vladimir Oltean Subject: [RFC PATCH net 1/4] net: dsa: on 'bridge vlan add', check for 8021q uppers of all bridge ports Date: Tue, 9 Mar 2021 04:16:54 +0200 Message-Id: <20210309021657.3639745-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210309021657.3639745-1-olteanv@gmail.com> References: <20210309021657.3639745-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean The first (original) blamed patch intended to prevent the existence of overlapping 8021q uppers of any bridge port when attempting to offload a bridge VLAN. Unfortunately, it doesn't check the presence of the offending 8021q upper on all bridge ports, just on the one on which the 'bridge vlan add' command was emitted (and on the other ports in the crosschip bitmap, i.e. CPU port and DSA links, all irrelevant). For example, the following setup: $ ip link add dev br0 type bridge vlan_filtering 1 $ ip link add dev lan0.100 link lan0 type vlan id 100 $ ip link set dev lan0 master br0 $ ip link set dev lan1 master br0 $ bridge vlan add dev lan1 vid 100 should return an error at the last command, because if it doesn't, the hardware will be configured in an invalid state where forwarding will take place between traffic belonging to lan0.100 and lan1. The trouble is that in hardware, all VLANs kinda smell the same, so if we offload an 8021q upper on top of a bridged port, this will be in no way different than adding that VLAN with 'bridge vlan add', however from the perspective of Linux network stack semantics it is - traffic sent to 8021q uppers is 'stolen' from the bridge rx_handler in the software data path, and does not take part in bridging unless the 8021q upper is explicitly bridged, therefore we should observe those semantics. This changes dsa_slave_vlan_check_for_8021q_uppers into a more reusable dsa_check_bridge_for_overlapping_8021q_uppers, and also drops the bogus requirement for holding RCU read-side protection: we are already serialized with potential writers to the netdev adjacency lists because we are executing under the rtnl_mutex. The second blamed patch is where this commit actually applies to. Fixes: 061f6a505ac3 ("net: dsa: Add ndo_vlan_rx_{add, kill}_vid implementation") Fixes: 1ce39f0ee8da ("net: dsa: convert denying bridge VLAN with existing 8021q upper to PRECHANGEUPPER") Reported-by: Tobias Waldekranz Signed-off-by: Vladimir Oltean --- net/dsa/slave.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 63ee2cae4d8e..d36e11399626 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -323,23 +323,27 @@ static int dsa_slave_port_attr_set(struct net_device *dev, return ret; } -/* Must be called under rcu_read_lock() */ static int -dsa_slave_vlan_check_for_8021q_uppers(struct net_device *slave, - const struct switchdev_obj_port_vlan *vlan) +dsa_check_bridge_for_overlapping_8021q_uppers(struct net_device *bridge_dev, + u16 vid) { - struct net_device *upper_dev; - struct list_head *iter; - - netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) { - u16 vid; + struct list_head *iter_upper, *iter_lower; + struct net_device *upper, *lower; - if (!is_vlan_dev(upper_dev)) + netdev_for_each_lower_dev(bridge_dev, lower, iter_lower) { + if (!dsa_slave_dev_check(lower)) continue; - vid = vlan_dev_vlan_id(upper_dev); - if (vid == vlan->vid) - return -EBUSY; + netdev_for_each_upper_dev_rcu(lower, upper, iter_upper) { + u16 upper_vid; + + if (!is_vlan_dev(upper)) + continue; + + upper_vid = vlan_dev_vlan_id(upper); + if (upper_vid == vid) + return -EBUSY; + } } return 0; @@ -368,12 +372,11 @@ static int dsa_slave_vlan_add(struct net_device *dev, * the same VID. */ if (br_vlan_enabled(dp->bridge_dev)) { - rcu_read_lock(); - err = dsa_slave_vlan_check_for_8021q_uppers(dev, &vlan); - rcu_read_unlock(); + err = dsa_check_bridge_for_overlapping_8021q_uppers(dp->bridge_dev, + vlan.vid); if (err) { NL_SET_ERR_MSG_MOD(extack, - "Port already has a VLAN upper with this VID"); + "Bridge already has a port with a VLAN upper with this VID"); return err; } } From patchwork Tue Mar 9 02:16:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12123867 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E157DC433E0 for ; Tue, 9 Mar 2021 02:18:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB14B65290 for ; Tue, 9 Mar 2021 02:18:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230408AbhCICRi (ORCPT ); Mon, 8 Mar 2021 21:17:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41506 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230391AbhCICRR (ORCPT ); Mon, 8 Mar 2021 21:17:17 -0500 Received: from mail-ej1-x62e.google.com (mail-ej1-x62e.google.com [IPv6:2a00:1450:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A1A8C061760 for ; Mon, 8 Mar 2021 18:17:17 -0800 (PST) Received: by mail-ej1-x62e.google.com with SMTP id ox4so8853433ejb.11 for ; Mon, 08 Mar 2021 18:17:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Kh/o9qjNG5BCmC7dXeocIV1ZdxnOv3TrahTexKTYhjw=; b=n8pWxex4ba8/yKrWDWDfcc6/8YkGZnKL34PYlrGOJH1QquLmJ3AfSXYB+X1vS9C9jo u7F4d07y3hxa9QFfyOOXN7/SHu+OJ5vHm3NnX/yRPQQmwcqO0W6nV+uhHcd073wdb4Ja N0iMhY5Fvt/6/C9R9XWlby8q86vDqQ3JMrN5knANCnIwty9LP+ubouuQG6v4G2up+Ved C2biUaV7CYI7Me7gUoyLQw8XvR+/G7DITfFTWl/mnKLF7Wzq+qBYCJ03mk8wMlIdWV+R SeSALRbaTsoD0jl6tqJqoocmzT6Wy0dQ0w4A3gh13JSTuZfbO/hqFH6Vc/EiDCHLqU9L 8kkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Kh/o9qjNG5BCmC7dXeocIV1ZdxnOv3TrahTexKTYhjw=; b=B/WiUIItwPVaqnRZPOmDTj9LCbOISAkYakBayJeDGOhbLlBHe8W6iWjaO5R3tYHB+r 8p1mM8kla8H0L2lbJPW5iVpwaj4ChPC5IifJGhdB4D79uSlGMnu6wNRax0nQ5WZn39bG mtogHXeOeUwPaCnG/zLxVE+sjjFv8GRNkKmcaE9vWd726SmV87xBZfuLuAYnBKJS+3Sf EMVAC30iYT4KXjYHMErm+Cwk3kfXDmPa5XflsMUiqGvKgkwQV76/Z2gPaiJM+p8As2Nj cGMg+x7MektjzluY3gPTVzRk4/cY7mjxoRsLCbYn2oueylg0Z3yByNDs/DxcioK7hqTr wBXQ== X-Gm-Message-State: AOAM531n+N5Ptrp8p12ecSfsmJ+rP+apfQr7wKTQ88TBo/1ngVN64F8C dUdxyn73zIKM7uB9G0rcQP8= X-Google-Smtp-Source: ABdhPJz8utoQ/f5360TfHcZABooNF2qCkfoeu376eRPmnrqwpQx0GEvtqCkqhY2H2r9Oo7dPYo4VCg== X-Received: by 2002:a17:906:1d55:: with SMTP id o21mr17777386ejh.485.1615256235887; Mon, 08 Mar 2021 18:17:15 -0800 (PST) Received: from localhost.localdomain ([188.25.219.167]) by smtp.gmail.com with ESMTPSA id bj7sm4364902ejb.28.2021.03.08.18.17.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Mar 2021 18:17:15 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Kurt Kanzenbach , Tobias Waldekranz , Vladimir Oltean Subject: [RFC PATCH net 2/4] net: dsa: prevent hardware forwarding between unbridged 8021q uppers Date: Tue, 9 Mar 2021 04:16:55 +0200 Message-Id: <20210309021657.3639745-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210309021657.3639745-1-olteanv@gmail.com> References: <20210309021657.3639745-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean Tobias reports that the following set of commands, which bridge two ports that have 8021q uppers with the same VID, is incorrectly accepted by DSA as valid: .100 br0 .100 \ / \ / lan0 lan1 ip link add dev br0 type bridge vlan_filtering 1 ip link add dev lan0.100 link lan0 type vlan id 100 ip link add dev lan1.100 link lan1 type vlan id 100 ip link set dev lan0 master br0 ip link set dev lan1 master br0 # This should fail but doesn't Again, this is a variation of the same theme of 'all VLANs kinda smell the same in hardware, you can't tell if they came from 8021q or from the bridge'. When the base interfaces are bridged, the expectation of the Linux network stack is that traffic received by other upper interfaces except the bridge is not captured by the bridge rx_handler, therefore not subject to forwarding. So the above setup should not do forwarding for VLAN ID 100, but it does it nonetheless. So it should be denied. Reported-by: Tobias Waldekranz Fixes: 061f6a505ac3 ("net: dsa: Add ndo_vlan_rx_{add, kill}_vid implementation") Signed-off-by: Vladimir Oltean --- net/dsa/dsa_priv.h | 6 +++++- net/dsa/port.c | 23 ++++++++++++++++++++++- net/dsa/slave.c | 13 +++++++++---- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index d40dfede494c..d6f9b73241b4 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -181,7 +181,8 @@ 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); void dsa_port_disable(struct dsa_port *dp); -int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); +int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, + struct netlink_ext_ack *extack); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); int dsa_port_lag_change(struct dsa_port *dp, struct netdev_lag_lower_state_info *linfo); @@ -261,6 +262,9 @@ static inline bool dsa_tree_offloads_netdev(struct dsa_switch_tree *dst, /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; +int dsa_check_bridge_for_overlapping_8021q_uppers(struct net_device *bridge_dev, + struct net_device *skip, + u16 vid); void dsa_slave_mii_bus_init(struct dsa_switch *ds); int dsa_slave_create(struct dsa_port *dp); void dsa_slave_destroy(struct net_device *slave_dev); diff --git a/net/dsa/port.c b/net/dsa/port.c index c9c6d7ab3f47..0aad5a84361c 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -144,7 +144,8 @@ static void dsa_port_change_brport_flags(struct dsa_port *dp, } } -int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) +int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, + struct netlink_ext_ack *extack) { struct dsa_notifier_bridge_info info = { .tree_index = dp->ds->dst->index, @@ -152,8 +153,28 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) .port = dp->index, .br = br, }; + struct net_device *slave = dp->slave; + struct net_device *upper_dev; + struct list_head *iter; int err; + netdev_for_each_upper_dev_rcu(slave, upper_dev, iter) { + u16 vid; + + if (!is_vlan_dev(upper_dev)) + continue; + + vid = vlan_dev_vlan_id(upper_dev); + + err = dsa_check_bridge_for_overlapping_8021q_uppers(br, slave, + vid); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Configuration would leak VLAN-tagged packets between bridge ports"); + return err; + } + } + /* Notify the port driver to set its configurable flags in a way that * matches the initial settings of a bridge port. */ diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d36e11399626..0e884fd439f8 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -323,9 +323,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev, return ret; } -static int -dsa_check_bridge_for_overlapping_8021q_uppers(struct net_device *bridge_dev, - u16 vid) +int dsa_check_bridge_for_overlapping_8021q_uppers(struct net_device *bridge_dev, + struct net_device *skip, + u16 vid) { struct list_head *iter_upper, *iter_lower; struct net_device *upper, *lower; @@ -334,6 +334,9 @@ dsa_check_bridge_for_overlapping_8021q_uppers(struct net_device *bridge_dev, if (!dsa_slave_dev_check(lower)) continue; + if (lower == skip) + continue; + netdev_for_each_upper_dev_rcu(lower, upper, iter_upper) { u16 upper_vid; @@ -373,6 +376,7 @@ static int dsa_slave_vlan_add(struct net_device *dev, */ if (br_vlan_enabled(dp->bridge_dev)) { err = dsa_check_bridge_for_overlapping_8021q_uppers(dp->bridge_dev, + NULL, vlan.vid); if (err) { NL_SET_ERR_MSG_MOD(extack, @@ -1969,7 +1973,8 @@ static int dsa_slave_changeupper(struct net_device *dev, if (netif_is_bridge_master(info->upper_dev)) { if (info->linking) { - err = dsa_port_bridge_join(dp, info->upper_dev); + err = dsa_port_bridge_join(dp, info->upper_dev, + info->info.extack); if (!err) dsa_bridge_mtu_normalization(dp); err = notifier_from_errno(err); From patchwork Tue Mar 9 02:16:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12123875 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2E158C433E9 for ; Tue, 9 Mar 2021 02:18:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F24C7652B1 for ; Tue, 9 Mar 2021 02:18:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230423AbhCICRi (ORCPT ); Mon, 8 Mar 2021 21:17:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41506 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230393AbhCICRS (ORCPT ); Mon, 8 Mar 2021 21:17:18 -0500 Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F1462C06175F for ; Mon, 8 Mar 2021 18:17:17 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id w9so17648547edt.13 for ; Mon, 08 Mar 2021 18:17:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Hi02CMV5uF2G57Z09yWWJgF7a0xzqbWvf5OLD+vXTgc=; b=hHoibArFAiciJkX9CNndgJVTXk3+VjPl3uXt77TjSTnL97MAwoG7+F4RC0v/Ibx+gf DOyeIGPQtKrai+MiO54LRp8nxpiaXmtrcm96T55NDoP3whhB6Ovh1zXT340thqDCGzAH I9/MWno0I4/dbEtcBaZ910ma3G5wHsaIQQqAxYaz7ShmxKBpl7OfjXK6WZsQLj4d1hZV HtY4L/sBY8sEVlhhjj6SSa6Xlhpw2Ln3pC4C18St8VsKUyGQg2CvHxbaWiwKxoL/JWw/ Z3WIk/9NOCeUN5HsKd7jv4t9nk7BRK8PA9d1pa6A89TWWlU+rkPpwfqDZphe4MW+zz61 egiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Hi02CMV5uF2G57Z09yWWJgF7a0xzqbWvf5OLD+vXTgc=; b=NMEUZMIcl4w2sKrq8hX/x7n1F/aGGpBF8ZSpZsuxYDqOAqy9CCr6V/zQARPZlhTt97 vybmxPeGfDWtXDp93Kaf09DxJzgzGHvuEZBFtvKc5leN+6M21bRyhZssQr7h2J2FjqBx hAxCb1ZXlNCXV185gRhLoE0U3ZY989aNXM2y1/Z62d8g97P7qALdqMBypEF4lVX1Sh73 PSkfUu6qPG5U303DKTFWAG5XoxR40sZtMUNUqL+IdVSOkBPei0rzkmSTVop6dqOtWT+H 7CixZI+A8fwe7M0kN0M+TeRlRwmODfH7HT2dUMJ4dqym+d2F+hHMrXotIcFJKljotdBm YVog== X-Gm-Message-State: AOAM530hKrn8nVIJqQ226U7JHPeD67K0WEmcrjzUQ8FwxZwwNFiEl0o6 TcFJKSruM2Oi412tzSF6G3I= X-Google-Smtp-Source: ABdhPJygleCFuaCwaf/8v7SSAbxghzKRj+e91rHSeCw76/AM/y/iMsOfKFUPGuGj4dag/OnCLQYtaw== X-Received: by 2002:a05:6402:888:: with SMTP id e8mr1467200edy.51.1615256236766; Mon, 08 Mar 2021 18:17:16 -0800 (PST) Received: from localhost.localdomain ([188.25.219.167]) by smtp.gmail.com with ESMTPSA id bj7sm4364902ejb.28.2021.03.08.18.17.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Mar 2021 18:17:16 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Kurt Kanzenbach , Tobias Waldekranz , Vladimir Oltean Subject: [RFC PATCH net 3/4] net: dsa: don't advertise 'rx-vlan-filter' if VLAN filtering not global Date: Tue, 9 Mar 2021 04:16:56 +0200 Message-Id: <20210309021657.3639745-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210309021657.3639745-1-olteanv@gmail.com> References: <20210309021657.3639745-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean The blamed patch has removed the driver's ability to return -EOPNOTSUPP in the .port_vlan_add method when called from .ndo_vlan_rx_add_vid (unmassaged by DSA, -EOPNOTSUPP is a hard error for vlan_vid_add). But we have not managed well enough the cases under which .port_vlan_add is called in the first place, as will be explained below. This was reported as a problem by Tobias because mv88e6xxx_port_vlan_prepare is stubborn and only accepts VLANs on bridged ports. That is understandably so, because standalone mv88e6xxx ports are VLAN-unaware, and VTU entries are said to be a scarce resource. Otherwise said, the following fails lamentably on mv88e6xxx: ip link add br0 type bridge vlan_filtering 1 ip link set lan3 master br0 ip link add link lan10 name lan10.1 type vlan id 1 [485256.724147] mv88e6085 d0032004.mdio-mii:12: p10: hw VLAN 1 already used by port 3 in br0 RTNETLINK answers: Operation not supported We need to step back and explain that the dsa_slave_vlan_rx_add_vid and dsa_slave_vlan_rx_kill_vid methods exist for drivers that need the 'rx-vlan-filter: on' feature in ethtool -k, which can be due to any of the following reasons: 1. vlan_filtering_is_global = true, and some ports are under a VLAN-aware bridge while others are standalone, and the standalone ports would otherwise drop VLAN-tagged traffic. This is described in commit 061f6a505ac3 ("net: dsa: Add ndo_vlan_rx_{add, kill}_vid implementation"). 2. the ports that are under a VLAN-aware bridge should also set this feature, for 8021q uppers having a VID not claimed by the bridge. In this case, the driver will essentially not even know that the VID is coming from the 8021q layer and not the bridge. 3. Hellcreek. This driver needs it because in standalone mode, it uses unique VLANs per port to ensure separation. For separation of untagged traffic, it uses different PVIDs for each port, and for separation of VLAN-tagged traffic, it never accepts 8021q uppers with the same vid on two ports. If a driver does not fall under any of the above 3 categories, there is no reason why it should advertise the 'rx-vlan-filter' feature, therefore no reason why it should offload the VLANs added through vlan_vid_add. This commit fixes the problem by removing the 'rx-vlan-filter' feature from the slave devices when they operate in standalone mode, and when they offload a VLAN-unaware bridge. This gives the mv88e6xxx driver what it wants, since it keeps the 8021q VLANs away from the VTU until VLAN awareness is enabled (point at which the ports are no longer standalone, hence the check in mv88e6xxx_port_vlan_prepare passes). And since the issue predates the existence of the hellcreek driver, case 3 will be dealt with in a separate patch. The commit also has the nice side effect that we no longer lie to the network stack about our VLAN filtering status. Because the 'rx-vlan-filter' feature is now dynamically toggled, and our .ndo_vlan_rx_add_vid does not get called when 'rx-vlan-filter' is off, we need to avoid bugs such as the following by replaying the VLANs from 8021q uppers every time we enable VLAN filtering: ip link add link lan0 name lan0.100 type vlan id 100 ip addr add 192.168.100.1/24 dev lan0.100 ping 192.168.100.2 # should work ip link add br0 type bridge vlan_filtering 0 ip link set lan0 master br0 ping 192.168.100.2 # should still work ip link set br0 type bridge vlan_filtering 1 ping 192.168.100.2 # should still work but doesn't Fixes: 9b236d2a69da ("net: dsa: Advertise the VLAN offload netdev ability only if switch supports it") Reported-by: Tobias Waldekranz Signed-off-by: Vladimir Oltean --- net/dsa/dsa_priv.h | 2 ++ net/dsa/port.c | 37 +++++++++++++++++++++++++++++-- net/dsa/slave.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index d6f9b73241b4..6d0058238a0e 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -274,6 +274,8 @@ int dsa_slave_register_notifier(void); void dsa_slave_unregister_notifier(void); void dsa_slave_setup_tagger(struct net_device *slave); int dsa_slave_change_mtu(struct net_device *dev, int new_mtu); +int dsa_slave_manage_vlan_filtering(struct net_device *dev, + bool vlan_filtering); static inline struct dsa_port *dsa_slave_to_port(const struct net_device *dev) { diff --git a/net/dsa/port.c b/net/dsa/port.c index 0aad5a84361c..deb3586c0e61 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -384,6 +384,7 @@ static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct netlink_ext_ack *extack) { + bool old_vlan_filtering = dsa_port_is_vlan_filtering(dp); struct dsa_switch *ds = dp->ds; bool apply; int err; @@ -409,12 +410,44 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, if (err) return err; - if (ds->vlan_filtering_is_global) + if (ds->vlan_filtering_is_global) { + int port; + + for (port = 0; port < ds->num_ports; port++) { + struct net_device *slave; + + if (!dsa_is_user_port(ds, port)) + continue; + + /* We might be called in the unbind path, so not + * all slave devices might still be registered. + */ + slave = dsa_to_port(ds, port)->slave; + if (!slave) + continue; + + err = dsa_slave_manage_vlan_filtering(slave, + vlan_filtering); + if (err) + goto restore; + } + ds->vlan_filtering = vlan_filtering; - else + } else { + err = dsa_slave_manage_vlan_filtering(dp->slave, + vlan_filtering); + if (err) + goto restore; + dp->vlan_filtering = vlan_filtering; + } return 0; + +restore: + ds->ops->port_vlan_filtering(ds, dp->index, old_vlan_filtering, NULL); + + return err; } /* This enforces legacy behavior for switch drivers which assume they can't diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 0e884fd439f8..e5ca29df7605 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1380,6 +1380,58 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, return 0; } +static int dsa_slave_restore_vlan(struct net_device *vdev, int vid, void *arg) +{ + return dsa_slave_vlan_rx_add_vid(arg, vlan_dev_vlan_proto(vdev), vid); +} + +static int dsa_slave_clear_vlan(struct net_device *vdev, int vid, void *arg) +{ + return dsa_slave_vlan_rx_kill_vid(arg, vlan_dev_vlan_proto(vdev), vid); +} + +/* Keep the VLAN RX filtering list originating from 8021q uppers in sync with + * the hardware only if VLAN filtering is enabled. + * + * - Standalone ports offload: + * - no VLAN (any 8021q upper is a software VLAN) if + * ds->vlan_filtering_is_global = false + * - the 8021q upper VLANs if ds->vlan_filtering_is_global = true and there + * are bridges spanning this switch chip which have vlan_filtering=1 + * + * - Ports under a vlan_filtering=0 bridge offload: + * - no VLAN if ds->configure_vlan_while_not_filtering = false (deprecated) + * - the bridge VLANs if ds->configure_vlan_while_not_filtering = true + * + * - Ports under a vlan_filtering=1 bridge offload: + * - the bridge VLANs + * - the 8021q upper VLANs + */ +int dsa_slave_manage_vlan_filtering(struct net_device *slave, + bool vlan_filtering) +{ + int err; + + if (vlan_filtering) { + slave->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + + err = vlan_for_each(slave, dsa_slave_restore_vlan, slave); + if (err) { + vlan_for_each(slave, dsa_slave_clear_vlan, slave); + slave->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + return err; + } + } else { + err = vlan_for_each(slave, dsa_slave_clear_vlan, slave); + if (err) + return err; + + slave->features &= ~NETIF_F_HW_VLAN_CTAG_FILTER; + } + + return 0; +} + struct dsa_hw_port { struct list_head list; struct net_device *dev; @@ -1850,8 +1902,6 @@ int dsa_slave_create(struct dsa_port *port) return -ENOMEM; slave_dev->features = master->vlan_features | NETIF_F_HW_TC; - if (ds->ops->port_vlan_add && ds->ops->port_vlan_del) - slave_dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; slave_dev->hw_features |= NETIF_F_HW_TC; slave_dev->features |= NETIF_F_LLTX; slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; From patchwork Tue Mar 9 02:16:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12123871 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41759C43381 for ; Tue, 9 Mar 2021 02:18:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2DFB065290 for ; Tue, 9 Mar 2021 02:18:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230433AbhCICRj (ORCPT ); Mon, 8 Mar 2021 21:17:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41506 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230395AbhCICRT (ORCPT ); Mon, 8 Mar 2021 21:17:19 -0500 Received: from mail-ej1-x632.google.com (mail-ej1-x632.google.com [IPv6:2a00:1450:4864:20::632]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D89FEC06175F for ; Mon, 8 Mar 2021 18:17:18 -0800 (PST) Received: by mail-ej1-x632.google.com with SMTP id c10so24412992ejx.9 for ; Mon, 08 Mar 2021 18:17:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MwEUL3leO5vGNSGOykqxQ6pxQvePSNcDrkFy2vqfSik=; b=HpE3JQcIak2NGtZ54JMp0ET7lfDORbbV+6T5WU8Zv4y0YiHvKxuB6nTSu53W3RhzjA y0UJfexLD8hw2EBgEA5LHAilQpo8choFbsSvP2eSyHlLCblnKpw5P8CfGELF1rlOpzrl oDXkVk5rrWRhcDpci6tfuvqol9ci65n7XHDT/ua7CSop+87EmW3ok9WYw6h0Z61MQHER 0lZ7QqxjzJalgcuCmMgxgisNBTqDi4m/FxVhHiqMJ6IqHnRlNY76otVnTmGFB1A08v7w GsemA1IPrANtltPRA3TSEfq8zGf8MSeoJWxhniQbo0VTaEeWTVFGy35SQw/jeXP+wlqW svrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MwEUL3leO5vGNSGOykqxQ6pxQvePSNcDrkFy2vqfSik=; b=Tnw0a/9Sl8AWNPpOfDOtpiOvJ8g0yR1+rSIX9Yw+0l1njhv+KItuQJzOEjtbYavQAH 4li2X0cul23JwFvFzRHwZyZ5TkA0CHGiYFWt3KpQv9qgX4cdtoHnY+ZJgDhBUQhkAoEw bokdFWCBjb47XVUWi1gzPMFlYg/9w15FK4jF89CedEkJ3mc658LzBkvFhK7sBd5iscBf +pAZUI9wtvEPTqXGMK6/szNFAYdSMuewnmV57gIcaGfkMZHwKW/t/NxLrpBoTTvtW+y+ 6esRICqKe+aTGaS+eQCfY6e+LRnfIlc54PTuCLSMFddBgegXxmy2dtqV52Q7osRbIt5g uSGA== X-Gm-Message-State: AOAM532jRoiJsYU5X6Kj+dQ5nwk1NR4jwe+wGqtcWCJBW0ZmzbBZ9PiT edYNe0ujXycDprX1/ivHOGSn3rpJNLQ= X-Google-Smtp-Source: ABdhPJws/b9GemTV6ei1JmxuEtQXcba+PU87ROeHgvqXvQzGdvAdtcyMGeOui6KVYD+UsOTcpK1W/A== X-Received: by 2002:a17:906:b884:: with SMTP id hb4mr17681721ejb.536.1615256237628; Mon, 08 Mar 2021 18:17:17 -0800 (PST) Received: from localhost.localdomain ([188.25.219.167]) by smtp.gmail.com with ESMTPSA id bj7sm4364902ejb.28.2021.03.08.18.17.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 08 Mar 2021 18:17:17 -0800 (PST) From: Vladimir Oltean To: "David S . Miller" , Jakub Kicinski , netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Kurt Kanzenbach , Tobias Waldekranz , Vladimir Oltean Subject: [RFC PATCH net 4/4] net: dsa: let drivers state that they need VLAN filtering while standalone Date: Tue, 9 Mar 2021 04:16:57 +0200 Message-Id: <20210309021657.3639745-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210309021657.3639745-1-olteanv@gmail.com> References: <20210309021657.3639745-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean As explained in the blamed patch, the hellcreek driver uses some tricks to comply with the network stack expectations: it enforces port separation in standalone mode using VLANs. For untagged traffic, bridging between ports is prevented by using different PVIDs, and for VLAN-tagged traffic, it never accepts 8021q uppers with the same VID on two ports, so packets with one VLAN cannot leak from one port to another. That is almost fine*, and has worked because hellcreek relied on an implicit behavior of the DSA core that was changed by the previous patch: the standalone ports declare the 'rx-vlan-filter' feature as 'on [fixed]'. Since most of the DSA drivers are actually VLAN-unaware in standalone mode, that feature was actually incorrectly reflecting the hardware/driver state, so there was a desire to fix it. This leaves the hellcreek driver in a situation where it has to explicitly request this behavior from the DSA framework. We configure the ports as follows: - Standalone: 'rx-vlan-filter' is on. An 8021q upper on top of a standalone hellcreek port will go through dsa_slave_vlan_rx_add_vid and will add a VLAN to the hardware tables, giving the driver the opportunity to refuse it through .port_prechangeupper. - Bridged with vlan_filtering=0: 'rx-vlan-filter' is off. An 8021q upper on top of a bridged hellcreek port will not go through dsa_slave_vlan_rx_add_vid, because there will not be any attempt to offload this VLAN. The driver already disables VLAN awareness, so that upper should receive the traffic it needs. - Bridged with vlan_filtering=1: 'rx-vlan-filter' is on. An 8021q upper on top of a bridged hellcreek port will call dsa_slave_vlan_rx_add_vid, and can again be vetoed through .port_prechangeupper. *It is not actually completely fine, because if I follow through correctly, we can have the following situation: ip link add br0 type bridge vlan_filtering 0 ip link set lan0 master br0 # lan0 now becomes VLAN-unaware ip link set lan0 nomaster # lan0 fails to become VLAN-aware again, therefore breaking isolation This patch fixes that by extending the DSA core logic, based on this requested attribute, to change the VLAN awareness state of the switch (port) when it leaves the bridge. Fixes: e358bef7c392 ("net: dsa: Give drivers the chance to veto certain upper devices") Signed-off-by: Vladimir Oltean --- drivers/net/dsa/hirschmann/hellcreek.c | 1 + include/net/dsa.h | 3 +++ net/dsa/slave.c | 8 ++++++-- net/dsa/switch.c | 20 +++++++++++++++----- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 463137c39db2..b8112de24b3f 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1126,6 +1126,7 @@ static int hellcreek_setup(struct dsa_switch *ds) * filtering setups are not supported. */ ds->vlan_filtering_is_global = true; + ds->needs_standalone_vlan_filtering = true; /* Intercept _all_ PTP multicast traffic */ ret = hellcreek_setup_fdb(hellcreek); diff --git a/include/net/dsa.h b/include/net/dsa.h index 83a933e563fe..58ce8089af9a 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -355,6 +355,9 @@ struct dsa_switch { */ bool vlan_filtering_is_global; + /* Keep VLAN filtering enabled on unbridged ports. */ + bool needs_standalone_vlan_filtering; + /* Pass .port_vlan_add and .port_vlan_del to drivers even for bridges * that have vlan_filtering=0. All drivers should ideally set this (and * then the option would get removed), but it is unknown whether this diff --git a/net/dsa/slave.c b/net/dsa/slave.c index e5ca29df7605..c878fedb81d5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1395,9 +1395,11 @@ static int dsa_slave_clear_vlan(struct net_device *vdev, int vid, void *arg) * * - Standalone ports offload: * - no VLAN (any 8021q upper is a software VLAN) if - * ds->vlan_filtering_is_global = false + * ds->vlan_filtering_is_global = false and + * ds->needs_standalone_vlan_filtering = false * - the 8021q upper VLANs if ds->vlan_filtering_is_global = true and there - * are bridges spanning this switch chip which have vlan_filtering=1 + * are bridges spanning this switch chip which have vlan_filtering=1, or + * ds->needs_standalone_vlan_filtering = true. * * - Ports under a vlan_filtering=0 bridge offload: * - no VLAN if ds->configure_vlan_while_not_filtering = false (deprecated) @@ -1903,6 +1905,8 @@ int dsa_slave_create(struct dsa_port *port) slave_dev->features = master->vlan_features | NETIF_F_HW_TC; slave_dev->hw_features |= NETIF_F_HW_TC; + if (ds->needs_standalone_vlan_filtering) + slave_dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; slave_dev->features |= NETIF_F_LLTX; slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; if (!IS_ERR_OR_NULL(port->mac)) diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 56ed31b0e636..9a02d24739e1 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -104,9 +104,10 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds, static int dsa_switch_bridge_leave(struct dsa_switch *ds, struct dsa_notifier_bridge_info *info) { - bool unset_vlan_filtering = br_vlan_enabled(info->br); struct dsa_switch_tree *dst = ds->dst; struct netlink_ext_ack extack = {0}; + bool change_vlan_filtering = false; + bool vlan_filtering; int err, port; if (dst->index == info->tree_index && ds->index == info->sw_index && @@ -119,6 +120,15 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, info->sw_index, info->port, info->br); + if (ds->needs_standalone_vlan_filtering && !br_vlan_enabled(info->br)) { + change_vlan_filtering = true; + vlan_filtering = true; + } else if (!ds->needs_standalone_vlan_filtering && + br_vlan_enabled(info->br)) { + change_vlan_filtering = true; + vlan_filtering = false; + } + /* If the bridge was vlan_filtering, the bridge core doesn't trigger an * event for changing vlan_filtering setting upon slave ports leaving * it. That is a good thing, because that lets us handle it and also @@ -127,21 +137,21 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, * vlan_filtering callback is only when the last port the last * VLAN-aware bridge. */ - if (unset_vlan_filtering && ds->vlan_filtering_is_global) { + if (change_vlan_filtering && ds->vlan_filtering_is_global) { for (port = 0; port < ds->num_ports; port++) { struct net_device *bridge_dev; bridge_dev = dsa_to_port(ds, port)->bridge_dev; if (bridge_dev && br_vlan_enabled(bridge_dev)) { - unset_vlan_filtering = false; + change_vlan_filtering = false; break; } } } - if (unset_vlan_filtering) { + if (change_vlan_filtering) { err = dsa_port_vlan_filtering(dsa_to_port(ds, info->port), - false, &extack); + vlan_filtering, &extack); if (extack._msg) dev_err(ds->dev, "port %d: %s\n", info->port, extack._msg);