Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp3023003pxb; Fri, 12 Feb 2021 07:23:11 -0800 (PST) X-Google-Smtp-Source: ABdhPJwClsiaL9Q96FSxAK9qSqyP9q6vKh2Vgb4Z8b2BDy0NZJrIDmaEaJkLuHcbsLlPX/EquXCd X-Received: by 2002:a17:906:d84:: with SMTP id m4mr3490359eji.437.1613143391227; Fri, 12 Feb 2021 07:23:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613143391; cv=none; d=google.com; s=arc-20160816; b=Y3PPzuYOr03rXdpaXWvaA1dSH4IqOCEYoMSyUF+tilHRlAl7fmZeZKx7f+M4/8BYfr 0XfS2eaHQ9RatFaQJ9WBHN1YDdToUJzJ6gA+M1KL9UlUbA8QchHETfVdQGMJ+lErYNzV SaZoCEvDZJSWcMB+ZSlltvL7lg44KzmTjoCyZDIPQXSdwkQGrP55/1H7tm8siLhpyoK2 /DzdainayZ1imGAPpxeO1m+2sKf9Ni90M55go6JvbfjUinQ6Qr/xTh1DfMfPVAQkxkbd MY9L1SZ/C0geIWThJKf7bkmOEYdUrnqpxF0j6vTdALvuhSPpXsRMkOt2WGBLD7FG2uRO gh+g== 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=3txk3xzuaJ+luXWZVWBUlXIhxgR9+690DPw6ux/lwb4=; b=aOUZBVr0qIrInlFBT9n6W3Mj0P1eOgblS3Kv22bVyRkUBLfQaXADcAmeJ4QPFC6OOO PXUIYBYuq98Qy4VFs2Ostj/h2PXSM04TzjCBuwEmeHnged4QnEF4IR2ic5bn0vt6wWpl qbTS7rp7cvWCgKs1p5pqTy26BoNSFpYhxSSUWqfHEQdMxyPqX7l6UZyV4FrhjFNaIEZ7 zq7DKHfQWaazK/o7cCahmy/K8eDU489w8m5e+N5TMnPg8OdExRzSQyqG6vEQgipw9TnI GLu0E6HgEA3iXURJYwR/iQrqIFrKpfqZA4tanT1cL84BVIHAh1P0i3FYPk6ZXCnaR352 z35w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=SAmMq4yY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f16si6621480ejw.361.2021.02.12.07.22.48; Fri, 12 Feb 2021 07:23:11 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=SAmMq4yY; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232080AbhBLPSx (ORCPT + 99 others); Fri, 12 Feb 2021 10:18:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48068 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231567AbhBLPQ4 (ORCPT ); Fri, 12 Feb 2021 10:16:56 -0500 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 203D4C061788; Fri, 12 Feb 2021 07:16:16 -0800 (PST) Received: by mail-ej1-x62b.google.com with SMTP id f14so16221791ejc.8; Fri, 12 Feb 2021 07:16: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=3txk3xzuaJ+luXWZVWBUlXIhxgR9+690DPw6ux/lwb4=; b=SAmMq4yYxfpPC2vCJkMrc9KnpLTTPktTIn/W2GRELoK84+vCpMSng2nd/0KJ872EgL DUigC7Ex19jWXuHQdlrCjYQnqqXaTn32p4CEPo90PTz3oYOr23Hf8/H2yazHJ917p1OK PPiWvl3eIENuZhkpVXXlg0XEeQgXLERZvUOIndxSdnV0EdeDIXECxiTU4/v82bSwaE4N jUxaJnSiqa6VTnFZpZzSIjMx47xy+ZcAa3FdTpXyEVhuvWZCiKqAJLxBW82hmoiTqIai FRbSr2PeALPvhsuHbfUWzFNByVyQ9K5vjaaYxtRo1LjwwBBjq+ae+3kgXwaaQCtPwSGk Dmyg== 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=3txk3xzuaJ+luXWZVWBUlXIhxgR9+690DPw6ux/lwb4=; b=Mf9VMkDC7UoIoXfTVuEB4MtdVOJDda8Bvh3rU9ojuPWwLtQwCVgOE2g1nq6DFw8drc ueSxhEtSyyriF98iySgoRawLgCWD+6MCtMb5zAKiieAkrj1zzwNzEb+L1OTfV+DOvuoZ B6WyCMK8gr8/JjB1Owj/8dxz/tgIz75yp8i7PxAkwbDEe7mhDGTk8pmOcFEAOAdC+m75 MNr53N5gu7S4er/wNmvY593AJ6zaJMLa73f9Ay3qPlAOnjKP6BN3xjBMYcMbSvCgDdgv sUtYqAfJiTphePkQy728EtC4lav2IiOt4mBlG3+kefVTHOLKOl5gMf//P6Tjg/5G7tfU uqJQ== X-Gm-Message-State: AOAM530vNkRBXOKDr2LJ3pav2/pNA9PPQ3ms4rENbHibP8nky1vA2zf0 hGXhrqMjnzf/HKP68btAOQg= X-Received: by 2002:a17:906:86cf:: with SMTP id j15mr3454069ejy.194.1613142974845; Fri, 12 Feb 2021 07:16:14 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id z19sm6515456edr.69.2021.02.12.07.16.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 12 Feb 2021 07:16:14 -0800 (PST) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, bridge@lists.linux-foundation.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Vadym Kochan , Taras Chornyi , Grygorii Strashko , Vignesh Raghavendra , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH v5 net-next 04/10] net: dsa: configure better brport flags when ports leave the bridge Date: Fri, 12 Feb 2021 17:15:54 +0200 Message-Id: <20210212151600.3357121-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210212151600.3357121-1-olteanv@gmail.com> References: <20210212151600.3357121-1-olteanv@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Vladimir Oltean For a DSA switch port operating in standalone mode, address learning doesn't make much sense since that is a bridge function. In fact, address learning even breaks setups such as this one: +---------------------------------------------+ | | | +-------------------+ | | | br0 | send receive | | +--------+-+--------+ +--------+ +--------+ | | | | | | | | | | | | | swp0 | | swp1 | | swp2 | | swp3 | | | | | | | | | | | | +-+--------+-+--------+-+--------+-+--------+-+ | ^ | ^ | | | | | +-----------+ | | | +--------------------------------+ because if the switch has a single FDB (can offload a single bridge) then source address learning on swp3 can "steal" the source MAC address of swp2 from br0's FDB, because learning frames coming from swp2 will be done twice: first on the swp1 ingress port, second on the swp3 ingress port. So the hardware FDB will become out of sync with the software bridge, and when swp2 tries to send one more packet towards swp1, the ASIC will attempt to short-circuit the forwarding path and send it directly to swp3 (since that's the last port it learned that address on), which it obviously can't, because swp3 operates in standalone mode. So DSA drivers operating in standalone mode should still configure a list of bridge port flags even when they are standalone. Currently DSA attempts to call dsa_port_bridge_flags with 0, which disables egress flooding of unknown unicast and multicast, something which doesn't make much sense. For the switches that implement .port_egress_floods - b53 and mv88e6xxx, it probably doesn't matter too much either, since they can possibly inject traffic from the CPU into a standalone port, regardless of MAC DA, even if egress flooding is turned off for that port, but certainly not all DSA switches can do that - sja1105, for example, can't. So it makes sense to use a better common default there, such as "flood everything". It should also be noted that what DSA calls "dsa_port_bridge_flags()" is a degenerate name for just calling .port_egress_floods(), since nothing else is implemented - not learning, in particular. But disabling address learning, something that this driver is also coding up for, will be supported by individual drivers once .port_egress_floods is replaced with a more generic .port_bridge_flags. Previous attempts to code up this logic have been in the common bridge layer, but as pointed out by Ido Schimmel, there are corner cases that are missed when doing that: https://patchwork.kernel.org/project/netdevbpf/patch/20210209151936.97382-5-olteanv@gmail.com/ So, at least for now, let's leave DSA in charge of setting port flags before and after the bridge join and leave. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- Changes in v5: None. Changes in v4: None. Changes in v3: Patch is new, logically it was moved from the bridge layer to the DSA layer. net/dsa/port.c | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/net/dsa/port.c b/net/dsa/port.c index b93bda463026..1f877bf21bb4 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -122,6 +122,27 @@ void dsa_port_disable(struct dsa_port *dp) rtnl_unlock(); } +static void dsa_port_change_brport_flags(struct dsa_port *dp, + bool bridge_offload) +{ + unsigned long mask, flags; + int flag, err; + + mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; + if (bridge_offload) + flags = mask; + else + flags = mask & ~BR_LEARNING; + + for_each_set_bit(flag, &mask, 32) { + err = dsa_port_pre_bridge_flags(dp, BIT(flag)); + if (err) + continue; + + dsa_port_bridge_flags(dp, flags & BIT(flag)); + } +} + int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) { struct dsa_notifier_bridge_info info = { @@ -132,10 +153,10 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) }; int err; - /* Set the flooding mode before joining the port in the switch */ - err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD); - if (err) - return err; + /* Notify the port driver to set its configurable flags in a way that + * matches the initial settings of a bridge port. + */ + dsa_port_change_brport_flags(dp, true); /* Here the interface is already bridged. Reflect the current * configuration so that drivers can program their chips accordingly. @@ -146,7 +167,7 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) /* The bridging is rolled back on error */ if (err) { - dsa_port_bridge_flags(dp, 0); + dsa_port_change_brport_flags(dp, false); dp->bridge_dev = NULL; } @@ -172,8 +193,18 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) if (err) pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n"); - /* Port is leaving the bridge, disable flooding */ - dsa_port_bridge_flags(dp, 0); + /* Configure the port for standalone mode (no address learning, + * flood everything). + * The bridge only emits SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS events + * when the user requests it through netlink or sysfs, but not + * automatically at port join or leave, so we need to handle resetting + * the brport flags ourselves. But we even prefer it that way, because + * otherwise, some setups might never get the notification they need, + * for example, when a port leaves a LAG that offloads the bridge, + * it becomes standalone, but as far as the bridge is concerned, no + * port ever left. + */ + dsa_port_change_brport_flags(dp, false); /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer, * so allow it to be in BR_STATE_FORWARDING to be kept functional -- 2.25.1