From patchwork Sun Feb 7 23:21:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073549 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=unavailable 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 23D11C4332B for ; Sun, 7 Feb 2021 23:23:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0515664DE7 for ; Sun, 7 Feb 2021 23:23:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229716AbhBGXXy (ORCPT ); Sun, 7 Feb 2021 18:23:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46518 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229638AbhBGXXp (ORCPT ); Sun, 7 Feb 2021 18:23:45 -0500 Received: from mail-ed1-x529.google.com (mail-ed1-x529.google.com [IPv6:2a00:1450:4864:20::529]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32155C061786; Sun, 7 Feb 2021 15:23:05 -0800 (PST) Received: by mail-ed1-x529.google.com with SMTP id c6so16128098ede.0; Sun, 07 Feb 2021 15:23:05 -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=m/M4BuWposQchCicdEReyb7C0vsmEwgOGgW3VC+NZ6g=; b=JQSNwUzn0XRH4kCIjTYgB9hynQ9YZhunXZZbzjvMHjndkOq/oXEUHV5vepZJO17jT6 qTawomR7TcUgpb2mM3xGIY6MYvIiu+wWdXL7YBk+zns0HAKh5VU1wSEGnOtD/yRJaUiX AkYQ4bzoL4JY6q94LlvDG27eB4HaHi17mPCWGuOW1Vc/VauW6PWyWtHwPF+iJl7g5kus zlfcMyvYvkKH2/1FLSmwif8moVa0sdRyV0E3vHfTnVPXm4RxYsUa2CZIRbqkSyzT/Ero IOgAimIKosnCYeLhG/dtCumaPP+iH3oaZct72mL4m9lDh9J2fFo+39FBfeC1Goqqip1d NTEQ== 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=m/M4BuWposQchCicdEReyb7C0vsmEwgOGgW3VC+NZ6g=; b=D3q93uzuwnvsAZ5FfGtM3+PFp6QRPR7NZUpPPnMjSWAs/TeVbv7ZA2iLqcwYPgAo8Q oYH2N454s+Xfw74Knj44k8TEMaedgu6ComuVBiw3C4LSP1hsoDidZWufHIWmz9c5IFlt uMOyaH4Pb39+rXLhyti04ABBka0taCW3blKLoR+zjdfxCIfmNUtKWitdwYEAwdUdxK2d stJzB+18OlWGEjvVocCQJVVYf2Co3am+/GAgwXL9npUZXaWFmcou8flxc1qROdeCbcFP 3cXhNjrLDqdnqvgpScdOPdfzpHbNOHCr/bUgc4VJyNmDPn3BnINBy1INXD6MsBm+wJd9 2bxw== X-Gm-Message-State: AOAM531HlAsPh4RnyZv124Lk6maQi4DJi0vTI8Oz52VH/kMwUmekZ40k Ghh7bSEh0IEOoKoiAPnYfh0= X-Google-Smtp-Source: ABdhPJx0/11F6eJfTkWElJL6eTZpS/Il0fsX33bYY1gkCv1NYC7GL05D5o1qGH5jjeYD4p9DYpsM1w== X-Received: by 2002:a05:6402:202a:: with SMTP id ay10mr14602428edb.93.1612740183924; Sun, 07 Feb 2021 15:23:03 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:03 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 1/9] net: bridge: don't print in br_switchdev_set_port_flag Date: Mon, 8 Feb 2021 01:21:33 +0200 Message-Id: <20210207232141.2142678-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean Currently br_switchdev_set_port_flag has two options for error handling and neither is good: - The driver returns -EOPNOTSUPP in PRE_BRIDGE_FLAGS if it doesn't support offloading that flag, and this gets silently ignored and converted to an errno of 0. Nobody does this. - The driver returns some other error code, like -EINVAL, in PRE_BRIDGE_FLAGS, and br_switchdev_set_port_flag shouts loudly. The problem is that we'd like to offload some port flags during bridge join and leave, but also not have the bridge shout at us if those fail. But on the other hand we'd like the user to know that we can't offload something when they set that through netlink. And since we can't have the driver return -EOPNOTSUPP or -EINVAL depending on whether it's called by the user or internally by the bridge, let's just add an extack argument to br_switchdev_set_port_flag and propagate it to its callers. Then, when we need offloading to really fail silently, this can simply be passed a NULL argument. This is just a temporary patch because it's rather noisy. We'll propagate the extack through the switchdev notifier next. Signed-off-by: Vladimir Oltean --- net/bridge/br_netlink.c | 53 +++++++++++++++++++++++++-------------- net/bridge/br_private.h | 6 +++-- net/bridge/br_switchdev.c | 9 +++---- 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index bd3962da345a..02aa95c08b77 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -854,7 +854,8 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state) /* Set/clear or port flags based on attribute */ static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], - int attrtype, unsigned long mask) + int attrtype, unsigned long mask, + struct netlink_ext_ack *extack) { unsigned long flags; int err; @@ -867,7 +868,7 @@ static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], else flags = p->flags & ~mask; - err = br_switchdev_set_port_flag(p, flags, mask); + err = br_switchdev_set_port_flag(p, flags, mask, extack); if (err) return err; @@ -876,58 +877,71 @@ static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], } /* Process bridge protocol info on port */ -static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) +static int br_setport(struct net_bridge_port *p, struct nlattr *tb[], + struct netlink_ext_ack *extack) { unsigned long old_flags = p->flags; bool br_vlan_tunnel_old = false; int err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE); + err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD); + err = br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE); + err = br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, + BR_MULTICAST_FAST_LEAVE, extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK); + err = br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING); + err = br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD); + err = br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD); + err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST); + err = br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, + BR_MULTICAST_TO_UNICAST, extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, BR_BCAST_FLOOD); + err = br_set_port_flag(p, tb, IFLA_BRPORT_BCAST_FLOOD, + BR_BCAST_FLOOD, extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP); + err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP, + extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI); + err = br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, + BR_PROXYARP_WIFI, extack); if (err) return err; br_vlan_tunnel_old = (p->flags & BR_VLAN_TUNNEL) ? true : false; - err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL); + err = br_set_port_flag(p, tb, IFLA_BRPORT_VLAN_TUNNEL, BR_VLAN_TUNNEL, + extack); if (err) return err; @@ -983,11 +997,12 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) } err = br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS, - BR_NEIGH_SUPPRESS); + BR_NEIGH_SUPPRESS, extack); if (err) return err; - err = br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED); + err = br_set_port_flag(p, tb, IFLA_BRPORT_ISOLATED, BR_ISOLATED, + extack); if (err) return err; @@ -1046,7 +1061,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags, return err; spin_lock_bh(&p->br->lock); - err = br_setport(p, tb); + err = br_setport(p, tb, extack); spin_unlock_bh(&p->br->lock); } else { /* Binary compatibility with old RSTP */ @@ -1141,7 +1156,7 @@ static int br_port_slave_changelink(struct net_device *brdev, return 0; spin_lock_bh(&br->lock); - ret = br_setport(br_port_get_rtnl(dev), data); + ret = br_setport(br_port_get_rtnl(dev), data, extack); spin_unlock_bh(&br->lock); return ret; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index d242ba668e47..a1639d41188b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1575,7 +1575,8 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, const struct sk_buff *skb); int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, - unsigned long mask); + unsigned long mask, + struct netlink_ext_ack *extack); void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type); int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, @@ -1605,7 +1606,8 @@ static inline bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, static inline int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, - unsigned long mask) + unsigned long mask, + struct netlink_ext_ack *extack) { return 0; } diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index a9c23ef83443..c18e1d600dc6 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -60,7 +60,8 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, - unsigned long mask) + unsigned long mask, + struct netlink_ext_ack *extack) { struct switchdev_attr attr = { .orig_dev = p->dev, @@ -83,8 +84,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, return 0; if (err) { - br_warn(p->br, "bridge flag offload is not supported %u(%s)\n", - (unsigned int)p->port_no, p->dev->name); + NL_SET_ERR_MSG_MOD(extack, "bridge flag offload is not supported"); return -EOPNOTSUPP; } @@ -94,8 +94,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, err = switchdev_port_attr_set(p->dev, &attr); if (err) { - br_warn(p->br, "error setting offload flag on port %u(%s)\n", - (unsigned int)p->port_no, p->dev->name); + NL_SET_ERR_MSG_MOD(extack, "error setting offload flag on port"); return err; } From patchwork Sun Feb 7 23:21:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073551 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 0448CC433E0 for ; Sun, 7 Feb 2021 23:24:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CDF3364E37 for ; Sun, 7 Feb 2021 23:24:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229731AbhBGXX4 (ORCPT ); Sun, 7 Feb 2021 18:23:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229587AbhBGXXr (ORCPT ); Sun, 7 Feb 2021 18:23:47 -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 E48ABC061788; Sun, 7 Feb 2021 15:23:06 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id t5so16045313eds.12; Sun, 07 Feb 2021 15:23:06 -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=6V55UnxJUNtfF6mxxNh3yKhc1dFJ3yj+qa4nTLp6jtE=; b=DPRbClDr7Vg+0mguADIfQHBYikc2VIF/iM9jM1UCG+tDLOMb14ohD6ddMzvpiWH6E+ e3PuoUs0X8dmbHkNJEa+LpbU8LB7BYinlyk6jRSyDV5G3SCNyzqkcn1hCgosQwn0hN/M MShwLFFPiEXvVcai0LX5TmQZ9Xpr2mcTU+b4xGd4xpQwlUQFXd8pLktm/NSpaTsp3T6e RxHuhW6uy4eRxUt0IIVUNdGc6FlQY042PsLa1fB2zWO+Oj5Bi9rdHWb9juts3Lo4yA+M 0LwOSZY0XxvXMvfP0XAJ+phaYAsHekZR1AwrikpYsQXv3nblfAm5YEnTRGE/ZdnipA0N OtsA== 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=6V55UnxJUNtfF6mxxNh3yKhc1dFJ3yj+qa4nTLp6jtE=; b=hKSENcX4ysJ6fhiuRmC+9JMBjtengWBNrSfk44h79WSEWIZgeyIAdQ0YOrndoymTB4 AwNf5JLisMvy+KU0wbQ+wHu8jz+imrecuDwrDqkoq5z2uohpfN6JDFn3AD3bwpme727p SEo5PAs9DNRXroGKw1bV7gRkiwlGP5pO52HmiUi/ixHiV1im9H928p9QJICNebXIQgDy 0rpJoOdg2pu/+1+9JwJRWCkQFj3z89Uh6vZJRcvo83T0OK/1y1TMMh613Y88stqJjaD/ QMKMJGl2nmwv5Uxa9g3hm8iudAAqgwqnPKPcBNW4vFrIVKV+3PphzRUkUGH3y2bWmKOM BYsQ== X-Gm-Message-State: AOAM530YCb1iaXdr2P/p/lNMEUF5WJa73jfL2tZXDhkR1vgmIrYDBAov 6b/R87R2YZ1/4DkPysjPFvU= X-Google-Smtp-Source: ABdhPJxFXRT+UaRgQIPAfUruJlA37l9D7M819lc+InVk0Y5KYktwCobz9FZ4zl3qpNXCsv5BqmAmlw== X-Received: by 2002:a05:6402:6d6:: with SMTP id n22mr14431087edy.128.1612740185569; Sun, 07 Feb 2021 15:23:05 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:05 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 2/9] net: bridge: offload initial and final port flags through switchdev Date: Mon, 8 Feb 2021 01:21:34 +0200 Message-Id: <20210207232141.2142678-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean It must first be admitted that switchdev device drivers have a life beyond the bridge, and when they aren't offloading the bridge driver they are operating with forwarding disabled between ports, emulating as closely as possible N standalone network interfaces. Now it must be said that for a switchdev 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 ASIC 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 switchdev drivers operating in standalone mode should disable address learning. As a matter of practicality, we can reduce code duplication in drivers by having the bridge notify through switchdev of the initial and final brport flags. Then, drivers can simply start up hardcoded for no address learning (similar to how they already start up hardcoded for no forwarding), then they only need to listen for SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS and their job is basically done, no need for special cases when the port joins or leaves the bridge etc. When a port leaves the bridge (and therefore becomes standalone), we issue a switchdev attribute that apart from disabling address learning, enables flooding of all kinds. This is also done for pragmatic reasons, because even though standalone switchdev ports might not need to have flooding enabled in order to inject traffic with any MAC DA from the control interface, it certainly doesn't hurt either, and it even makes more sense than disabling flooding of unknown traffic towards that port. Note that the implementation is a bit wacky because the switchdev API for port attributes is very counterproductive. Instead of issuing a single switchdev notification with a bitwise OR of all flags that we're modifying, we need to issue 4 individual notifications, one for each bit. This is because the SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS notifier forces you to refuse the entire operation if there's at least one bit which you can't offload, and that is currently BR_BCAST_FLOOD which nobody does. So this change would do nothing for no one if we offloaded all flags at once, but the idea is to offload as much as possible instead of all or nothing. Signed-off-by: Vladimir Oltean --- net/bridge/br_if.c | 24 +++++++++++++++++++++++- net/bridge/br_netlink.c | 16 ++++------------ net/bridge/br_private.h | 2 ++ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f7d2f472ae24..8903333654f0 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -89,6 +89,21 @@ void br_port_carrier_check(struct net_bridge_port *p, bool *notified) spin_unlock_bh(&br->lock); } +int nbp_flags_change(struct net_bridge_port *p, unsigned long flags, + unsigned long mask, struct netlink_ext_ack *extack) +{ + int err; + + err = br_switchdev_set_port_flag(p, flags, mask, extack); + if (err) + return err; + + p->flags &= ~mask; + p->flags |= flags; + + return 0; +} + static void br_port_set_promisc(struct net_bridge_port *p) { int err = 0; @@ -343,6 +358,10 @@ static void del_nbp(struct net_bridge_port *p) update_headroom(br, get_max_headroom(br)); netdev_reset_rx_headroom(dev); + nbp_flags_change(p, 0, BR_LEARNING, NULL); + nbp_flags_change(p, BR_FLOOD, BR_FLOOD, NULL); + nbp_flags_change(p, BR_MCAST_FLOOD, BR_MCAST_FLOOD, NULL); + nbp_flags_change(p, BR_BCAST_FLOOD, BR_BCAST_FLOOD, NULL); nbp_vlan_flush(p); br_fdb_delete_by_port(br, p, 0, 1); switchdev_deferred_process(); @@ -428,7 +447,10 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, p->path_cost = port_cost(dev); p->priority = 0x8000 >> BR_PORT_BITS; p->port_no = index; - p->flags = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; + nbp_flags_change(p, BR_LEARNING, BR_LEARNING, NULL); + nbp_flags_change(p, BR_FLOOD, BR_FLOOD, NULL); + nbp_flags_change(p, BR_MCAST_FLOOD, BR_MCAST_FLOOD, NULL); + nbp_flags_change(p, BR_BCAST_FLOOD, BR_BCAST_FLOOD, NULL); br_init_port(p); br_set_state(p, BR_STATE_DISABLED); br_stp_port_timer_init(p); diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 02aa95c08b77..ab54d1daa9b4 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -852,28 +852,20 @@ static int br_set_port_state(struct net_bridge_port *p, u8 state) return 0; } -/* Set/clear or port flags based on attribute */ +/* Set/clear or port flags based on netlink attribute */ static int br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], int attrtype, unsigned long mask, struct netlink_ext_ack *extack) { - unsigned long flags; - int err; + unsigned long flags = 0; if (!tb[attrtype]) return 0; if (nla_get_u8(tb[attrtype])) - flags = p->flags | mask; - else - flags = p->flags & ~mask; - - err = br_switchdev_set_port_flag(p, flags, mask, extack); - if (err) - return err; + flags = mask; - p->flags = flags; - return 0; + return nbp_flags_change(p, flags, mask, extack); } /* Process bridge protocol info on port */ diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a1639d41188b..f064abd86bdf 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -749,6 +749,8 @@ netdev_features_t br_features_recompute(struct net_bridge *br, void br_port_flags_change(struct net_bridge_port *port, unsigned long mask); void br_manage_promisc(struct net_bridge *br); int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev); +int nbp_flags_change(struct net_bridge_port *p, unsigned long flags, + unsigned long mask, struct netlink_ext_ack *extack); /* br_input.c */ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb); From patchwork Sun Feb 7 23:21:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073553 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 4BB58C43381 for ; Sun, 7 Feb 2021 23:24:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1E1A364E37 for ; Sun, 7 Feb 2021 23:24:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229760AbhBGXYO (ORCPT ); Sun, 7 Feb 2021 18:24:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46532 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229702AbhBGXXt (ORCPT ); Sun, 7 Feb 2021 18:23:49 -0500 Received: from mail-ej1-x62f.google.com (mail-ej1-x62f.google.com [IPv6:2a00:1450:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F26CC06178A; Sun, 7 Feb 2021 15:23:08 -0800 (PST) Received: by mail-ej1-x62f.google.com with SMTP id l25so4535966eja.9; Sun, 07 Feb 2021 15:23:08 -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=e9XiWgYMfVUBSKTt2/GH7FXs22RSflWWzqO+GytFND8=; b=hrNsNNr92ti6PuUoJlwmbCFI/0za7J7d0/Mr1fl7pIVF/V67yqcNAU7YeBI1zSE4BR vSgZbG8ewwmWuad2Q2X9OSAP4c84PibFdy8bnfSPBkaQ9FmMBRHaN3w/O9cdp6mm9EV8 peKBNbGwlC6Vf40m7+O7ezFrNYLrfBDQGu+ob/LKU8JvBMEyGf3HXYSNIAPqbIBS7vif 3Eri2/HMq/LZ13WJHBIo1J5K9kcfOKCIJav6wJ+e3tptTsOgagQ5kZPg9d+zYB7WFel+ pb0WnbEwHIyu8EbFSKaQgXu1bBNnxT99UcGWQbSWSZ1xu9g3g6ZWAW8/5kh+P6vKWZ9M uU4g== 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=e9XiWgYMfVUBSKTt2/GH7FXs22RSflWWzqO+GytFND8=; b=iKXJ2ODQAbBoRNzAkAs/QuHRs+6VA4fqHfaTcC/b+9EXZDq0IscHbQc0k/ZvsN/3zK ahzgV9P9JBDRMq2B2gEZ9v7LuS3BeU2nigI1gCNT2ik0qx6FvmM2I5YJMPWDvBjIy3pk AWGj7hPDZTUlaqdwQQX+qAgUU70WCTRZ89fY3lrU5EzT+nDKSZiAsC+wLBJqhajS30SZ 6p2ocRy/cwkMlWOsx4VzwJhO05D/Vvhruz305i61F8MZHE0Q5t+sIJxEd9Y3a0gtbp+X kzAsoHrtJlhYC4MwnUuTJCB5bYS7zUpPLCnSFvRFmxcZg2w9tRnGAHm30kkBqW1tcbxl 3MIA== X-Gm-Message-State: AOAM533rRMtmZPosopqVpmgrb1cxlPQ1P1+jkVw9e0m31MTozQND9+fC 78wZ271/qha9SP7VvkR+M30= X-Google-Smtp-Source: ABdhPJzZ9hMYurUekGo++xUICdbenx+WJqC9rfS+Fr5RgTrA/SSw5oKu9PUajnSEZ4VhPv4nmDn8BQ== X-Received: by 2002:a17:906:f4f:: with SMTP id h15mr14443806ejj.498.1612740187258; Sun, 07 Feb 2021 15:23:07 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:06 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 3/9] net: dsa: stop setting initial and final brport flags Date: Mon, 8 Feb 2021 01:21:35 +0200 Message-Id: <20210207232141.2142678-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean With the bridge driver doing that for us now, we can simplify our mid-layer logic a little bit, which would have otherwise needed some tuning for the disabling of address learning that is necessary in standalone mode. Signed-off-by: Vladimir Oltean --- net/dsa/port.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/net/dsa/port.c b/net/dsa/port.c index 5e079a61528e..aa1cbba7f89f 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -132,11 +132,6 @@ 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; - /* Here the interface is already bridged. Reflect the current * configuration so that drivers can program their chips accordingly. */ @@ -145,10 +140,8 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) err = dsa_broadcast(DSA_NOTIFIER_BRIDGE_JOIN, &info); /* The bridging is rolled back on error */ - if (err) { - dsa_port_bridge_flags(dp, 0); + if (err) dp->bridge_dev = NULL; - } return err; } @@ -172,9 +165,6 @@ 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); - /* 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 */ From patchwork Sun Feb 7 23:21:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073555 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=unavailable 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 B436DC433E6 for ; Sun, 7 Feb 2021 23:25:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 798CC64E3B for ; Sun, 7 Feb 2021 23:25:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229821AbhBGXYk (ORCPT ); Sun, 7 Feb 2021 18:24:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229766AbhBGXYW (ORCPT ); Sun, 7 Feb 2021 18:24:22 -0500 Received: from mail-ej1-x636.google.com (mail-ej1-x636.google.com [IPv6:2a00:1450:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 608CBC06178B; Sun, 7 Feb 2021 15:23:10 -0800 (PST) Received: by mail-ej1-x636.google.com with SMTP id bl23so21822698ejb.5; Sun, 07 Feb 2021 15:23:10 -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=7ThCOkenuQFpeKsMtK2nCof+I8uOT9vtJkcRp6jlfyM=; b=S0uj7F9ziMIrG/frHxikHmNavPB2oPJMgnfejwjEnf3++bLVO+jiSXqXDb67RilIRK ZNFKZ3yUAJHrinDluQDa8Q9kIUb6OK/H0MnWmdZ7KtEpcmE+FnHo+BaZltqmaj+Y/Iom QRsFOB6WjOHnJCo7gpaTf+/Rvki0zXdNclhfksklp7YlDrxLk1E1EIuC/YgBiJRyF4Ep jClRQZU/zLQmciVUCcWhA4JB7kzlmsjubtvYC6FFja0ZotO/e/7VhCUGR3mVIrLG5N/o w5yuaF/SO7BwtBgb8lC8ihjLQEY96ou2Fp/C3/J131MFOP98nzMnwhp5Aa8I66doGGLG 7n6g== 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=7ThCOkenuQFpeKsMtK2nCof+I8uOT9vtJkcRp6jlfyM=; b=KhmEfUJ1iclljs1APenx+qYce+KgnoobIdn5HOT8RsdHIJdbzR4pNKeACdorrDOY71 FxBV3iPj7/1MiyQdplZhUTjYAvNZhWVIy/jLs/1vI4zyOq36Bfjww0kdsGYFiwh9NXrG Wx1oaRCLyo2G5u7LLsuXXeYIaBrPwu7Dr6w8Sb3rA4CznxUyCmkbN7neG2+jotOnvtdp MT95n1VzWRTNNRlCxB8v3I0bzHtF8Ukbiw87KJ1G3yQVzDCdU+gGvvtmNNtUiG3sBq18 TOwSXg22RYJWGRWo/Al0SMoYd+9eoOIpXbayBUmKSCIxWItugX3SdaPucT6OYvpREScO i7OA== X-Gm-Message-State: AOAM531EOvO63XCkWJffPWDgahocHyj9Cbg9AjCftt4GtV/walP38Dc4 8lL4HLSG8HSwmxrYsfjLOd0I+FyELIQ= X-Google-Smtp-Source: ABdhPJxPH2FRRS6x0ZxKv+1VDOQZw4FUBawIfctuOxS/cHD2Eu6xWRK+tp6UXAOBLXpdNImeR/pj8Q== X-Received: by 2002:a17:906:9249:: with SMTP id c9mr14454993ejx.416.1612740188939; Sun, 07 Feb 2021 15:23:08 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:08 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 4/9] net: dsa: kill .port_egress_floods overengineering Date: Mon, 8 Feb 2021 01:21:36 +0200 Message-Id: <20210207232141.2142678-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean The bridge offloads the port flags through a single bit mask using switchdev, which among others, contains learning and flooding settings. The commit 57652796aa97 ("net: dsa: add support for bridge flags") missed one crucial aspect of the SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS API when designing the API one level lower, towards the drivers. This is that the bitmask of passed brport flags never has more than one bit set at a time. On the other hand, the prototype passed to the driver is .port_egress_floods(int port, bool unicast, bool multicast), which configures two flags at a time. If the bridge wants to see what flags are supported by the device, it emits a SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS attribute. DSA currently checks if .port_egress_floods is implemented, and if it is, reports both BR_FLOOD and BR_MCAST_FLOOD. So the driver has no choice if it wants to inform the bridge that it can configure unicast flooding but not multicast flooding - the DSA mid layer is standing in the way. Secondly, as outlined in the first paragraph, flooding is not all that is passed through the brport flags bitmask, but also learning. If a DSA switch wanted to configure its learning parameter in spirit of the current API, new logic would need to be added to DSA for .port_set_learning. This implies that dsa_port_pre_bridge_flags would have to deduce, based on which of .port_set_learning and .port_egress_floods are implemented, what to mark as supported, and then figure out which of .port_set_learning or .port_egress_floods to call from dsa_port_bridge_flags. The latter is non-trivial because, as mentioned, all brport flags finally end up offloaded in the same bitmask, and ideally we wouldn't want DSA to call an unneeded method, i.e. .port_set_learning when nothing learning-related has changed, or .port_egress_floods when nothing flooding-related has changed, especially when the reconfiguration for that might involve a switch reset. So to avoid that, DSA's only option would be to perform 'edge detection' by keeping an unsigned long dsa_port::brport_flags and check for the XOR between the cached value and the new flags in order to determine what changed. Either that, or make the drivers check early if anything has changed, and return if not. But either way, this is fairly overengineered. Thirdly, currently DSA deems the driver too dumb to deserve knowing that a SWITCHDEV_ATTR_ID_BRIDGE_MROUTER attribute was offloaded, because it just calls .port_egress_floods for the CPU port. When we'll add support for the plain SWITCHDEV_ATTR_ID_PORT_MROUTER, that will become a real problem because the flood settings will need to be held statefully in the DSA middle layer, otherwise changing the mrouter port attribute will impact the flooding attribute. And that's _assuming_ that the underlying hardware doesn't have anything else to do when a multicast router attaches to a port than flood unknown traffic to it. If it does, there will need to be a dedicated .port_set_mrouter anyway. Lastly, we have DSA drivers that have a backlink into a pure switchdev driver (felix -> ocelot). It seems reasonable that the other switchdev drivers should not have to suffer from the oddities of DSA overengineering, so keeping DSA a pass-through layer makes more sense there. To simplify the brport flags situation we just delete .port_egress_floods and we introduce .port_pre_bridge_flags and .port_bridge_flags which are passed to the driver. Also, the logic from dsa_port_mrouter is removed and a .port_set_mrouter is created. The .port_pre_bridge_flags callback is temporary and will be removed in a later patch, together with SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS. Functionally speaking, we simply move the calls to .port_egress_floods one step lower, in the two drivers that implement it: mv88e6xxx and b53, so things should work just as before. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/b53/b53_common.c | 24 +++++++++++++++++++++++- drivers/net/dsa/mv88e6xxx/chip.c | 26 +++++++++++++++++++++++++- include/net/dsa.h | 8 ++++++-- net/dsa/dsa_priv.h | 2 +- net/dsa/port.c | 21 ++++++++------------- 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 23fc7225c8d1..0c4000783b15 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1948,6 +1948,26 @@ int b53_br_egress_floods(struct dsa_switch *ds, int port, } EXPORT_SYMBOL(b53_br_egress_floods); +static int b53_pre_br_flags(struct dsa_switch *ds, int port, + unsigned long mask) +{ + if (mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) + return -EINVAL; + + return 0; +} + +static int b53_br_flags(struct dsa_switch *ds, int port, unsigned long flags) +{ + return b53_br_egress_floods(ds, port, flags & BR_FLOOD, + flags & BR_MCAST_FLOOD); +} + +static int b53_set_mrouter(struct dsa_switch *ds, int port, bool mrouter) +{ + return b53_br_egress_floods(ds, port, true, mrouter); +} + static bool b53_possible_cpu_port(struct dsa_switch *ds, int port) { /* Broadcom switches will accept enabling Broadcom tags on the @@ -2187,9 +2207,11 @@ static const struct dsa_switch_ops b53_switch_ops = { .set_mac_eee = b53_set_mac_eee, .port_bridge_join = b53_br_join, .port_bridge_leave = b53_br_leave, + .port_bridge_flags = b53_br_flags, + .port_pre_bridge_flags = b53_pre_br_flags, + .port_set_mrouter = b53_set_mrouter, .port_stp_state_set = b53_br_set_stp_state, .port_fast_age = b53_br_fast_age, - .port_egress_floods = b53_br_egress_floods, .port_vlan_filtering = b53_vlan_filtering, .port_vlan_add = b53_vlan_add, .port_vlan_del = b53_vlan_del, diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index ae0b490f00cd..bd986244aa27 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -5380,6 +5380,28 @@ static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, return err; } +static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port, + unsigned long mask) +{ + if (mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) + return -EINVAL; + + return 0; +} + +static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port, + unsigned long flags) +{ + return mv88e6xxx_port_egress_floods(ds, port, flags & BR_FLOOD, + flags & BR_MCAST_FLOOD); +} + +static int mv88e6xxx_port_set_mrouter(struct dsa_switch *ds, int port, + bool mrouter) +{ + return mv88e6xxx_port_egress_floods(ds, port, true, mrouter); +} + static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds, struct net_device *lag, struct netdev_lag_upper_info *info) @@ -5678,7 +5700,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .set_ageing_time = mv88e6xxx_set_ageing_time, .port_bridge_join = mv88e6xxx_port_bridge_join, .port_bridge_leave = mv88e6xxx_port_bridge_leave, - .port_egress_floods = mv88e6xxx_port_egress_floods, + .port_pre_bridge_flags = mv88e6xxx_port_pre_bridge_flags, + .port_bridge_flags = mv88e6xxx_port_bridge_flags, + .port_set_mrouter = mv88e6xxx_port_set_mrouter, .port_stp_state_set = mv88e6xxx_port_stp_state_set, .port_fast_age = mv88e6xxx_port_fast_age, .port_vlan_filtering = mv88e6xxx_port_vlan_filtering, diff --git a/include/net/dsa.h b/include/net/dsa.h index 60acb9fca124..e37fee22caab 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -621,8 +621,12 @@ struct dsa_switch_ops { void (*port_stp_state_set)(struct dsa_switch *ds, int port, u8 state); void (*port_fast_age)(struct dsa_switch *ds, int port); - int (*port_egress_floods)(struct dsa_switch *ds, int port, - bool unicast, bool multicast); + int (*port_pre_bridge_flags)(struct dsa_switch *ds, int port, + unsigned long mask); + int (*port_bridge_flags)(struct dsa_switch *ds, int port, + unsigned long flags); + int (*port_set_mrouter)(struct dsa_switch *ds, int port, + bool mrouter); /* * VLAN support diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 8a1bcb2b4208..da99961599de 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -174,7 +174,7 @@ int dsa_port_mdb_add(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); int dsa_port_mdb_del(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); -int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags); +int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long mask); int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags); int dsa_port_mrouter(struct dsa_port *dp, bool mrouter); int dsa_port_vlan_add(struct dsa_port *dp, diff --git a/net/dsa/port.c b/net/dsa/port.c index aa1cbba7f89f..8df492412138 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -382,39 +382,34 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock) return 0; } -int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags) +int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long mask) { struct dsa_switch *ds = dp->ds; - if (!ds->ops->port_egress_floods || - (flags & ~(BR_FLOOD | BR_MCAST_FLOOD))) + if (!ds->ops->port_pre_bridge_flags) return -EINVAL; - return 0; + return ds->ops->port_pre_bridge_flags(ds, dp->index, mask); } int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags) { struct dsa_switch *ds = dp->ds; - int port = dp->index; - int err = 0; - if (ds->ops->port_egress_floods) - err = ds->ops->port_egress_floods(ds, port, flags & BR_FLOOD, - flags & BR_MCAST_FLOOD); + if (!ds->ops->port_bridge_flags) + return -EINVAL; - return err; + return ds->ops->port_bridge_flags(ds, dp->index, flags); } int dsa_port_mrouter(struct dsa_port *dp, bool mrouter) { struct dsa_switch *ds = dp->ds; - int port = dp->index; - if (!ds->ops->port_egress_floods) + if (!ds->ops->port_set_mrouter) return -EOPNOTSUPP; - return ds->ops->port_egress_floods(ds, port, true, mrouter); + return ds->ops->port_set_mrouter(ds, dp->index, mrouter); } int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu, From patchwork Sun Feb 7 23:21:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073557 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=unavailable 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 0541FC4332B for ; Sun, 7 Feb 2021 23:25:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CA74364E54 for ; Sun, 7 Feb 2021 23:25:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229866AbhBGXYy (ORCPT ); Sun, 7 Feb 2021 18:24:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229767AbhBGXYW (ORCPT ); Sun, 7 Feb 2021 18:24:22 -0500 Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com [IPv6:2a00:1450:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3CA3EC06178C; Sun, 7 Feb 2021 15:23:12 -0800 (PST) Received: by mail-ed1-x535.google.com with SMTP id c6so16128248ede.0; Sun, 07 Feb 2021 15:23:12 -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=zlz7bjVNF9/MTX7P6d7PFu82V+wVVk03D7gELioz3RY=; b=tMDU8Wau3BKsMIp9zSNU/vVpu+R9i2v5rNtpE8xgVw3O04otVqldC+qBpIgjtrM9sM 8YzamjttyJX6ZozN9YFwYaffPKwUEL2+2RmLGyVqlc2Co6WplGPiFFqJhV+gAZZ3Aw+V 0T3bXSXKqrhwZPxoMy5c0ZQZ42w0dMACrsxlkbYmzBPI8Y0oxtvmLeykYEDJSHBTga4z GaCeiUdEMrIHo44rbg2q893+K9vXg1bptLGxpC1DUi66rrtJdCyjaYcNTtikjzIHa3x4 TFYsKl6Jl/ASk27RZ6Wsq6TxN967sZfZ0HPgRqVP6ZGF/vAVJw6Ca/EJk+0fZpJFYHLm wcHQ== 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=zlz7bjVNF9/MTX7P6d7PFu82V+wVVk03D7gELioz3RY=; b=lh9r5++7B8yYc6FlqQiLsP7ORNHucdmQW8Ym2rUUD506jzINMXXux0nbL8LLwJ/HFG QcWTgbPSI5IAinPT0WXz2XLwIL7wbpMoF8fUJs0Rw+Hrz+Wruu1aBjrAH4+I1oKrDoS7 vh1qmdZTLF0ePu2p+r5CO3kbg/iQfAGTVNQVkIKdN5md8yTYh+oBNISxvU9YMuNyALfK 8jvvwS2muu4USVDN/oiD11sCE8L6txd8NapZmCbaeuQY6T2EwFF88Wlob9w91gJ3cioB 0KLuyDyVkv6KWEdYd5EZLQ9MA048SGsNbQA1bCWF2/Ek+vSYXMBhZfOzO4KcTD4GbS6k wqQw== X-Gm-Message-State: AOAM533Dd9j9ImX9jd3MT0EL0iRocsFfyBXlm3cw+00cgCnZdA4vZMLY 4XkPEAhRAwXQCHZuLMUqMGY= X-Google-Smtp-Source: ABdhPJxgzqTjUTCIDYBHxdkJMnbe3ghH40nIGmdkZebswQtc5VMcvBx98km6RP5J4YgzpzNH+oyxhw== X-Received: by 2002:a05:6402:4253:: with SMTP id g19mr14532932edb.343.1612740190870; Sun, 07 Feb 2021 15:23:10 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:10 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 5/9] net: squash switchdev attributes PRE_BRIDGE_FLAGS and BRIDGE_FLAGS Date: Mon, 8 Feb 2021 01:21:37 +0200 Message-Id: <20210207232141.2142678-6-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean There does not appear to be any strong reason why br_switchdev_set_port_flag issues a separate notification for checking the supported brport flags rather than just attempting to apply them and propagating the error if that fails. However, there is a reason why this switchdev API is counterproductive for a driver writer, and that is because although br_switchdev_set_port_flag gets passed a "flags" and a "mask", those are passed piecemeal to the driver, so while the PRE_BRIDGE_FLAGS listener knows what changed because it has the "mask", the BRIDGE_FLAGS listener doesn't, because it only has the final value. This means that "edge detection" needs to be done by each individual BRIDGE_FLAGS listener by XOR-ing the old and the new flags, which in turn means that copying the flags into a driver private variable is strictly necessary. This can be solved by passing the "flags" and the "value" together into a single switchdev attribute, and it also reduces some boilerplate in the drivers that offload this. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/b53/b53_common.c | 16 ++++------- drivers/net/dsa/mv88e6xxx/chip.c | 17 ++++------- .../marvell/prestera/prestera_switchdev.c | 16 +++++------ .../mellanox/mlxsw/spectrum_switchdev.c | 28 ++++++------------- drivers/net/ethernet/rocker/rocker_main.c | 24 +++------------- drivers/net/ethernet/ti/cpsw_switchdev.c | 20 ++++--------- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 22 ++++----------- include/net/dsa.h | 4 +-- include/net/switchdev.h | 8 ++++-- net/bridge/br_switchdev.c | 19 ++++--------- net/dsa/dsa_priv.h | 4 +-- net/dsa/port.c | 15 ++-------- net/dsa/slave.c | 3 -- 13 files changed, 58 insertions(+), 138 deletions(-) diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 0c4000783b15..a713117111c6 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1948,19 +1948,14 @@ int b53_br_egress_floods(struct dsa_switch *ds, int port, } EXPORT_SYMBOL(b53_br_egress_floods); -static int b53_pre_br_flags(struct dsa_switch *ds, int port, - unsigned long mask) +static int b53_br_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags val) { - if (mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) + if (val.mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) return -EINVAL; - return 0; -} - -static int b53_br_flags(struct dsa_switch *ds, int port, unsigned long flags) -{ - return b53_br_egress_floods(ds, port, flags & BR_FLOOD, - flags & BR_MCAST_FLOOD); + return b53_br_egress_floods(ds, port, val.flags & BR_FLOOD, + val.flags & BR_MCAST_FLOOD); } static int b53_set_mrouter(struct dsa_switch *ds, int port, bool mrouter) @@ -2208,7 +2203,6 @@ static const struct dsa_switch_ops b53_switch_ops = { .port_bridge_join = b53_br_join, .port_bridge_leave = b53_br_leave, .port_bridge_flags = b53_br_flags, - .port_pre_bridge_flags = b53_pre_br_flags, .port_set_mrouter = b53_set_mrouter, .port_stp_state_set = b53_br_set_stp_state, .port_fast_age = b53_br_fast_age, diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index bd986244aa27..deb68e54fa74 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -5380,20 +5380,14 @@ static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, return err; } -static int mv88e6xxx_port_pre_bridge_flags(struct dsa_switch *ds, int port, - unsigned long mask) +static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags val) { - if (mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) + if (val.mask & ~(BR_FLOOD | BR_MCAST_FLOOD)) return -EINVAL; - return 0; -} - -static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port, - unsigned long flags) -{ - return mv88e6xxx_port_egress_floods(ds, port, flags & BR_FLOOD, - flags & BR_MCAST_FLOOD); + return mv88e6xxx_port_egress_floods(ds, port, val.flags & BR_FLOOD, + val.flags & BR_MCAST_FLOOD); } static int mv88e6xxx_port_set_mrouter(struct dsa_switch *ds, int port, @@ -5700,7 +5694,6 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .set_ageing_time = mv88e6xxx_set_ageing_time, .port_bridge_join = mv88e6xxx_port_bridge_join, .port_bridge_leave = mv88e6xxx_port_bridge_leave, - .port_pre_bridge_flags = mv88e6xxx_port_pre_bridge_flags, .port_bridge_flags = mv88e6xxx_port_bridge_flags, .port_set_mrouter = mv88e6xxx_port_set_mrouter, .port_stp_state_set = mv88e6xxx_port_stp_state_set, diff --git a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c index 8c2b03151736..ab62945c7183 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c @@ -581,24 +581,27 @@ int prestera_bridge_port_event(struct net_device *dev, unsigned long event, static int prestera_port_attr_br_flags_set(struct prestera_port *port, struct net_device *dev, - unsigned long flags) + struct switchdev_brport_flags val) { struct prestera_bridge_port *br_port; int err; + if (val.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) + err = -EINVAL; + br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev); if (!br_port) return 0; - err = prestera_hw_port_flood_set(port, flags & BR_FLOOD); + err = prestera_hw_port_flood_set(port, val.flags & BR_FLOOD); if (err) return err; - err = prestera_hw_port_learning_set(port, flags & BR_LEARNING); + err = prestera_hw_port_learning_set(port, val.flags & BR_LEARNING); if (err) return err; - memcpy(&br_port->flags, &flags, sizeof(flags)); + memcpy(&br_port->flags, &val.flags, sizeof(val.flags)); return 0; } @@ -705,11 +708,6 @@ static int prestera_port_obj_attr_set(struct net_device *dev, err = prestera_port_attr_stp_state_set(port, attr->orig_dev, attr->u.stp_state); break; - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - if (attr->u.brport_flags & - ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) - err = -EINVAL; - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = prestera_port_attr_br_flags_set(port, attr->orig_dev, attr->u.brport_flags); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 20c4f3c2cf23..f19be04704e7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -653,23 +653,16 @@ mlxsw_sp_bridge_port_learning_set(struct mlxsw_sp_port *mlxsw_sp_port, return err; } -static int mlxsw_sp_port_attr_br_pre_flags_set(struct mlxsw_sp_port - *mlxsw_sp_port, - unsigned long brport_flags) -{ - if (brport_flags & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) - return -EINVAL; - - return 0; -} - static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, struct net_device *orig_dev, - unsigned long brport_flags) + struct switchdev_brport_flags val) { struct mlxsw_sp_bridge_port *bridge_port; int err; + if (val.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) + return -EINVAL; + bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp_port->mlxsw_sp->bridge, orig_dev); if (!bridge_port) @@ -677,12 +670,12 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp_bridge_port_flood_table_set(mlxsw_sp_port, bridge_port, MLXSW_SP_FLOOD_TYPE_UC, - brport_flags & BR_FLOOD); + val.flags & BR_FLOOD); if (err) return err; err = mlxsw_sp_bridge_port_learning_set(mlxsw_sp_port, bridge_port, - brport_flags & BR_LEARNING); + val.flags & BR_LEARNING); if (err) return err; @@ -691,13 +684,12 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, err = mlxsw_sp_bridge_port_flood_table_set(mlxsw_sp_port, bridge_port, MLXSW_SP_FLOOD_TYPE_MC, - brport_flags & - BR_MCAST_FLOOD); + val.flags & BR_MCAST_FLOOD); if (err) return err; out: - memcpy(&bridge_port->flags, &brport_flags, sizeof(brport_flags)); + memcpy(&bridge_port->flags, &val.flags, sizeof(val.flags)); return 0; } @@ -898,10 +890,6 @@ static int mlxsw_sp_port_attr_set(struct net_device *dev, attr->orig_dev, attr->u.stp_state); break; - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - err = mlxsw_sp_port_attr_br_pre_flags_set(mlxsw_sp_port, - attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = mlxsw_sp_port_attr_br_flags_set(mlxsw_sp_port, attr->orig_dev, diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index 740a715c49c6..b8087dd0b284 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1575,8 +1575,8 @@ rocker_world_port_attr_bridge_flags_support_get(const struct rocker_port * } static int -rocker_world_port_attr_pre_bridge_flags_set(struct rocker_port *rocker_port, - unsigned long brport_flags) +rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, + struct switchdev_brport_flags val) { struct rocker_world_ops *wops = rocker_port->rocker->wops; unsigned long brport_flags_s; @@ -1590,22 +1590,10 @@ rocker_world_port_attr_pre_bridge_flags_set(struct rocker_port *rocker_port, if (err) return err; - if (brport_flags & ~brport_flags_s) + if (val.mask & ~brport_flags_s) return -EINVAL; - return 0; -} - -static int -rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, - unsigned long brport_flags) -{ - struct rocker_world_ops *wops = rocker_port->rocker->wops; - - if (!wops->port_attr_bridge_flags_set) - return -EOPNOTSUPP; - - return wops->port_attr_bridge_flags_set(rocker_port, brport_flags); + return wops->port_attr_bridge_flags_set(rocker_port, val.flags); } static int @@ -2056,10 +2044,6 @@ static int rocker_port_attr_set(struct net_device *dev, err = rocker_world_port_attr_stp_state_set(rocker_port, attr->u.stp_state); break; - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - err = rocker_world_port_attr_pre_bridge_flags_set(rocker_port, - attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = rocker_world_port_attr_bridge_flags_set(rocker_port, attr->u.brport_flags); diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c index 9967cf985728..dd4b1e161dde 100644 --- a/drivers/net/ethernet/ti/cpsw_switchdev.c +++ b/drivers/net/ethernet/ti/cpsw_switchdev.c @@ -57,12 +57,15 @@ static int cpsw_port_stp_state_set(struct cpsw_priv *priv, u8 state) static int cpsw_port_attr_br_flags_set(struct cpsw_priv *priv, struct net_device *orig_dev, - unsigned long brport_flags) + struct switchdev_brport_flags val) { struct cpsw_common *cpsw = priv->cpsw; bool unreg_mcast_add = false; - if (brport_flags & BR_MCAST_FLOOD) + if (val.mask & ~(BR_LEARNING | BR_MCAST_FLOOD)) + return -EINVAL; + + if (val.flags & BR_MCAST_FLOOD) unreg_mcast_add = true; dev_dbg(priv->dev, "BR_MCAST_FLOOD: %d port %u\n", unreg_mcast_add, priv->emac_port); @@ -73,15 +76,6 @@ static int cpsw_port_attr_br_flags_set(struct cpsw_priv *priv, return 0; } -static int cpsw_port_attr_br_flags_pre_set(struct net_device *netdev, - unsigned long flags) -{ - if (flags & ~(BR_LEARNING | BR_MCAST_FLOOD)) - return -EINVAL; - - return 0; -} - static int cpsw_port_attr_set(struct net_device *ndev, const struct switchdev_attr *attr) { @@ -91,10 +85,6 @@ static int cpsw_port_attr_set(struct net_device *ndev, dev_dbg(priv->dev, "attr: id %u port: %u\n", attr->id, priv->emac_port); switch (attr->id) { - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - ret = cpsw_port_attr_br_flags_pre_set(ndev, - attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_STP_STATE: ret = cpsw_port_stp_state_set(priv, attr->u.stp_state); dev_dbg(priv->dev, "stp state: %u\n", attr->u.stp_state); diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index ca3d07fe7f58..c4bcd63b68b8 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -908,28 +908,22 @@ static int dpaa2_switch_port_attr_stp_state_set(struct net_device *netdev, return dpaa2_switch_port_set_stp_state(port_priv, state); } -static int dpaa2_switch_port_attr_br_flags_pre_set(struct net_device *netdev, - unsigned long flags) -{ - if (flags & ~(BR_LEARNING | BR_FLOOD)) - return -EINVAL; - - return 0; -} - static int dpaa2_switch_port_attr_br_flags_set(struct net_device *netdev, - unsigned long flags) + struct switchdev_brport_flags val) { struct ethsw_port_priv *port_priv = netdev_priv(netdev); int err = 0; + if (val.mask & ~(BR_LEARNING | BR_FLOOD)) + return -EINVAL; + /* Learning is enabled per switch */ err = dpaa2_switch_set_learning(port_priv->ethsw_data, - !!(flags & BR_LEARNING)); + !!(val.flags & BR_LEARNING)); if (err) goto exit; - err = dpaa2_switch_port_set_flood(port_priv, !!(flags & BR_FLOOD)); + err = dpaa2_switch_port_set_flood(port_priv, !!(val.flags & BR_FLOOD)); exit: return err; @@ -945,10 +939,6 @@ static int dpaa2_switch_port_attr_set(struct net_device *netdev, err = dpaa2_switch_port_attr_stp_state_set(netdev, attr->u.stp_state); break; - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - err = dpaa2_switch_port_attr_br_flags_pre_set(netdev, - attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: err = dpaa2_switch_port_attr_br_flags_set(netdev, attr->u.brport_flags); diff --git a/include/net/dsa.h b/include/net/dsa.h index e37fee22caab..8af12850337d 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -621,10 +621,8 @@ struct dsa_switch_ops { void (*port_stp_state_set)(struct dsa_switch *ds, int port, u8 state); void (*port_fast_age)(struct dsa_switch *ds, int port); - int (*port_pre_bridge_flags)(struct dsa_switch *ds, int port, - unsigned long mask); int (*port_bridge_flags)(struct dsa_switch *ds, int port, - unsigned long flags); + struct switchdev_brport_flags val); int (*port_set_mrouter)(struct dsa_switch *ds, int port, bool mrouter); diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 88fcac140966..62f16a6bd313 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -20,7 +20,6 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_UNDEFINED, SWITCHDEV_ATTR_ID_PORT_STP_STATE, SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, - SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, @@ -33,6 +32,11 @@ enum switchdev_attr_id { #endif }; +struct switchdev_brport_flags { + unsigned long flags; + unsigned long mask; +}; + struct switchdev_attr { struct net_device *orig_dev; enum switchdev_attr_id id; @@ -41,7 +45,7 @@ struct switchdev_attr { void (*complete)(struct net_device *dev, int err, void *priv); union { u8 stp_state; /* PORT_STP_STATE */ - unsigned long brport_flags; /* PORT_{PRE}_BRIDGE_FLAGS */ + struct switchdev_brport_flags brport_flags; /* PORT_BRIDGE_FLAGS */ bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index c18e1d600dc6..3b460eb225dd 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -65,8 +65,11 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, { struct switchdev_attr attr = { .orig_dev = p->dev, - .id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, - .u.brport_flags = mask, + .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, + .u.brport_flags = { + .flags = flags, + .mask = mask, + }, }; struct switchdev_notifier_port_attr_info info = { .attr = &attr, @@ -78,7 +81,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, /* We run from atomic context here */ err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev, - &info.info, NULL); + &info.info, extack); err = notifier_to_errno(err); if (err == -EOPNOTSUPP) return 0; @@ -88,16 +91,6 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, return -EOPNOTSUPP; } - attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS; - attr.flags = SWITCHDEV_F_DEFER; - attr.u.brport_flags = flags; - - err = switchdev_port_attr_set(p->dev, &attr); - if (err) { - NL_SET_ERR_MSG_MOD(extack, "error setting offload flag on port"); - return err; - } - return 0; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index da99961599de..4fed6b833936 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -174,8 +174,8 @@ int dsa_port_mdb_add(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); int dsa_port_mdb_del(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb); -int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long mask); -int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags); +int dsa_port_bridge_flags(const struct dsa_port *dp, + struct switchdev_brport_flags val); int dsa_port_mrouter(struct dsa_port *dp, bool mrouter); int dsa_port_vlan_add(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan); diff --git a/net/dsa/port.c b/net/dsa/port.c index 8df492412138..fffe5f14ec0a 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -382,24 +382,15 @@ int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock) return 0; } -int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long mask) -{ - struct dsa_switch *ds = dp->ds; - - if (!ds->ops->port_pre_bridge_flags) - return -EINVAL; - - return ds->ops->port_pre_bridge_flags(ds, dp->index, mask); -} - -int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags) +int dsa_port_bridge_flags(const struct dsa_port *dp, + struct switchdev_brport_flags val) { struct dsa_switch *ds = dp->ds; if (!ds->ops->port_bridge_flags) return -EINVAL; - return ds->ops->port_bridge_flags(ds, dp->index, flags); + return ds->ops->port_bridge_flags(ds, dp->index, val); } int dsa_port_mrouter(struct dsa_port *dp, bool mrouter) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 431bdbdd8473..d53c455a73f3 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -289,9 +289,6 @@ static int dsa_slave_port_attr_set(struct net_device *dev, case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME: ret = dsa_port_ageing_time(dp, attr->u.ageing_time); break; - case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS: - ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags); - break; case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: ret = dsa_port_bridge_flags(dp, attr->u.brport_flags); break; From patchwork Sun Feb 7 23:21:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073559 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=unavailable 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 8E8FFC433DB for ; Sun, 7 Feb 2021 23:25:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5E83464E31 for ; Sun, 7 Feb 2021 23:25:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229912AbhBGXZT (ORCPT ); Sun, 7 Feb 2021 18:25:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229772AbhBGXY1 (ORCPT ); Sun, 7 Feb 2021 18:24:27 -0500 Received: from mail-ed1-x533.google.com (mail-ed1-x533.google.com [IPv6:2a00:1450:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D7DACC061793; Sun, 7 Feb 2021 15:23:13 -0800 (PST) Received: by mail-ed1-x533.google.com with SMTP id y8so16087992ede.6; Sun, 07 Feb 2021 15:23:13 -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=y/6NgpsBeErYab+30KbKJBuFft3Z4fcnH7w7GQj4tp0=; b=JbkOPJr04aovGfsmAXPf9CiN9/Koa04BxXUywI8aB5dDQfr4dJo77KZrCeVzJjMzuB 10VWCvRGiRtt5Ya0/9SRRpBtWCUWh+hXxUKwYMsc9BL8ar/HYLGN5k26Yzp33MvvYPmG /iIRu+VDCGYluLfubCnaBoBN73kssBkwKg+8gjZeFPmzH2ZPEPrKD8vB4z+nkc9OwVdA vaH2NKM9NmW5PsSgXP7j1t/3c/hdI6D0s45puXvW4SLb6dUZTiVXZR1eGxTOMi8iFzLF cJF//YxAV9QxDR/DJSU3tBYgFbZn2vS7ErUYyocqt+Ha5qm5X05x0xVBqE1G8x05rsWH aC6Q== 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=y/6NgpsBeErYab+30KbKJBuFft3Z4fcnH7w7GQj4tp0=; b=SoyIyVvD0a6RaViVQCBWa7b5J9AoRKhDNTOPgxGiO4Bj/sNgLPoRJTctItQxH9sded 8kHLDGCSgv/nG/9hmvsa/1Uks14LhJaO2UgZJ7FYIbADOHTamVQwvHrGQD5YSckL6UiD KCZGxTY1QqRfCr5NG5O2RC+zAvnQQ8IHfs6TiR+lej5Ej8gS4NTzcv4G70OAmrcT8vfN dyBRE+ekm3y5ogWyzDA2R5r7UC8IRA3/sF8U7LU8wlFag53w9ClEna8u8UYbcwpe35Io 4vZ4iwLvoCnJhRTT1aaEie7iu++gw0OOpyVGO8vp5K+zaQmgA19DzuaVodXytyrr+PZF zJGQ== X-Gm-Message-State: AOAM531+tB6C/hnd7gr13eOSKt8jENmzAfPmuLXvFfe0trMHGasFBfWD 4CVhH1XJwdevIuInYTVzK90= X-Google-Smtp-Source: ABdhPJz2MW6lRmsPoHfx225bQo9k1cPNmF8qL1rL6nIybLWX5V2DHCTvP5xKbieAUmwKKL1h47UG4Q== X-Received: by 2002:aa7:dc0d:: with SMTP id b13mr14557245edu.170.1612740192587; Sun, 07 Feb 2021 15:23:12 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:12 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 6/9] net: bridge: stop treating EOPNOTSUPP as special in br_switchdev_set_port_flag Date: Mon, 8 Feb 2021 01:21:38 +0200 Message-Id: <20210207232141.2142678-7-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean It is customary to return -EOPNOTSUPP when an operation is not supported. Sometimes the fact that an operation is not supported is irrelevant to upper layers, and in that case the return code is ignored. However, in the case of br_switchdev_set_port_flag, it took it upon itself to treat -EOPNOTSUPP differently and replace it with 0. Due to that, users won't be notified that a switchdev port doesn't support changing a certain bridge port flag (learning, flooding etc). However, no one is returning -EOPNOTSUPP, seemingly as a workaround to the fact that -EOPNOTSUPP will be ignored. So let's stop treating -EOPNOTSUPP special, and just propagate that error, and convert all drivers to use EOPNOTSUPP instead of EINVAL. We already made br_switchdev_set_port_flag stop printing, and we have callers that shouldn't fail already ignore the error code. Signed-off-by: Vladimir Oltean --- .../ethernet/marvell/prestera/prestera_switchdev.c | 2 +- .../net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +- drivers/net/ethernet/rocker/rocker_main.c | 2 +- drivers/net/ethernet/ti/cpsw_switchdev.c | 2 +- drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 2 +- net/bridge/br_switchdev.c | 11 +---------- net/dsa/port.c | 2 +- 7 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c index ab62945c7183..9acd6907454d 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_switchdev.c @@ -587,7 +587,7 @@ static int prestera_port_attr_br_flags_set(struct prestera_port *port, int err; if (val.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) - err = -EINVAL; + err = -EOPNOTSUPP; br_port = prestera_bridge_port_by_dev(port->sw->swdev, dev); if (!br_port) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index f19be04704e7..a2b2dd7bf6b3 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -661,7 +661,7 @@ static int mlxsw_sp_port_attr_br_flags_set(struct mlxsw_sp_port *mlxsw_sp_port, int err; if (val.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD)) - return -EINVAL; + return -EOPNOTSUPP; bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp_port->mlxsw_sp->bridge, orig_dev); diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index b8087dd0b284..e755c9ac8716 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -1591,7 +1591,7 @@ rocker_world_port_attr_bridge_flags_set(struct rocker_port *rocker_port, return err; if (val.mask & ~brport_flags_s) - return -EINVAL; + return -EOPNOTSUPP; return wops->port_attr_bridge_flags_set(rocker_port, val.flags); } diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c index dd4b1e161dde..b47ec2ac5b17 100644 --- a/drivers/net/ethernet/ti/cpsw_switchdev.c +++ b/drivers/net/ethernet/ti/cpsw_switchdev.c @@ -63,7 +63,7 @@ static int cpsw_port_attr_br_flags_set(struct cpsw_priv *priv, bool unreg_mcast_add = false; if (val.mask & ~(BR_LEARNING | BR_MCAST_FLOOD)) - return -EINVAL; + return -EOPNOTSUPP; if (val.flags & BR_MCAST_FLOOD) unreg_mcast_add = true; diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c index c4bcd63b68b8..25ebb127db3c 100644 --- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c +++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c @@ -915,7 +915,7 @@ static int dpaa2_switch_port_attr_br_flags_set(struct net_device *netdev, int err = 0; if (val.mask & ~(BR_LEARNING | BR_FLOOD)) - return -EINVAL; + return -EOPNOTSUPP; /* Learning is enabled per switch */ err = dpaa2_switch_set_learning(port_priv->ethsw_data, diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index 3b460eb225dd..e1774f1b0a44 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -82,16 +82,7 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p, /* We run from atomic context here */ err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev, &info.info, extack); - err = notifier_to_errno(err); - if (err == -EOPNOTSUPP) - return 0; - - if (err) { - NL_SET_ERR_MSG_MOD(extack, "bridge flag offload is not supported"); - return -EOPNOTSUPP; - } - - return 0; + return notifier_to_errno(err); } static void diff --git a/net/dsa/port.c b/net/dsa/port.c index fffe5f14ec0a..26be06ba1461 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -388,7 +388,7 @@ int dsa_port_bridge_flags(const struct dsa_port *dp, struct dsa_switch *ds = dp->ds; if (!ds->ops->port_bridge_flags) - return -EINVAL; + return -EOPNOTSUPP; return ds->ops->port_bridge_flags(ds, dp->index, val); } From patchwork Sun Feb 7 23:21:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073561 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=unavailable 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 53B15C433E0 for ; Sun, 7 Feb 2021 23:25:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2974764E32 for ; Sun, 7 Feb 2021 23:25:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229963AbhBGXZb (ORCPT ); Sun, 7 Feb 2021 18:25:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229774AbhBGXY1 (ORCPT ); Sun, 7 Feb 2021 18:24:27 -0500 Received: from mail-ej1-x62c.google.com (mail-ej1-x62c.google.com [IPv6:2a00:1450:4864:20::62c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9E168C061794; Sun, 7 Feb 2021 15:23:15 -0800 (PST) Received: by mail-ej1-x62c.google.com with SMTP id f14so21814882ejc.8; Sun, 07 Feb 2021 15:23:15 -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=zCy1EvMOOXH22EDc1HyamzeL1z53w13AeBEhwJyUZ3g=; b=c5j/diN8gx4zgCBwE67swYl3o8kHpanpQ7ncIHsLV3r7pplyNhBoRLoe+laZ3L+o3c lGqm7S7lddC8LMo9HwNtmj1ohpiCmcbAeiFh3zBTk/BKvSQqZ9J3nJiv6f9au4Z4Uv12 u4Asyha9Q2k2uRK/yonDDmGRO8/wQlsTpQdbn+7DaZ8Mti/mIlQ2VJLSnRK8K7jo2LAc WL7cN2jJlVu9NKNM5xe1Ot7ZrlsTbHZ1YKJ82vUgk0SlGK+RJL0gVzqp4ntxHZJd+BI3 mW2aglhzFA8yampMpg+tLL9Tjc1TpHkLUNwgjUKT0YMEFO8qUeJvSb4ONEl/Rx/EmnId yNWg== 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=zCy1EvMOOXH22EDc1HyamzeL1z53w13AeBEhwJyUZ3g=; b=qk94OpVQJ3AUnsHvyspq1I6qgfR7odnG24+czJHn9nzbGdpWK38wdj2ejwMPuNNFoR IrwAik0sRg+EfnZ1dK4WmUUdsffFZTvIS8ERIfeW7y3rcRPkUirbTJN3j8wWUqAZePTL Uub1eO7RN2U8BnN+bfCP2+XOi1oPfPmFb2wfcIylFjUTeSPxtciDyNcQOELRQwDCDIfI OZhQAyCfvJ8a//JRXYGX7otDMvGf1nz9Yz9g3zDDXqqHfBY+/f/bUYNX3/3UvkJaBZGl omJhGDZRMjWUcQejZU5VDw5Aw/nMo0kh01CU3QwSHZ/urKpcvQGEdOIS2MSqX0xIvvlq u2Rg== X-Gm-Message-State: AOAM530Wb8apf0EetCFw1PmF97ZeG2UyfpBMXkaz2USpYgNmistbPcPS E0xHxsunpEMkK1Fr8nyJj7c= X-Google-Smtp-Source: ABdhPJwquKnPTKBiRX+xvUdB0FvC7LMA7bWVQGIsqLYHs2piy0t0wfFUtEx4Ivvn63GpGu6/t0mfQA== X-Received: by 2002:a17:906:805:: with SMTP id e5mr14217883ejd.104.1612740194366; Sun, 07 Feb 2021 15:23: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 u21sm7540016ejj.120.2021.02.07.15.23.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:13 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 7/9] net: mscc: ocelot: use separate flooding PGID for broadcast Date: Mon, 8 Feb 2021 01:21:39 +0200 Message-Id: <20210207232141.2142678-8-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean In preparation of offloading the bridge port flags which have independent settings for unknown multicast and for broadcast, we should also start reserving one destination Port Group ID for the flooding of broadcast packets, to allow configuring it individually. Signed-off-by: Vladimir Oltean --- drivers/net/ethernet/mscc/ocelot.c | 13 ++++++++----- include/soc/mscc/ocelot.h | 15 ++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index f8b85ab8be5d..8c1052346b58 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1662,7 +1662,7 @@ int ocelot_init(struct ocelot *ocelot) /* Setup flooding PGIDs */ for (i = 0; i < ocelot->num_flooding_pgids; i++) ocelot_write_rix(ocelot, ANA_FLOODING_FLD_MULTICAST(PGID_MC) | - ANA_FLOODING_FLD_BROADCAST(PGID_MC) | + ANA_FLOODING_FLD_BROADCAST(PGID_BC) | ANA_FLOODING_FLD_UNICAST(PGID_UC), ANA_FLOODING, i); ocelot_write(ocelot, ANA_FLOODING_IPMC_FLD_MC6_DATA(PGID_MCIPV6) | @@ -1683,15 +1683,18 @@ int ocelot_init(struct ocelot *ocelot) ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_SRC + port); } - /* Allow broadcast MAC frames. */ for_each_nonreserved_multicast_dest_pgid(ocelot, i) { u32 val = ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports - 1, 0)); ocelot_write_rix(ocelot, val, ANA_PGID_PGID, i); } - ocelot_write_rix(ocelot, - ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), - ANA_PGID_PGID, PGID_MC); + /* Allow broadcast and unknown L2 multicast to the CPU. */ + ocelot_rmw_rix(ocelot, ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)), + ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)), + ANA_PGID_PGID, PGID_MC); + ocelot_rmw_rix(ocelot, ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)), + ANA_PGID_PGID_PGID(BIT(ocelot->num_phys_ports)), + ANA_PGID_PGID, PGID_BC); ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV4); ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV6); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index d0d48e9620fb..7ee85527cb5f 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -54,16 +54,17 @@ * PGID_CPU: used for whitelisting certain MAC addresses, such as the addresses * of the switch port net devices, towards the CPU port module. * PGID_UC: the flooding destinations for unknown unicast traffic. - * PGID_MC: the flooding destinations for broadcast and non-IP multicast - * traffic. + * PGID_MC: the flooding destinations for non-IP multicast traffic. * PGID_MCIPV4: the flooding destinations for IPv4 multicast traffic. * PGID_MCIPV6: the flooding destinations for IPv6 multicast traffic. + * PGID_BC: the flooding destinations for broadcast traffic. */ -#define PGID_CPU 59 -#define PGID_UC 60 -#define PGID_MC 61 -#define PGID_MCIPV4 62 -#define PGID_MCIPV6 63 +#define PGID_CPU 58 +#define PGID_UC 59 +#define PGID_MC 60 +#define PGID_MCIPV4 61 +#define PGID_MCIPV6 62 +#define PGID_BC 63 #define for_each_unicast_dest_pgid(ocelot, pgid) \ for ((pgid) = 0; \ From patchwork Sun Feb 7 23:21:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073563 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=unavailable 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 6076DC433E0 for ; Sun, 7 Feb 2021 23:26:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2090764E31 for ; Sun, 7 Feb 2021 23:26:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229615AbhBGX0D (ORCPT ); Sun, 7 Feb 2021 18:26:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229581AbhBGXY1 (ORCPT ); Sun, 7 Feb 2021 18:24:27 -0500 Received: from mail-ej1-x62f.google.com (mail-ej1-x62f.google.com [IPv6:2a00:1450:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64780C061797; Sun, 7 Feb 2021 15:23:17 -0800 (PST) Received: by mail-ej1-x62f.google.com with SMTP id f14so21814930ejc.8; Sun, 07 Feb 2021 15:23: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=QRsNxzGQFppccEbDrAzAQZxrCw1vkgxA8/iJ+Ragx3U=; b=m59WEeCxgWWZb/rdO/f3mx2lkNSklmdBwbew55DbrdqSRbxuDmJcsfUNZYcZwmPPDN NGQfiobNiMrnvAdnoI1IagELs1nE7CZrNt4dM1Mfo29L4iiFXY4X7m/jQoBGu2W/DIdt aQqZcXPZl6s1CsL6vhQL3mCbW82C5ubqwM31JjCh6vx8xW2AprcbP21AQ9phdTKmHl1P e+ii2ZThvFtCxM/v4vurD1+geRpLWEHyGnsRiHw94M343YQntw5ZTWTXF1AyieIJPTds wAvV8xaPFSQ/EXx30kk2CmW/J6K+huKiymnW8PUJDs8gFk+fiHAxSKtH96XE/FrBd5FJ Yl8w== 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=QRsNxzGQFppccEbDrAzAQZxrCw1vkgxA8/iJ+Ragx3U=; b=FbnnVXn5Jk4fXUUwgOsdz6NyFm70eJVK7Rmf8LMMMZ888d2mrGDfRh8UM2uTK8Pzx0 B+XDo3Lzp1zHkKuep3sl/uC7shMuS03Sj9Eyw31lfAyFmbWXTMgNWZDIfzC5XDfdReib mxt4nUQpDY5Z0nCByGCtWT+NBOJq02811MZRW4ND/u66W/Iv5LKYRmK9JPysEYTIGzrK XtEVqG15XAOWWjG2okwLU9s4+FZavwqM6H/PtnsHdpMXD8jPy0fmzFw3DbCU8XwxU0l5 ZqpWfhsj5mFZxdNXFVBxmzfAJAynscxxvugYNcTK0RBrd6pDWho5xKO165mTEIa8+LRE LRsA== X-Gm-Message-State: AOAM531oT4OfY5Gg4RbcHW6mTuPFPJWy3Dq3evOdSwXv8N6q1FSScEIn Fo+0M6S/mqsRQZDietYgdBo= X-Google-Smtp-Source: ABdhPJza32f6Qg/JIahyMSXGreUPQT5UkdkPMvCfBX4chge6VcsDk25poKrJdAtDPg9dvvtp5AdNTA== X-Received: by 2002:a17:906:31c1:: with SMTP id f1mr14137180ejf.263.1612740196137; Sun, 07 Feb 2021 15:23:16 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:15 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 8/9] net: mscc: ocelot: offload bridge port flags to device Date: Mon, 8 Feb 2021 01:21:40 +0200 Message-Id: <20210207232141.2142678-9-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean We should not be unconditionally enabling address learning, since doing that is actively detrimential when a port is standalone and not offloading a bridge. Namely, if a port in the switch is standalone and others are offloading the bridge, then we could enter a situation where we learn an address towards the standalone port, but the bridged ports could not forward the packet there, because the CPU is the only path between the standalone and the bridged ports. The solution of course is to not enable address learning unless the bridge asks for it. Signed-off-by: Vladimir Oltean Reviewed-by: Alexandre Belloni --- drivers/net/dsa/ocelot/felix.c | 9 ++++ drivers/net/ethernet/mscc/ocelot.c | 57 +++++++++++++++++++++++++- drivers/net/ethernet/mscc/ocelot_net.c | 4 ++ include/soc/mscc/ocelot.h | 4 ++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 1bd5aea12b25..4d1fef28b6cf 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -553,6 +553,14 @@ static void felix_bridge_stp_state_set(struct dsa_switch *ds, int port, return ocelot_bridge_stp_state_set(ocelot, port, state); } +static int felix_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags val) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_port_bridge_flags(ocelot, port, val); +} + static int felix_bridge_join(struct dsa_switch *ds, int port, struct net_device *br) { @@ -1358,6 +1366,7 @@ const struct dsa_switch_ops felix_switch_ops = { .port_fdb_del = felix_fdb_del, .port_mdb_add = felix_mdb_add, .port_mdb_del = felix_mdb_del, + .port_bridge_flags = felix_bridge_flags, .port_bridge_join = felix_bridge_join, .port_bridge_leave = felix_bridge_leave, .port_lag_join = felix_lag_join, diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 8c1052346b58..c8bfc2f9534a 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -984,6 +984,7 @@ EXPORT_SYMBOL(ocelot_apply_bridge_fwd_mask); void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) { + struct ocelot_port *ocelot_port = ocelot->ports[port]; u32 port_cfg; if (!(BIT(port) & ocelot->bridge_mask)) @@ -996,7 +997,8 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) ocelot->bridge_fwd_mask |= BIT(port); fallthrough; case BR_STATE_LEARNING: - port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA; + if (ocelot_port->brport_flags & BR_LEARNING) + port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA; break; default: @@ -1253,6 +1255,7 @@ EXPORT_SYMBOL(ocelot_port_bridge_join); int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, struct net_device *bridge) { + struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_vlan pvid = {0}, native_vlan = {0}; int ret; @@ -1268,6 +1271,10 @@ int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, ocelot_port_set_pvid(ocelot, port, pvid); ocelot_port_set_native_vlan(ocelot, port, native_vlan); + ocelot_port->brport_flags = 0; + ocelot_rmw_gix(ocelot, 0, ANA_PORT_PORT_CFG_LEARN_ENA, + ANA_PORT_PORT_CFG, port); + return 0; } EXPORT_SYMBOL(ocelot_port_bridge_leave); @@ -1480,6 +1487,54 @@ int ocelot_get_max_mtu(struct ocelot *ocelot, int port) } EXPORT_SYMBOL(ocelot_get_max_mtu); +int ocelot_port_bridge_flags(struct ocelot *ocelot, int port, + struct switchdev_brport_flags val) +{ + struct ocelot_port *ocelot_port = ocelot->ports[port]; + + if (val.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD | BR_LEARNING)) + return -EOPNOTSUPP; + + if (val.mask & BR_LEARNING) { + u32 port_cfg = 0; + + if (val.flags & BR_LEARNING) + port_cfg = ANA_PORT_PORT_CFG_LEARN_ENA; + + ocelot_rmw_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG_LEARN_ENA, + ANA_PORT_PORT_CFG, port); + } + if (val.mask & BR_FLOOD) { + u32 pgid = 0; + + if (val.flags & BR_FLOOD) + pgid = BIT(port); + + ocelot_rmw_rix(ocelot, pgid, BIT(port), ANA_PGID_PGID, PGID_UC); + } + if (val.mask & BR_MCAST_FLOOD) { + u32 pgid = 0; + + if (val.flags & BR_MCAST_FLOOD) + pgid = BIT(port); + + ocelot_rmw_rix(ocelot, pgid, BIT(port), ANA_PGID_PGID, PGID_MC); + } + if (val.mask & BR_BCAST_FLOOD) { + u32 pgid = 0; + + if (val.flags & BR_BCAST_FLOOD) + pgid = BIT(port); + + ocelot_rmw_rix(ocelot, pgid, BIT(port), ANA_PGID_PGID, PGID_BC); + } + + ocelot_port->brport_flags = val.flags; + + return 0; +} +EXPORT_SYMBOL(ocelot_port_bridge_flags); + void ocelot_init_port(struct ocelot *ocelot, int port) { struct ocelot_port *ocelot_port = ocelot->ports[port]; diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 8f12fa45b1b5..e5a07a1d7647 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1025,6 +1025,10 @@ static int ocelot_port_attr_set(struct net_device *dev, case SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED: ocelot_port_attr_mc_set(ocelot, port, !attr->u.mc_disabled); break; + case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS: + err = ocelot_port_bridge_flags(ocelot, port, + attr->u.brport_flags); + break; default: err = -EOPNOTSUPP; break; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 7ee85527cb5f..d8b4b1d3be15 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -597,6 +597,8 @@ struct ocelot_port { struct regmap *target; + unsigned long brport_flags; + bool vlan_aware; /* VLAN that untagged frames are classified to, on ingress */ struct ocelot_vlan pvid_vlan; @@ -764,6 +766,8 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port, int ocelot_port_vlan_filtering(struct ocelot *ocelot, int port, bool enabled); void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state); void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot); +int ocelot_port_bridge_flags(struct ocelot *ocelot, int port, + struct switchdev_brport_flags val); int ocelot_port_bridge_join(struct ocelot *ocelot, int port, struct net_device *bridge); int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, From patchwork Sun Feb 7 23:21:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12073565 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=unavailable 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 AECD3C433DB for ; Sun, 7 Feb 2021 23:26:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7D7CA64DE8 for ; Sun, 7 Feb 2021 23:26:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229972AbhBGX0S (ORCPT ); Sun, 7 Feb 2021 18:26:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46686 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229785AbhBGXY3 (ORCPT ); Sun, 7 Feb 2021 18:24:29 -0500 Received: from mail-ed1-x531.google.com (mail-ed1-x531.google.com [IPv6:2a00:1450:4864:20::531]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 29D4BC0617A9; Sun, 7 Feb 2021 15:23:19 -0800 (PST) Received: by mail-ed1-x531.google.com with SMTP id q2so16116202edi.4; Sun, 07 Feb 2021 15:23:19 -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=sMuPubZ45bqcqp7F8mYy1wbLZt7y2eQbAhZhBI5pduQ=; b=E6IkE+EEEAbE0TKB4FhAcQL0fn5pBQkSvkaQTo99WVLWEKXka6frrJqeOmlHcibsdn XWVJEIkNFXdVUNJhmXJESmEh5zkOij/Hc51cAFOxLXDLA3vr77Zx+9pYcGZ0XE/vtAaH cIcWfRxImTW5gQRljjrEsMqRNCxWOKm/xx+MFtP0J/On7hizsAlpEL819U5Kj/v7p/rz 0kLjGK03xzWh5O0Zt/1A0rSsejT3hNQivdSC9IytGlklNW4ekVkxil4pK//jCsre5evU XhnQs5WnfbRHEHOXVwrWE92kijxc7D7sOj82FbM0v1BZFZN0Kouwp5EwOdKHmXGQrnSd 3nQw== 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=sMuPubZ45bqcqp7F8mYy1wbLZt7y2eQbAhZhBI5pduQ=; b=Q2iipv8P5p3Xs4RLgczb6oqpj+6iUXJ7f2RhSDxW+8ztJgSyexGtgXvdRGhn+xgXOk Wnd8kCG1Tp6TPLemJrGB4jRcOsWtUgblvKhwwKeFcj0+Tnyxi/YxfmlRarU4Fr/exB0v EywaJAlsm/EBB4cOhXAhwM76czH2hLOIpjOgfOxG2E6J2N9mNvbDFXfnMpU2m5Ss6opf qkiElz0MRBDbWKAYLssOYYznupbKk37naHeNs2NG3CZo94VLRFYelRBdiFCq76GzwuOE VjfkvmQhq9YQYAp8G0X/pdoprZgpgGzZpObm6qOahXYu/dZNRQck6WxtC0TMQWzHtWWr oPSA== X-Gm-Message-State: AOAM530nq4h11Q+3ONqCGpx4A/dNmxRIyBvtFHjoo5SMvDXDIM3uyVj+ ERhMRo2HjCu8q64GryqzqXg= X-Google-Smtp-Source: ABdhPJxx8zCBbcCYDSH7IkOVT3WhlPRqi+moQ4NwndkfmHp5byWVOD/6TBrjVf3FAdSJBzDWV15ZXw== X-Received: by 2002:a05:6402:4391:: with SMTP id o17mr14733767edc.196.1612740197806; Sun, 07 Feb 2021 15:23:17 -0800 (PST) Received: from localhost.localdomain (5-12-227-87.residential.rdsnet.ro. [5.12.227.87]) by smtp.gmail.com with ESMTPSA id u21sm7540016ejj.120.2021.02.07.15.23.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Feb 2021 15:23:17 -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 , Ioana Ciornei , Ivan Vecera , linux-omap@vger.kernel.org Subject: [PATCH net-next 9/9] net: mscc: ocelot: support multiple bridges Date: Mon, 8 Feb 2021 01:21:41 +0200 Message-Id: <20210207232141.2142678-10-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210207232141.2142678-1-olteanv@gmail.com> References: <20210207232141.2142678-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 From: Vladimir Oltean The ocelot switches are a bit odd in that they do not have an STP state to put the ports into. Instead, the forwarding configuration is delayed from the typical port_bridge_join into stp_state_set, when the port enters the BR_STATE_FORWARDING state. I can only guess that the implementation of this quirk is the reason that led to the simplification of the driver such that only one bridge could be offloaded at a time. We can simplify the data structures somewhat, and introduce a per-port bridge device pointer and STP state, similar to how the LAG offload works now (there we have a per-port bonding device pointer and TX enabled state). This allows offloading multiple bridges with relative ease, while still keeping in place the quirk to delay the programming of the PGIDs. Signed-off-by: Vladimir Oltean --- drivers/net/ethernet/mscc/ocelot.c | 69 +++++++++++----------- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 2 +- include/soc/mscc/ocelot.h | 7 +-- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index c8bfc2f9534a..6f2967376210 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -912,6 +912,26 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond, return mask; } +static u32 ocelot_get_bridge_fwd_mask(struct ocelot *ocelot, + struct net_device *bridge) +{ + u32 mask = 0; + int port; + + for (port = 0; port < ocelot->num_phys_ports; port++) { + struct ocelot_port *ocelot_port = ocelot->ports[port]; + + if (!ocelot_port) + continue; + + if (ocelot_port->stp_state == BR_STATE_FORWARDING && + ocelot_port->bridge == bridge) + mask |= BIT(port); + } + + return mask; +} + static u32 ocelot_get_dsa_8021q_cpu_mask(struct ocelot *ocelot) { u32 mask = 0; @@ -961,10 +981,12 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot) */ mask = GENMASK(ocelot->num_phys_ports - 1, 0); mask &= ~cpu_fwd_mask; - } else if (ocelot->bridge_fwd_mask & BIT(port)) { + } else if (ocelot_port->bridge) { + struct net_device *bridge = ocelot_port->bridge; struct net_device *bond = ocelot_port->bond; - mask = ocelot->bridge_fwd_mask & ~BIT(port); + mask = ocelot_get_bridge_fwd_mask(ocelot, bridge); + mask &= ~BIT(port); if (bond) { mask &= ~ocelot_get_bond_mask(ocelot, bond, false); @@ -985,29 +1007,16 @@ EXPORT_SYMBOL(ocelot_apply_bridge_fwd_mask); void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) { struct ocelot_port *ocelot_port = ocelot->ports[port]; - u32 port_cfg; - - if (!(BIT(port) & ocelot->bridge_mask)) - return; + u32 learn_ena = 0; - port_cfg = ocelot_read_gix(ocelot, ANA_PORT_PORT_CFG, port); + ocelot_port->stp_state = state; - switch (state) { - case BR_STATE_FORWARDING: - ocelot->bridge_fwd_mask |= BIT(port); - fallthrough; - case BR_STATE_LEARNING: - if (ocelot_port->brport_flags & BR_LEARNING) - port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA; - break; - - default: - port_cfg &= ~ANA_PORT_PORT_CFG_LEARN_ENA; - ocelot->bridge_fwd_mask &= ~BIT(port); - break; - } + if ((state == BR_STATE_LEARNING || state == BR_STATE_FORWARDING) && + ocelot_port->brport_flags & BR_LEARNING) + learn_ena = ANA_PORT_PORT_CFG_LEARN_ENA; - ocelot_write_gix(ocelot, port_cfg, ANA_PORT_PORT_CFG, port); + ocelot_rmw_gix(ocelot, learn_ena, ANA_PORT_PORT_CFG_LEARN_ENA, + ANA_PORT_PORT_CFG, port); ocelot_apply_bridge_fwd_mask(ocelot); } @@ -1237,16 +1246,9 @@ EXPORT_SYMBOL(ocelot_port_mdb_del); int ocelot_port_bridge_join(struct ocelot *ocelot, int port, struct net_device *bridge) { - if (!ocelot->bridge_mask) { - ocelot->hw_bridge_dev = bridge; - } else { - if (ocelot->hw_bridge_dev != bridge) - /* This is adding the port to a second bridge, this is - * unsupported */ - return -ENODEV; - } + struct ocelot_port *ocelot_port = ocelot->ports[port]; - ocelot->bridge_mask |= BIT(port); + ocelot_port->bridge = bridge; return 0; } @@ -1259,10 +1261,7 @@ int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, struct ocelot_vlan pvid = {0}, native_vlan = {0}; int ret; - ocelot->bridge_mask &= ~BIT(port); - - if (!ocelot->bridge_mask) - ocelot->hw_bridge_dev = NULL; + ocelot_port->bridge = NULL; ret = ocelot_port_vlan_filtering(ocelot, port, false); if (ret) diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 6b6eb92149ba..c366d96fc945 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -694,7 +694,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg) /* Everything we see on an interface that is in the HW bridge * has already been forwarded. */ - if (ocelot->bridge_mask & BIT(info.port)) + if (ocelot_port->bridge) skb->offload_fwd_mark = 1; skb->protocol = eth_type_trans(skb, dev); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index d8b4b1d3be15..333300b14a97 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -617,6 +617,9 @@ struct ocelot_port { struct net_device *bond; bool lag_tx_active; + + struct net_device *bridge; + u8 stp_state; }; struct ocelot { @@ -636,10 +639,6 @@ struct ocelot { int num_frame_refs; int num_mact_rows; - struct net_device *hw_bridge_dev; - u16 bridge_mask; - u16 bridge_fwd_mask; - struct ocelot_port **ports; u8 base_mac[ETH_ALEN];