Message ID | 20230314163651.242259-3-clement.leger@bootlin.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp1872035wrd; Tue, 14 Mar 2023 10:00:43 -0700 (PDT) X-Google-Smtp-Source: AK7set93JVUF58nEkYhLsphfMaKAVFxZjpCHGSg/PRTj+ZnNnpO8liKADQEE7hHPj6zKq8dOiTgd X-Received: by 2002:a05:6a20:6993:b0:cc:1996:9853 with SMTP id t19-20020a056a20699300b000cc19969853mr32770431pzk.47.1678813242793; Tue, 14 Mar 2023 10:00:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1678813242; cv=none; d=google.com; s=arc-20160816; b=w576WtSkP0436KhwPlYkAjpjr8jOFMASy9U9GRnDtFhO9r6DJgDzCFQpgkt0wU3uFJ yp3eu3RabqA4Eqquu1PL51UauydxrJCQ1nHyxa80my6DtFYfBgFNkYnVR6MuB4LKkZ5p J/TeSp4IXQXWFRAm4Mm87c59xwn9aA8O71k++DuF4EsE5vqXU1TTYq+vpUSKd0p3QNEh psMHjK2lSeniIloWTMJqyd4imK+orqas9dI1T3UBbB4mIoNCRzIVDaShy6jMfmlYwWKB 4CFXsnUxy1i6zsrvulvhm+mGMdUsvRhdDXXKKubpkXWeWC4jRDtNjd5ZXKAHPxo2/zbx 2o2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=Ib/mOXHYH3Do6zNpWmBQIKneKPV3vlWtkcbraPhLrAg=; b=DHYUZLELTlqm8z1kLYjYSchAnx/SnNa5kUYYFpAuYXP8QvVno1kp41XTd1qk5CBHiB MQ/6q/hKyPl0nZpGZ05iGtCOcqeAIbpptA0SSbS9kS95qdrKiLO2tR8ImozWaiU60jsV PjgNoPkovZTdf65CLWzViV9X+6MLq2c9BacuaBU3OofVmVE/WJWKAzGLfeVXZQu8V9wJ 8GjoQY8mrk3DSZrd9ZjWEQry67LqtEqEYWuc68W48IKQBXoEUsw0/UJwgcASOIYyRkHz ZNeRbhWY8x8jn3zQtvEl73KFPTGF4axpLCmB6p5n7jlq2N+NV69vDqDbqzLT01Ec5ZGc bkgQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=ih5vssL0; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p25-20020a634f59000000b004fc2dfedcd6si2608166pgl.213.2023.03.14.10.00.25; Tue, 14 Mar 2023 10:00:42 -0700 (PDT) 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=@bootlin.com header.s=gm1 header.b=ih5vssL0; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230280AbjCNQfQ (ORCPT <rfc822;realc9580@gmail.com> + 99 others); Tue, 14 Mar 2023 12:35:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56804 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230393AbjCNQes (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 14 Mar 2023 12:34:48 -0400 Received: from relay11.mail.gandi.net (relay11.mail.gandi.net [217.70.178.231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F4D79B2C8; Tue, 14 Mar 2023 09:34:36 -0700 (PDT) Received: (Authenticated sender: clement.leger@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id F1EC5100015; Tue, 14 Mar 2023 16:34:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1678811675; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ib/mOXHYH3Do6zNpWmBQIKneKPV3vlWtkcbraPhLrAg=; b=ih5vssL02L5TJGe1puUEuS45ApxJCkgWpDrdKKwo3ZhoBbYGXma9Tcze0iLwiCCvNCk8bs pXMp8PDBrRVQ42l3FGgG0ubSfIYJ5vfbLsQ03YGwTK0qxuBGqeQZm6KqoV/Eeyf/NpOjGH QqEr6HClriLceSw5QvZiRnq1tbEuxQgQTqaKBYa/Wg2Ezcbx/j3fBBefFya2K2K8CavadV pINOeZdxhvO24skOBdaNHxipxHZ76Mh6CcpyC6gD3Nd4V5dLXTOQU8V8+wjFS3ADd6w+63 mvrTACxsxC1AwoqJg6aBjJ2dtYek6WbP4X2cVd3yK1mqKN1/X0aNdCDMZUCEaw== From: =?utf-8?b?Q2zDqW1lbnQgTMOpZ2Vy?= <clement.leger@bootlin.com> To: Andrew Lunn <andrew@lunn.ch>, Florian Fainelli <f.fainelli@gmail.com>, Vladimir Oltean <olteanv@gmail.com>, "David S. Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com> Cc: =?utf-8?b?Q2zDqW1lbnQgTMOpZ2Vy?= <clement.leger@bootlin.com>, Thomas Petazzoni <thomas.petazzoni@bootlin.com>, Herve Codina <herve.codina@bootlin.com>, =?utf-8?q?Miqu=C3=A8l_Raynal?= <miquel.raynal@bootlin.com>, Milan Stevanovic <milan.stevanovic@se.com>, Jimmy Lalande <jimmy.lalande@se.com>, Pascal Eberhard <pascal.eberhard@se.com>, Arun Ramadoss <Arun.Ramadoss@microchip.com>, linux-renesas-soc@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH RESEND net-next v4 2/3] net: dsa: rzn1-a5psw: add support for .port_bridge_flags Date: Tue, 14 Mar 2023 17:36:50 +0100 Message-Id: <20230314163651.242259-3-clement.leger@bootlin.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230314163651.242259-1-clement.leger@bootlin.com> References: <20230314163651.242259-1-clement.leger@bootlin.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1760363274514801473?= X-GMAIL-MSGID: =?utf-8?q?1760363274514801473?= |
Series |
net: dsa: rzn1-a5psw: add support for vlan and .port_bridge_flags
|
|
Commit Message
Clément Léger
March 14, 2023, 4:36 p.m. UTC
When running vlan test (bridge_vlan_aware/unaware.sh), there were some failure due to the lack .port_bridge_flag function to disable port flooding. Implement this operation for BR_LEARNING, BR_FLOOD, BR_MCAST_FLOOD and BR_BCAST_FLOOD. Signed-off-by: Clément Léger <clement.leger@bootlin.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> --- drivers/net/dsa/rzn1_a5psw.c | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
Comments
On Tue, Mar 14, 2023 at 05:36:50PM +0100, Clément Léger wrote: > When running vlan test (bridge_vlan_aware/unaware.sh), there were some > failure due to the lack .port_bridge_flag function to disable port > flooding. Implement this operation for BR_LEARNING, BR_FLOOD, > BR_MCAST_FLOOD and BR_BCAST_FLOOD. > > Signed-off-by: Clément Léger <clement.leger@bootlin.com> > Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> > --- Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
On Tue, Mar 14, 2023 at 05:36:50PM +0100, Clément Léger wrote: > +static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port, > + struct switchdev_brport_flags flags, > + struct netlink_ext_ack *extack) > +{ > + if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | > + BR_BCAST_FLOOD)) > + return -EINVAL; > + > + return 0; > +} > + > +static int > +a5psw_port_bridge_flags(struct dsa_switch *ds, int port, > + struct switchdev_brport_flags flags, > + struct netlink_ext_ack *extack) > +{ > + struct a5psw *a5psw = ds->priv; > + u32 val; > + > + if (flags.mask & BR_LEARNING) { > + val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port); > + a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, > + A5PSW_INPUT_LEARN_DIS(port), val); > + } 2 issues. 1: does this not get overwritten by a5psw_port_stp_state_set()? 2: What is the hardware default value for A5PSW_INPUT_LEARN? Please make sure that standalone ports have learning disabled by default, when the driver probes. > + > + if (flags.mask & BR_FLOOD) { > + val = flags.val & BR_FLOOD ? BIT(port) : 0; > + a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val); > + } > + > + if (flags.mask & BR_MCAST_FLOOD) { > + val = flags.val & BR_MCAST_FLOOD ? BIT(port) : 0; > + a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val); > + } > + > + if (flags.mask & BR_BCAST_FLOOD) { > + val = flags.val & BR_BCAST_FLOOD ? BIT(port) : 0; > + a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val); > + } Humm, there's a (huge) problem with this flooding mask. a5psw_flooding_set_resolution() - called from a5psw_port_bridge_join() and a5psw_port_bridge_leave() - touches the same registers as a5psw_port_bridge_flags(). Which means that your bridge forwarding domain controls are the same as your flooding controls. Which is bad news, because dsa_port_bridge_leave() -> dsa_port_switchdev_unsync_attrs() -> dsa_port_clear_brport_flags() -> dsa_port_bridge_flags() -> a5psw_port_bridge_flags() enables flooding on the port after calling a5psw_port_bridge_leave(). So the port which has left a bridge is standalone, but it still forwards packets to the other bridged ports! You should be able to see that this is the case, if you put the ports under a dummy bridge, then run tools/testing/selftests/drivers/net/dsa/no_forwarding.sh.
Le Wed, 15 Mar 2023 01:08:21 +0200, Vladimir Oltean <olteanv@gmail.com> a écrit : > On Tue, Mar 14, 2023 at 05:36:50PM +0100, Clément Léger wrote: > > +static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port, > > + struct switchdev_brport_flags flags, > > + struct netlink_ext_ack *extack) > > +{ > > + if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | > > + BR_BCAST_FLOOD)) > > + return -EINVAL; > > + > > + return 0; > > +} > > + > > +static int > > +a5psw_port_bridge_flags(struct dsa_switch *ds, int port, > > + struct switchdev_brport_flags flags, > > + struct netlink_ext_ack *extack) > > +{ > > + struct a5psw *a5psw = ds->priv; > > + u32 val; > > + > > + if (flags.mask & BR_LEARNING) { > > + val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port); > > + a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, > > + A5PSW_INPUT_LEARN_DIS(port), val); > > + } > > 2 issues. > > 1: does this not get overwritten by a5psw_port_stp_state_set()? Hum indeed. How is this kind of thing supposed to be handled ? Should I remove the handling of BR_LEARNING to forbid modifying it ? Ot should I allow it only if STP isn't enabled (which I'm not sure how to do it) ? > 2: What is the hardware default value for A5PSW_INPUT_LEARN? Please make > sure that standalone ports have learning disabled by default, when > the driver probes. > > > + > > + if (flags.mask & BR_FLOOD) { > > + val = flags.val & BR_FLOOD ? BIT(port) : 0; > > + a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val); > > + } > > + > > + if (flags.mask & BR_MCAST_FLOOD) { > > + val = flags.val & BR_MCAST_FLOOD ? BIT(port) : 0; > > + a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val); > > + } > > + > > + if (flags.mask & BR_BCAST_FLOOD) { > > + val = flags.val & BR_BCAST_FLOOD ? BIT(port) : 0; > > + a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val); > > + } > > Humm, there's a (huge) problem with this flooding mask. > > a5psw_flooding_set_resolution() - called from a5psw_port_bridge_join() > and a5psw_port_bridge_leave() - touches the same registers as > a5psw_port_bridge_flags(). Which means that your bridge forwarding > domain controls are the same as your flooding controls. > > Which is bad news, because > dsa_port_bridge_leave() > -> dsa_port_switchdev_unsync_attrs() > -> dsa_port_clear_brport_flags() > -> dsa_port_bridge_flags() > -> a5psw_port_bridge_flags() > > enables flooding on the port after calling a5psw_port_bridge_leave(). > So the port which has left a bridge is standalone, but it still forwards > packets to the other bridged ports! Actually not this way because the port is configured in a specific mode which only forward packet to the CPU ports. Indeed, we set a specific rule using the PATTERN_CTRL register with the MGMTFWD bit set: When set, the frame is forwarded to the management port only (suppressing destination address lookup). However, the port will received packets *from* the other ports (which is wrong... I can handle that by not setting the flooding attributes if the port is not in bridge. Doing so would definitely fix the various problems that could happen. BTW, the same goes with the learning bit that would be reenabled after leaving the bridge and you mentionned it should be disabled for a standalone port. > > You should be able to see that this is the case, if you put the ports > under a dummy bridge, then run tools/testing/selftests/drivers/net/dsa/no_forwarding.sh. Yes, makes sense. Thanks,
On Thu, Mar 16, 2023 at 12:53:29PM +0100, Clément Léger wrote: > Le Wed, 15 Mar 2023 01:08:21 +0200, > Vladimir Oltean <olteanv@gmail.com> a écrit : > > > On Tue, Mar 14, 2023 at 05:36:50PM +0100, Clément Léger wrote: > > > +static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port, > > > + struct switchdev_brport_flags flags, > > > + struct netlink_ext_ack *extack) > > > +{ > > > + if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | > > > + BR_BCAST_FLOOD)) > > > + return -EINVAL; > > > + > > > + return 0; > > > +} > > > + > > > +static int > > > +a5psw_port_bridge_flags(struct dsa_switch *ds, int port, > > > + struct switchdev_brport_flags flags, > > > + struct netlink_ext_ack *extack) > > > +{ > > > + struct a5psw *a5psw = ds->priv; > > > + u32 val; > > > + > > > + if (flags.mask & BR_LEARNING) { > > > + val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port); > > > + a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, > > > + A5PSW_INPUT_LEARN_DIS(port), val); > > > + } > > > > 2 issues. > > > > 1: does this not get overwritten by a5psw_port_stp_state_set()? > > Hum indeed. How is this kind of thing supposed to be handled ? Should I > remove the handling of BR_LEARNING to forbid modifying it ? Ot should I > allow it only if STP isn't enabled (which I'm not sure how to do it) ? It's handled correctly by only enabling learning in port_stp_state_set() if dp->learning allows it. See sja1105_bridge_stp_state_set(): case BR_STATE_LEARNING: mac[port].dyn_learn = dp->learning; break; case BR_STATE_FORWARDING: mac[port].dyn_learn = dp->learning; ocelot_bridge_stp_state_set(): if ((state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING) && ocelot_port->learn_ena) learn_ena = ANA_PORT_PORT_CFG_LEARN_ENA; ksz_port_stp_state_set(): case BR_STATE_LEARNING: if (!p->learning) data |= PORT_LEARN_DISABLE; break; case BR_STATE_FORWARDING: if (!p->learning) data |= PORT_LEARN_DISABLE; > > enables flooding on the port after calling a5psw_port_bridge_leave(). > > So the port which has left a bridge is standalone, but it still forwards > > packets to the other bridged ports! > > Actually not this way because the port is configured in a specific mode > which only forward packet to the CPU ports. Indeed, we set a specific > rule using the PATTERN_CTRL register with the MGMTFWD bit set: > When set, the frame is forwarded to the management port only > (suppressing destination address lookup). Ah, cool, this answers one of my issues in the other thread. > However, the port will received packets *from* the other ports (which is > wrong... I can handle that by not setting the flooding attributes if > the port is not in bridge. Doing so would definitely fix the various > problems that could happen. hmm.. I guess that could work?
diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c index 7dcca15e0b11..5059b2814cdd 100644 --- a/drivers/net/dsa/rzn1_a5psw.c +++ b/drivers/net/dsa/rzn1_a5psw.c @@ -342,6 +342,49 @@ static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port, a5psw->br_dev = NULL; } +static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | + BR_BCAST_FLOOD)) + return -EINVAL; + + return 0; +} + +static int +a5psw_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + struct a5psw *a5psw = ds->priv; + u32 val; + + if (flags.mask & BR_LEARNING) { + val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port); + a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, + A5PSW_INPUT_LEARN_DIS(port), val); + } + + if (flags.mask & BR_FLOOD) { + val = flags.val & BR_FLOOD ? BIT(port) : 0; + a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val); + } + + if (flags.mask & BR_MCAST_FLOOD) { + val = flags.val & BR_MCAST_FLOOD ? BIT(port) : 0; + a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val); + } + + if (flags.mask & BR_BCAST_FLOOD) { + val = flags.val & BR_BCAST_FLOOD ? BIT(port) : 0; + a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val); + } + + return 0; +} + static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) { u32 mask = A5PSW_INPUT_LEARN_DIS(port) | A5PSW_INPUT_LEARN_BLOCK(port); @@ -754,6 +797,8 @@ static const struct dsa_switch_ops a5psw_switch_ops = { .set_ageing_time = a5psw_set_ageing_time, .port_bridge_join = a5psw_port_bridge_join, .port_bridge_leave = a5psw_port_bridge_leave, + .port_pre_bridge_flags = a5psw_port_pre_bridge_flags, + .port_bridge_flags = a5psw_port_bridge_flags, .port_stp_state_set = a5psw_port_stp_state_set, .port_fast_age = a5psw_port_fast_age, .port_fdb_add = a5psw_port_fdb_add,