From patchwork Mon Mar 22 23:51:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406471 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.7 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, URIBL_BLOCKED, 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 92A41C433E4 for ; Mon, 22 Mar 2021 23:52:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6F0C2619A5 for ; Mon, 22 Mar 2021 23:52:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230481AbhCVXwT (ORCPT ); Mon, 22 Mar 2021 19:52:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230437AbhCVXwE (ORCPT ); Mon, 22 Mar 2021 19:52:04 -0400 Received: from mail-ej1-x633.google.com (mail-ej1-x633.google.com [IPv6:2a00:1450:4864:20::633]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B29AAC061574; Mon, 22 Mar 2021 16:52:03 -0700 (PDT) Received: by mail-ej1-x633.google.com with SMTP id e14so5901145ejz.11; Mon, 22 Mar 2021 16:52:03 -0700 (PDT) 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=L7PBrxdFzG5KWaT2YGxWxyTgtqiT9AsP2MOM/CZw2Kc=; b=EcBL83arcK1GO3xEPgn7I5IcApcX1+zfJrZtvAwiaucbwBijf1UThCuuO3PQnDYlh9 It0BlO6djDlSt8f1ygvtm/PboT4K1lgZwd70E4PPiH9zF7PM0Qy1FX/Eg7AEm0loVlRX JpyTBLGunH1SrFrEEfjCUzVlr46tC4XPswgaB7eqhz2aOb6X3WjJSDdyZ2egTNwyCIAB WY9kyrZcc7/0gdwMGuJ7IEVQ7F5cuCUergEJJnr5c4iKKvE8y/W7B0m6lt2pKd1PGgpp mn+eb/ti1iO/ElOm853UoeR50sx7kVKokeCS1Em+usd/bWSYU4Ib+WMWmIlxMrafF7kk wxgA== 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=L7PBrxdFzG5KWaT2YGxWxyTgtqiT9AsP2MOM/CZw2Kc=; b=k3MxisBT3cH5S1Q0pa6rjhfeq5EMcsyNEBS8Zjic3Nwop5eFcf74QlT7//PYmpFmZu UxRKIBaLXSeaS1pIFLBc6s1fIZ4nZCntfYJ/+sDWZ72XXgFVcwCzpctctxfCBMR6MPmV UEBF9PIHQiEK7oNRB3SOkCXdd0N1rlylQHzN/McdsDK8m34O2od2Y/XOc6jzep2Pq4vx YgNiFM6n4nAhjQaHyOV1JLu/y8kbg8uTNro8vYdMCyxS/rA0PfvoxClSsMP+EeKqzh6O mjmnVRHz7RixD4bgxuNMyZeEaiC39lpLra0I96N8dhOS5hJrxQ6f1D2+dxalT+4E6S5G ZMcQ== X-Gm-Message-State: AOAM532OL330XgCTINil+/F34335eb3aOAVFPR7SClXh5OFwDRVPbefq uxsPlBJqRvl46AAQMND+D4w= X-Google-Smtp-Source: ABdhPJw0/mDX5Q8Eq8XYR6523kJWaNX2nu8y9A5/IX+NRS+RsqYIpTXbF1tayuBjWULEA9Fh1brN4Q== X-Received: by 2002:a17:906:fcc7:: with SMTP id qx7mr2170563ejb.486.1616457122482; Mon, 22 Mar 2021 16:52:02 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:02 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 01/11] net: bridge: add helper for retrieving the current bridge port STP state Date: Tue, 23 Mar 2021 01:51:42 +0200 Message-Id: <20210322235152.268695-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean It may happen that we have the following topology with DSA or any other switchdev driver with LAG offload: ip link add br0 type bridge stp_state 1 ip link add bond0 type bond ip link set bond0 master br0 ip link set swp0 master bond0 ip link set swp1 master bond0 STP decides that it should put bond0 into the BLOCKING state, and that's that. The ports that are actively listening for the switchdev port attributes emitted for the bond0 bridge port (because they are offloading it) and have the honor of seeing that switchdev port attribute can react to it, so we can program swp0 and swp1 into the BLOCKING state. But if then we do: ip link set swp2 master bond0 then as far as the bridge is concerned, nothing has changed: it still has one bridge port. But this new bridge port will not see any STP state change notification and will remain FORWARDING, which is how the standalone code leaves it in. We need a function in the bridge driver which retrieves the current STP state, such that drivers can synchronize to it when they may have missed switchdev events. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Reviewed-by: Tobias Waldekranz Acked-by: Nikolay Aleksandrov --- include/linux/if_bridge.h | 6 ++++++ net/bridge/br_stp.c | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index b979005ea39c..920d3a02cc68 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -136,6 +136,7 @@ struct net_device *br_fdb_find_port(const struct net_device *br_dev, __u16 vid); void br_fdb_clear_offload(const struct net_device *dev, u16 vid); bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag); +u8 br_port_get_stp_state(const struct net_device *dev); #else static inline struct net_device * br_fdb_find_port(const struct net_device *br_dev, @@ -154,6 +155,11 @@ br_port_flag_is_set(const struct net_device *dev, unsigned long flag) { return false; } + +static inline u8 br_port_get_stp_state(const struct net_device *dev) +{ + return BR_STATE_DISABLED; +} #endif #endif diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 21c6781906aa..86b5e05d3f21 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -64,6 +64,20 @@ void br_set_state(struct net_bridge_port *p, unsigned int state) } } +u8 br_port_get_stp_state(const struct net_device *dev) +{ + struct net_bridge_port *p; + + ASSERT_RTNL(); + + p = br_port_get_rtnl(dev); + if (!p) + return BR_STATE_DISABLED; + + return p->state; +} +EXPORT_SYMBOL_GPL(br_port_get_stp_state); + /* called under bridge lock */ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no) { From patchwork Mon Mar 22 23:51:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 407449 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.7 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, URIBL_BLOCKED, 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 2979DC433EB for ; Mon, 22 Mar 2021 23:52:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0EE63619A4 for ; Mon, 22 Mar 2021 23:52:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230504AbhCVXwU (ORCPT ); Mon, 22 Mar 2021 19:52:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57614 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230295AbhCVXwF (ORCPT ); Mon, 22 Mar 2021 19:52:05 -0400 Received: from mail-ej1-x629.google.com (mail-ej1-x629.google.com [IPv6:2a00:1450:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE077C061574; Mon, 22 Mar 2021 16:52:04 -0700 (PDT) Received: by mail-ej1-x629.google.com with SMTP id jy13so24098737ejc.2; Mon, 22 Mar 2021 16:52:04 -0700 (PDT) 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=M9VtCMHjMqidFWejIfAw/dLhfjAfoFArbamAgjqVgRk=; b=m3UolH3ty2cUCEdnj1dEmGcRrOwe/EqNyV8MzCbuacAJ20aUSCVJFqOd3FRkM2wYed weGqi4atZ7ZemcwKoFSBpUdAu1p17VsW4w7KIvlzENsZNOdmMuJlrw3rtF490vbk4HBL mojg4z98weoMRSnL9VfxSUdReyeIR1YETtPUPV9YkmqhhbGGqRyVbFdzy+0nsjVZ7NQc zAPZkxD2Hl1sRdbsptHqNUKLKuK4QN7sXcNeJze4DTLrRK0mumNt5yEheA/4bIDmdMau bSUBVopxW1wBwMWCRB05Cr6oT0pyr9uecKsKUjeK2CorgvHb+lDDr/89QoX7aEs61T2x rXvw== 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=M9VtCMHjMqidFWejIfAw/dLhfjAfoFArbamAgjqVgRk=; b=mAYtlNT87R6zp6GbZJ/usS/X+uDPIlw+3uOCPjzy9hP7CP3+cyTuxWb88XimyYk6Uv BdEUchmpunSEAn4wjrRP3i4ucV9b5WrarKVa8vZEuylIVXy10tsNnFLgxy1Oy2gWZLMA RcPpOwRTHwvDmX6z/s/SoyfspVMO7gXgDxA+K8NzdnwBKL6FbUfZiFyNyxJN6LHctzE7 GwuK2CMFuffxSpo/y4L2xlo89rS7cFM/RnKYEjFVf6LPMk/jXGf2uyfF+RkcnvPhST0N 72xjmDVAgJkEDJnYslEobUWmOyo8tSoftQ4NhYb1Y1UhGh/S/as+EKUBsc2y7rpuPfaJ CFcQ== X-Gm-Message-State: AOAM53198jpMhBCGACXbRBLNbyFwMmFy7pjAKFw4Ep6/WMoK+OB4L9X2 IawDqQER0OxkghyBX47CZvo= X-Google-Smtp-Source: ABdhPJzP7L0v60H16t3CsrXuPrni7YlMX3LqeuPibQaDWYuBwG14+H1uBhPAdImeVpubykwEBzznpg== X-Received: by 2002:a17:906:489:: with SMTP id f9mr2106844eja.428.1616457123736; Mon, 22 Mar 2021 16:52:03 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:03 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 02/11] net: bridge: add helper to retrieve the current ageing time Date: Tue, 23 Mar 2021 01:51:43 +0200 Message-Id: <20210322235152.268695-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean The SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME attribute is only emitted from: sysfs/ioctl/netlink -> br_set_ageing_time -> __set_ageing_time therefore not at bridge port creation time, so: (a) switchdev drivers have to hardcode the initial value for the address ageing time, because they didn't get any notification (b) that hardcoded value can be out of sync, if the user changes the ageing time before enslaving the port to the bridge We need a helper in the bridge, such that switchdev drivers can query the current value of the bridge ageing time when they start offloading it. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Reviewed-by: Tobias Waldekranz --- include/linux/if_bridge.h | 6 ++++++ net/bridge/br_stp.c | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 920d3a02cc68..ebd16495459c 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -137,6 +137,7 @@ struct net_device *br_fdb_find_port(const struct net_device *br_dev, void br_fdb_clear_offload(const struct net_device *dev, u16 vid); bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag); u8 br_port_get_stp_state(const struct net_device *dev); +clock_t br_get_ageing_time(struct net_device *br_dev); #else static inline struct net_device * br_fdb_find_port(const struct net_device *br_dev, @@ -160,6 +161,11 @@ static inline u8 br_port_get_stp_state(const struct net_device *dev) { return BR_STATE_DISABLED; } + +static inline clock_t br_get_ageing_time(struct net_device *br_dev) +{ + return 0; +} #endif #endif diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 86b5e05d3f21..3dafb6143cff 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -639,6 +639,19 @@ int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time) return 0; } +clock_t br_get_ageing_time(struct net_device *br_dev) +{ + struct net_bridge *br; + + if (!netif_is_bridge_master(br_dev)) + return 0; + + br = netdev_priv(br_dev); + + return jiffies_to_clock_t(br->ageing_time); +} +EXPORT_SYMBOL_GPL(br_get_ageing_time); + /* called under bridge lock */ void __br_set_topology_change(struct net_bridge *br, unsigned char val) { From patchwork Mon Mar 22 23:51:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406470 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.7 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, URIBL_BLOCKED, 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 0B46AC433EA for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E3A02619A5 for ; Mon, 22 Mar 2021 23:52:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231144AbhCVXwW (ORCPT ); Mon, 22 Mar 2021 19:52:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230439AbhCVXwH (ORCPT ); Mon, 22 Mar 2021 19:52:07 -0400 Received: from mail-ej1-x629.google.com (mail-ej1-x629.google.com [IPv6:2a00:1450:4864:20::629]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 516BDC061756; Mon, 22 Mar 2021 16:52:06 -0700 (PDT) Received: by mail-ej1-x629.google.com with SMTP id hq27so24111706ejc.9; Mon, 22 Mar 2021 16:52:06 -0700 (PDT) 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=BNvDq+x5CxEA4hEvtyw+m92SUzw5QJRpJT5L5Ues/LY=; b=Yw6J3YU91PE3S7nRGRtFPukroEe3a29Qwcg1bbbRodpIsgpsrshXdOBtQPviUOcDWW ivKTXsdAueqsPEWF+ghn6RQbvlMoWooZQgMjUpZ6VtJgKNd3tMeJAykemZ//kPZc2jZA 1QXB+e21mGR3pFlJgsmCnERytFrJlho8P61D+GMS1NqN5j888G8DmChmIbHaoJ4FQEep UtCkMyi1y3CkmfN+Qb/SLGsY29Yx6e4bfMFBy5JbBb9FjiAZvxa0fS9EC0FyLTOKKzjJ JR39FpYTmAUZslY2psg+K+ubdV/qJ+UGWh8DI3X8Adby4zsLgCxtwC5XNKYoOcN9c5UX 8Ljw== 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=BNvDq+x5CxEA4hEvtyw+m92SUzw5QJRpJT5L5Ues/LY=; b=B719mdj1ztbt7h5Izg3Re5kUZRaF0wi8PDOphuIVvaNl8gApD2d/BOieHCLHD91yqq MniqxiWD/CgDlTlwdQ369gJBy0QJCzmuNJAAytplp9jgItGjUjd7yOi687Sa9ajyithG c+cjRVKA6QQ5SjkT43oUWjUR+vSx3DZqK29RHBeLNnS776shTczzjT+kVTJO2F3JhlQy hbNoVlvZmhG9UhPmnCpnfn4hUtk5+JjFim+eZfXqFhpVl++JRJvyVu95kCxrA3JyIs6b IVO4Ux4f4bLIHIn9oeyCE74p1TlUNQzo6+z7BaThLVmANn+mpPrgB2cxlwC0gF+Zz1gt IgKA== X-Gm-Message-State: AOAM530fFAUougrtaqlS63C7siHQoqDAoyiNM2T16ukH1VkBmSX6tseV gb7aJfBNqtiOfam6CkfyKn0= X-Google-Smtp-Source: ABdhPJwe1lKNo4oFMnfLTrr2BoV1MCJEZMkuqJrV57E2eGPk3w7Su+AjGvYLL+OIyzI0CR0FXpCzHA== X-Received: by 2002:a17:906:5e01:: with SMTP id n1mr2123334eju.359.1616457125062; Mon, 22 Mar 2021 16:52:05 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:04 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 03/11] net: bridge: add helper to replay port and host-joined mdb entries Date: Tue, 23 Mar 2021 01:51:44 +0200 Message-Id: <20210322235152.268695-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean I have a system with DSA ports, and udhcpcd is configured to bring interfaces up as soon as they are created. I create a bridge as follows: ip link add br0 type bridge As soon as I create the bridge and udhcpcd brings it up, I also have avahi which automatically starts sending IPv6 packets to advertise some local services, and because of that, the br0 bridge joins the following IPv6 groups due to the code path detailed below: 33:33:ff:6d:c1:9c vid 0 33:33:00:00:00:6a vid 0 33:33:00:00:00:fb vid 0 br_dev_xmit -> br_multicast_rcv -> br_ip6_multicast_add_group -> __br_multicast_add_group -> br_multicast_host_join -> br_mdb_notify This is all fine, but inside br_mdb_notify we have br_mdb_switchdev_host hooked up, and switchdev will attempt to offload the host joined groups to an empty list of ports. Of course nobody offloads them. Then when we add a port to br0: ip link set swp0 master br0 the bridge doesn't replay the host-joined MDB entries from br_add_if, and eventually the host joined addresses expire, and a switchdev notification for deleting it is emitted, but surprise, the original addition was already completely missed. The strategy to address this problem is to replay the MDB entries (both the port ones and the host joined ones) when the new port joins the bridge, similar to what vxlan_fdb_replay does (in that case, its FDB can be populated and only then attached to a bridge that you offload). However there are 2 possibilities: the addresses can be 'pushed' by the bridge into the port, or the port can 'pull' them from the bridge. Considering that in the general case, the new port can be really late to the party, and there may have been many other switchdev ports that already received the initial notification, we would like to avoid delivering duplicate events to them, since they might misbehave. And currently, the bridge calls the entire switchdev notifier chain, whereas for replaying it should just call the notifier block of the new guy. But the bridge doesn't know what is the new guy's notifier block, it just knows where the switchdev notifier chain is. So for simplification, we make this a driver-initiated pull for now, and the notifier block is passed as an argument. To emulate the calling context for mdb objects (deferred and put on the blocking notifier chain), we must iterate under RCU protection through the bridge's mdb entries, queue them, and only call them once we're out of the RCU read-side critical section. There was some opportunity for reuse between br_mdb_switchdev_host_port, br_mdb_notify and the newly added br_mdb_queue_one in how the switchdev mdb object is created, so a helper was created. Suggested-by: Ido Schimmel Signed-off-by: Vladimir Oltean Acked-by: Nikolay Aleksandrov --- include/linux/if_bridge.h | 9 +++ include/net/switchdev.h | 1 + net/bridge/br_mdb.c | 148 +++++++++++++++++++++++++++++++++----- 3 files changed, 141 insertions(+), 17 deletions(-) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index ebd16495459c..f6472969bb44 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -69,6 +69,8 @@ bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto); bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto); bool br_multicast_enabled(const struct net_device *dev); bool br_multicast_router(const struct net_device *dev); +int br_mdb_replay(struct net_device *br_dev, struct net_device *dev, + struct notifier_block *nb, struct netlink_ext_ack *extack); #else static inline int br_multicast_list_adjacent(struct net_device *dev, struct list_head *br_ip_list) @@ -93,6 +95,13 @@ static inline bool br_multicast_router(const struct net_device *dev) { return false; } +static inline int br_mdb_replay(struct net_device *br_dev, + struct net_device *dev, + struct notifier_block *nb, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} #endif #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index b7fc7d0f54e2..8c3218177136 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -68,6 +68,7 @@ enum switchdev_obj_id { }; struct switchdev_obj { + struct list_head list; struct net_device *orig_dev; enum switchdev_obj_id id; u32 flags; diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 8846c5bcd075..95fa4af0e8dd 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -506,6 +506,134 @@ static void br_mdb_complete(struct net_device *dev, int err, void *priv) kfree(priv); } +static void br_switchdev_mdb_populate(struct switchdev_obj_port_mdb *mdb, + const struct net_bridge_mdb_entry *mp) +{ + if (mp->addr.proto == htons(ETH_P_IP)) + ip_eth_mc_map(mp->addr.dst.ip4, mdb->addr); +#if IS_ENABLED(CONFIG_IPV6) + else if (mp->addr.proto == htons(ETH_P_IPV6)) + ipv6_eth_mc_map(&mp->addr.dst.ip6, mdb->addr); +#endif + else + ether_addr_copy(mdb->addr, mp->addr.dst.mac_addr); + + mdb->vid = mp->addr.vid; +} + +static int br_mdb_replay_one(struct notifier_block *nb, struct net_device *dev, + struct switchdev_obj_port_mdb *mdb, + struct netlink_ext_ack *extack) +{ + struct switchdev_notifier_port_obj_info obj_info = { + .info = { + .dev = dev, + .extack = extack, + }, + .obj = &mdb->obj, + }; + int err; + + err = nb->notifier_call(nb, SWITCHDEV_PORT_OBJ_ADD, &obj_info); + return notifier_to_errno(err); +} + +static int br_mdb_queue_one(struct list_head *mdb_list, + enum switchdev_obj_id id, + const struct net_bridge_mdb_entry *mp, + struct net_device *orig_dev) +{ + struct switchdev_obj_port_mdb *mdb; + + mdb = kzalloc(sizeof(*mdb), GFP_ATOMIC); + if (!mdb) + return -ENOMEM; + + mdb->obj.id = id; + mdb->obj.orig_dev = orig_dev; + br_switchdev_mdb_populate(mdb, mp); + list_add_tail(&mdb->obj.list, mdb_list); + + return 0; +} + +int br_mdb_replay(struct net_device *br_dev, struct net_device *dev, + struct notifier_block *nb, struct netlink_ext_ack *extack) +{ + struct net_bridge_mdb_entry *mp; + struct switchdev_obj *obj, *tmp; + struct net_bridge *br; + LIST_HEAD(mdb_list); + int err = 0; + + ASSERT_RTNL(); + + if (!netif_is_bridge_master(br_dev) || !netif_is_bridge_port(dev)) + return -EINVAL; + + br = netdev_priv(br_dev); + + if (!br_opt_get(br, BROPT_MULTICAST_ENABLED)) + return 0; + + /* We cannot walk over br->mdb_list protected just by the rtnl_mutex, + * because the write-side protection is br->multicast_lock. But we + * need to emulate the [ blocking ] calling context of a regular + * switchdev event, so since both br->multicast_lock and RCU read side + * critical sections are atomic, we have no choice but to pick the RCU + * read side lock, queue up all our events, leave the critical section + * and notify switchdev from blocking context. + */ + rcu_read_lock(); + + hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) { + struct net_bridge_port_group __rcu **pp; + struct net_bridge_port_group *p; + + if (mp->host_joined) { + err = br_mdb_queue_one(&mdb_list, + SWITCHDEV_OBJ_ID_HOST_MDB, + mp, br_dev); + if (err) { + rcu_read_unlock(); + goto out_free_mdb; + } + } + + for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL; + pp = &p->next) { + if (p->key.port->dev != dev) + continue; + + err = br_mdb_queue_one(&mdb_list, + SWITCHDEV_OBJ_ID_PORT_MDB, + mp, dev); + if (err) { + rcu_read_unlock(); + goto out_free_mdb; + } + } + } + + rcu_read_unlock(); + + list_for_each_entry(obj, &mdb_list, list) { + err = br_mdb_replay_one(nb, dev, SWITCHDEV_OBJ_PORT_MDB(obj), + extack); + if (err) + goto out_free_mdb; + } + +out_free_mdb: + list_for_each_entry_safe(obj, tmp, &mdb_list, list) { + list_del(&obj->list); + kfree(SWITCHDEV_OBJ_PORT_MDB(obj)); + } + + return err; +} +EXPORT_SYMBOL_GPL(br_mdb_replay); + static void br_mdb_switchdev_host_port(struct net_device *dev, struct net_device *lower_dev, struct net_bridge_mdb_entry *mp, @@ -515,18 +643,12 @@ static void br_mdb_switchdev_host_port(struct net_device *dev, .obj = { .id = SWITCHDEV_OBJ_ID_HOST_MDB, .flags = SWITCHDEV_F_DEFER, + .orig_dev = dev, }, - .vid = mp->addr.vid, }; - if (mp->addr.proto == htons(ETH_P_IP)) - ip_eth_mc_map(mp->addr.dst.ip4, mdb.addr); -#if IS_ENABLED(CONFIG_IPV6) - else - ipv6_eth_mc_map(&mp->addr.dst.ip6, mdb.addr); -#endif + br_switchdev_mdb_populate(&mdb, mp); - mdb.obj.orig_dev = dev; switch (type) { case RTM_NEWMDB: switchdev_port_obj_add(lower_dev, &mdb.obj, NULL); @@ -558,21 +680,13 @@ void br_mdb_notify(struct net_device *dev, .id = SWITCHDEV_OBJ_ID_PORT_MDB, .flags = SWITCHDEV_F_DEFER, }, - .vid = mp->addr.vid, }; struct net *net = dev_net(dev); struct sk_buff *skb; int err = -ENOBUFS; if (pg) { - if (mp->addr.proto == htons(ETH_P_IP)) - ip_eth_mc_map(mp->addr.dst.ip4, mdb.addr); -#if IS_ENABLED(CONFIG_IPV6) - else if (mp->addr.proto == htons(ETH_P_IPV6)) - ipv6_eth_mc_map(&mp->addr.dst.ip6, mdb.addr); -#endif - else - ether_addr_copy(mdb.addr, mp->addr.dst.mac_addr); + br_switchdev_mdb_populate(&mdb, mp); mdb.obj.orig_dev = pg->key.port->dev; switch (type) { From patchwork Mon Mar 22 23:51:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406469 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.7 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, URIBL_BLOCKED, 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 F2C40C433ED for ; Mon, 22 Mar 2021 23:52:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CDD30619A9 for ; Mon, 22 Mar 2021 23:52:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230523AbhCVXwV (ORCPT ); Mon, 22 Mar 2021 19:52:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230267AbhCVXwI (ORCPT ); Mon, 22 Mar 2021 19:52:08 -0400 Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C82DC061574; Mon, 22 Mar 2021 16:52:07 -0700 (PDT) Received: by mail-ej1-x62d.google.com with SMTP id hq27so24111759ejc.9; Mon, 22 Mar 2021 16:52:07 -0700 (PDT) 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=PqzMdjhV83LXsXb2kivK1TtVxn6ToXVfM5lC7LerSCY=; b=V36fTkVTj174Ff6kbcd4RUHIGnsQ2X68qQgURWhEBIEJhIo8aTBgyYG9tH7NnV8/Hr 3AeWQf4OWxqURjcx4j0zKlKNs7aWrGEfio5ikbWk/uYUbXNBxfGY3KR/LYRtpGGq2bEL YAj79ITkwnUuAqfFL1d7PcCrSXzyZpth87K7HLwOwW4qBCWDyggfuE7KwvQ2scgFomUU zFZLsdeW4XTzQEtuKf2kdY+ENWVSmqby5Gq6fA3YYDwLu+h9js3xjIqwqwlsriWoTYp3 27b8M4Onsy862soxmV6nIBLNJ/RbAoCa6yzrm2bFoRFCKU9RD0yAvDTn6PwMBjRf8BZ1 nnQA== 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=PqzMdjhV83LXsXb2kivK1TtVxn6ToXVfM5lC7LerSCY=; b=KBtAkYcsNl3WbNcw4zIwNbAO3G0hAv7j9O5fxptRtDSF9VAFMKT95fNriZQ22NmJFe UCOGgZl7VdxPAQFmNOp2VmNl1Baq4HftYW/vluGy5qRRbDDzaS3nZdssrN3aAW2APkL2 Z9Pq0pzJ0yU6RjY3dB/rv7MAVH9hnskXRYbkzqVTANb8Vz3r+Z/TxK9kJYegbXqyKKVp c3LxodhViQdq0escGxqjrcN+BvR5ffNA97qzthbSbCkSZ7YlK4iKlNoj0eKQSgh85Ryz 1BakKDZcMrbbQXE+WLoAMkpOOJsYIt5D7Ka3cah0OX9wT10Rty3Rbo9b3eQwbRbzMa84 ObiQ== X-Gm-Message-State: AOAM530m/duoYafm7G7z83PpRpwIvw44fayFPCn/0ZzMVKjggejkyIDd es2V7vDEIHDSpGiLPHsvOh41RCCpn0Q= X-Google-Smtp-Source: ABdhPJz7Dys6eSoQpDlOu4Yb2/lmja+Qf5fwPq6I/O2bYqdJ0ipLa4hBcw2catE+XOqHs/Gt0uvROA== X-Received: by 2002:a17:906:1453:: with SMTP id q19mr2220820ejc.76.1616457126334; Mon, 22 Mar 2021 16:52:06 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:06 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 04/11] net: bridge: add helper to replay port and local fdb entries Date: Tue, 23 Mar 2021 01:51:45 +0200 Message-Id: <20210322235152.268695-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean When a switchdev port starts offloading a LAG that is already in a bridge and has an FDB entry pointing to it: ip link set bond0 master br0 bridge fdb add dev bond0 00:01:02:03:04:05 master static ip link set swp0 master bond0 the switchdev driver will have no idea that this FDB entry is there, because it missed the switchdev event emitted at its creation. Ido Schimmel pointed this out during a discussion about challenges with switchdev offloading of stacked interfaces between the physical port and the bridge, and recommended to just catch that condition and deny the CHANGEUPPER event: https://lore.kernel.org/netdev/20210210105949.GB287766@shredder.lan/ But in fact, we might need to deal with the hard thing anyway, which is to replay all FDB addresses relevant to this port, because it isn't just static FDB entries, but also local addresses (ones that are not forwarded but terminated by the bridge). There, we can't just say 'oh yeah, there was an upper already so I'm not joining that'. So, similar to the logic for replaying MDB entries, add a function that must be called by individual switchdev drivers and replays local FDB entries as well as ones pointing towards a bridge port. This time, we use the atomic switchdev notifier block, since that's what FDB entries expect for some reason. Reported-by: Ido Schimmel Signed-off-by: Vladimir Oltean Acked-by: Nikolay Aleksandrov --- include/linux/if_bridge.h | 9 +++++++ net/bridge/br_fdb.c | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index f6472969bb44..b564c4486a45 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -147,6 +147,8 @@ void br_fdb_clear_offload(const struct net_device *dev, u16 vid); bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag); u8 br_port_get_stp_state(const struct net_device *dev); clock_t br_get_ageing_time(struct net_device *br_dev); +int br_fdb_replay(struct net_device *br_dev, struct net_device *dev, + struct notifier_block *nb); #else static inline struct net_device * br_fdb_find_port(const struct net_device *br_dev, @@ -175,6 +177,13 @@ static inline clock_t br_get_ageing_time(struct net_device *br_dev) { return 0; } + +static inline int br_fdb_replay(struct net_device *br_dev, + struct net_device *dev, + struct notifier_block *nb) +{ + return -EOPNOTSUPP; +} #endif #endif diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b7490237f3fc..698b79747d32 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -726,6 +726,56 @@ static inline size_t fdb_nlmsg_size(void) + nla_total_size(sizeof(u8)); /* NFEA_ACTIVITY_NOTIFY */ } +static int br_fdb_replay_one(struct notifier_block *nb, + struct net_bridge_fdb_entry *fdb, + struct net_device *dev) +{ + struct switchdev_notifier_fdb_info item; + int err; + + item.addr = fdb->key.addr.addr; + item.vid = fdb->key.vlan_id; + item.added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags); + item.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags); + item.info.dev = dev; + + err = nb->notifier_call(nb, SWITCHDEV_FDB_ADD_TO_DEVICE, &item); + return notifier_to_errno(err); +} + +int br_fdb_replay(struct net_device *br_dev, struct net_device *dev, + struct notifier_block *nb) +{ + struct net_bridge_fdb_entry *fdb; + struct net_bridge *br; + int err = 0; + + if (!netif_is_bridge_master(br_dev) || !netif_is_bridge_port(dev)) + return -EINVAL; + + br = netdev_priv(br_dev); + + rcu_read_lock(); + + hlist_for_each_entry_rcu(fdb, &br->fdb_list, fdb_node) { + struct net_bridge_port *dst = READ_ONCE(fdb->dst); + struct net_device *dst_dev; + + dst_dev = dst ? dst->dev : br->dev; + if (dst_dev != br_dev && dst_dev != dev) + continue; + + err = br_fdb_replay_one(nb, fdb, dst_dev); + if (err) + break; + } + + rcu_read_unlock(); + + return err; +} +EXPORT_SYMBOL_GPL(br_fdb_replay); + static void fdb_notify(struct net_bridge *br, const struct net_bridge_fdb_entry *fdb, int type, bool swdev_notify) From patchwork Mon Mar 22 23:51:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406468 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.7 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, URIBL_BLOCKED, 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 94757C433F2 for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 40F05619A9 for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231161AbhCVXwY (ORCPT ); Mon, 22 Mar 2021 19:52:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230440AbhCVXwJ (ORCPT ); Mon, 22 Mar 2021 19:52:09 -0400 Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E7E2C061756; Mon, 22 Mar 2021 16:52:09 -0700 (PDT) Received: by mail-ej1-x62d.google.com with SMTP id r12so24120800ejr.5; Mon, 22 Mar 2021 16:52:09 -0700 (PDT) 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=44nKq5GK8p1avKVpGd20iBhUXg7GP0c0cb6BGtUh5kw=; b=qa4xklvrmnrJV2Ttk9lrGnxmR7Yh2KtWJkfU4bihrCEwT9m//ROhgo0ZEaIwYaa4WW E4eYHOcpdKLA56kWXUcRpNT2KGB6/ZO0/+DHGSRGAdgK5vInfsaGB+NMtiB3h3QLwdVh vo/nQB23DH8y2ogK8l2zvup71PUQmsXxmHZTRmQOkDSo0AwrZVJ7z8OC/kfU3YE89NeL VuNP6yp11GTTSvAVZvRNpq1FQETH8AJstjDfRdY3737j+UbIrDHJdJk4X1QDrmsADgCJ RbdVACDDP1rNgA3e2ITgVCtMuExRlmQDysWXIe8bL+9oqEh2GQs0rkgn/i81fHoJIX6J m3fw== 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=44nKq5GK8p1avKVpGd20iBhUXg7GP0c0cb6BGtUh5kw=; b=NNGQxSwKrohD4wQ93xxRdG0MoV6DTzJY6cmuXlCZJ4ersCFDLOM+7dS/kcr7bFElWB GfzA9WyFzgMMmcEqRTwA0Heg9lGf3EgfP78k2zCRELeIgaKiNuhCRqcqwgsKMdrmKq5V kbYkLPgcxUoHjr5KJI/zRE1glqiVajbvUr6w7SaCeB/ABNh5RFbeDIQElKkgEH7snf2U 857MqrFZPygcCFpsSLB76w6cXC0vHwM7wDEPchCj0gaQtlYa1X+mii+xhOgCi6K1UVj1 z8R0A8P3wjIv9meXN0oiM92jwQXa5Odb8a+d0Qz2WCRPTdOvEeVUPnoOvb46q6ETbiJB s3bw== X-Gm-Message-State: AOAM5300q6V1zLt7iR0YMB0V1OiVeu4fe+ESZkPde7fWKJKa/qkQXDZ9 SIzjo6MQHVHFSaMVFaBoexE= X-Google-Smtp-Source: ABdhPJzxQThgz4Uk24h+6fhDOnCaHDbJKvw/02CMfzuczkl/rhDRi+H0mPdAxTN/o4mDXDH1xNz8lw== X-Received: by 2002:a17:906:819:: with SMTP id e25mr2204566ejd.292.1616457127966; Mon, 22 Mar 2021 16:52:07 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:07 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 05/11] net: bridge: add helper to replay VLANs installed on port Date: Tue, 23 Mar 2021 01:51:46 +0200 Message-Id: <20210322235152.268695-6-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Currently this simple setup with DSA: ip link add br0 type bridge vlan_filtering 1 ip link add bond0 type bond ip link set bond0 master br0 ip link set swp0 master bond0 will not work because the bridge has created the PVID in br_add_if -> nbp_vlan_init, and it has notified switchdev of the existence of VLAN 1, but that was too early, since swp0 was not yet a lower of bond0, so it had no reason to act upon that notification. We need a helper in the bridge to replay the switchdev VLAN objects that were notified since the bridge port creation, because some of them may have been missed. As opposed to the br_mdb_replay function, the vg->vlan_list write side protection is offered by the rtnl_mutex which is sleepable, so we don't need to queue up the objects in atomic context, we can replay them right away. Signed-off-by: Vladimir Oltean Acked-by: Nikolay Aleksandrov --- include/linux/if_bridge.h | 10 ++++++ net/bridge/br_vlan.c | 73 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index b564c4486a45..2cc35038a8ca 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -111,6 +111,8 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid); int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto); int br_vlan_get_info(const struct net_device *dev, u16 vid, struct bridge_vlan_info *p_vinfo); +int br_vlan_replay(struct net_device *br_dev, struct net_device *dev, + struct notifier_block *nb, struct netlink_ext_ack *extack); #else static inline bool br_vlan_enabled(const struct net_device *dev) { @@ -137,6 +139,14 @@ static inline int br_vlan_get_info(const struct net_device *dev, u16 vid, { return -EINVAL; } + +static inline int br_vlan_replay(struct net_device *br_dev, + struct net_device *dev, + struct notifier_block *nb, + struct netlink_ext_ack *extack) +{ + return -EOPNOTSUPP; +} #endif #if IS_ENABLED(CONFIG_BRIDGE) diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 8829f621b8ec..ca8daccff217 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1751,6 +1751,79 @@ void br_vlan_notify(const struct net_bridge *br, kfree_skb(skb); } +static int br_vlan_replay_one(struct notifier_block *nb, + struct net_device *dev, + struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) +{ + struct switchdev_notifier_port_obj_info obj_info = { + .info = { + .dev = dev, + .extack = extack, + }, + .obj = &vlan->obj, + }; + int err; + + err = nb->notifier_call(nb, SWITCHDEV_PORT_OBJ_ADD, &obj_info); + return notifier_to_errno(err); +} + +int br_vlan_replay(struct net_device *br_dev, struct net_device *dev, + struct notifier_block *nb, struct netlink_ext_ack *extack) +{ + struct net_bridge_vlan_group *vg; + struct net_bridge_vlan *v; + struct net_bridge_port *p; + struct net_bridge *br; + int err = 0; + u16 pvid; + + ASSERT_RTNL(); + + if (!netif_is_bridge_master(br_dev)) + return -EINVAL; + + if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) + return -EINVAL; + + if (netif_is_bridge_master(dev)) { + br = netdev_priv(dev); + vg = br_vlan_group(br); + p = NULL; + } else { + p = br_port_get_rtnl(dev); + if (WARN_ON(!p)) + return -EINVAL; + vg = nbp_vlan_group(p); + br = p->br; + } + + if (!vg) + return 0; + + pvid = br_get_pvid(vg); + + list_for_each_entry(v, &vg->vlan_list, vlist) { + struct switchdev_obj_port_vlan vlan = { + .obj.orig_dev = dev, + .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, + .flags = br_vlan_flags(v, pvid), + .vid = v->vid, + }; + + if (!br_vlan_should_use(v)) + continue; + + br_vlan_replay_one(nb, dev, &vlan, extack); + if (err) + return err; + } + + return err; +} +EXPORT_SYMBOL_GPL(br_vlan_replay); + /* check if v_curr can enter a range ending in range_end */ bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, const struct net_bridge_vlan *range_end) From patchwork Mon Mar 22 23:51:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 407448 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.7 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, URIBL_BLOCKED, 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 ACC27C433F7 for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7EE61619A4 for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231179AbhCVXw0 (ORCPT ); Mon, 22 Mar 2021 19:52:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57642 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230445AbhCVXwL (ORCPT ); Mon, 22 Mar 2021 19:52:11 -0400 Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6437DC061574; Mon, 22 Mar 2021 16:52:10 -0700 (PDT) Received: by mail-ej1-x635.google.com with SMTP id u21so6148014ejo.13; Mon, 22 Mar 2021 16:52:10 -0700 (PDT) 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=O/92wVBAP5j4BB+u+puYhzxAdKb4svuqVtkB4xOs7jA=; b=TN8RWZO8zeXHI7/VmJtYlbV9gi2Qw9YB8otq/GrgWsCCGMIrSPOhS4IAmr+LDXqcFB /RV5AU5vSZaFz762Yj2pwZKQ2g7n6uzhbzLssdGB0Tv9f194CR4/e2fxli/ekKJYnosL iv5jstSxKBI2zefLyXgMK0uymv28iYmVhcKaZ3XibVZQ0bIrTXOAKazcyTIH7DAQdqI1 QyICvPcaobpZds8WZi1M9pEFHlwx1T5ioPX0/I0NAuvhD2nRdOKJlQxjsAsPEGnd6XDB ApTQXxI6KMFsiVUYsPUa9DzbukYiCqpqWB4fybLvaA/cw+K/ycK6W/3bYpWw26yX9Laf 2XpA== 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=O/92wVBAP5j4BB+u+puYhzxAdKb4svuqVtkB4xOs7jA=; b=aTm4B1A6Z7D75fgO/ALZVyPeKKoUFKxubnC+AxvLPyYV9Q8/JBsKWL4LU5If+2W1X4 tDPjV8u30WSVzp7PDBgZHf+hXGGgDS6PVnawtPF2UM1BJzIr+MxSvRzwu9Z5daCMlwUK QvDjTSARAC3Q7Wa9p/kFAs7vI7r/H96cdGhnilsigsJWPKbxen/jdUyvQgF16Vr9qxC9 lwoRZl+RveVQpZ+SON/cO3Guss4ZpDN/VLfbwgpuqoGNTOwsO7NFMzORcrxLRYxosOZN 9MDbNPtfAvS0T9RNZIdAG5wqaPoL1oxSzUly5h/b2AKBYL96QPTCDla8OOwSPGjb51Ph 3meA== X-Gm-Message-State: AOAM530vu2luSxMxE+66KXwLbb+oPlJdKTqHiYGDvWQ0nMXixNeQtg+2 4lx2L2Je8bfICKQJQhqVdMM= X-Google-Smtp-Source: ABdhPJzOBT60AjgajvsZsximQS+6UzbcLDK+RWlOrorpC2WPfXahYTh6YvZj/y6+hiuOaGmm/LDbLg== X-Received: by 2002:a17:906:18a1:: with SMTP id c1mr2108709ejf.62.1616457129211; Mon, 22 Mar 2021 16:52:09 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:08 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 06/11] net: dsa: call dsa_port_bridge_join when joining a LAG that is already in a bridge Date: Tue, 23 Mar 2021 01:51:47 +0200 Message-Id: <20210322235152.268695-7-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean DSA can properly detect and offload this sequence of operations: ip link add br0 type bridge ip link add bond0 type bond ip link set swp0 master bond0 ip link set bond0 master br0 But not this one: ip link add br0 type bridge ip link add bond0 type bond ip link set bond0 master br0 ip link set swp0 master bond0 Actually the second one is more complicated, due to the elapsed time between the enslavement of bond0 and the offloading of it via swp0, a lot of things could have happened to the bond0 bridge port in terms of switchdev objects (host MDBs, VLANs, altered STP state etc). So this is a bit of a can of worms, and making sure that the DSA port's state is in sync with this already existing bridge port is handled in the next patches. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Reviewed-by: Tobias Waldekranz --- net/dsa/port.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/net/dsa/port.c b/net/dsa/port.c index c9c6d7ab3f47..d39262a9fe0e 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -249,17 +249,31 @@ int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag, .lag = lag, .info = uinfo, }; + struct net_device *bridge_dev; int err; dsa_lag_map(dp->ds->dst, lag); dp->lag_dev = lag; err = dsa_port_notify(dp, DSA_NOTIFIER_LAG_JOIN, &info); - if (err) { - dp->lag_dev = NULL; - dsa_lag_unmap(dp->ds->dst, lag); - } + if (err) + goto err_lag_join; + bridge_dev = netdev_master_upper_dev_get(lag); + if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) + return 0; + + err = dsa_port_bridge_join(dp, bridge_dev); + if (err) + goto err_bridge_join; + + return 0; + +err_bridge_join: + dsa_port_notify(dp, DSA_NOTIFIER_LAG_LEAVE, &info); +err_lag_join: + dp->lag_dev = NULL; + dsa_lag_unmap(dp->ds->dst, lag); return err; } From patchwork Mon Mar 22 23:51:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406466 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.7 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, URIBL_BLOCKED, 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 A134DC433E8 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 86503619A4 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231435AbhCVXxD (ORCPT ); Mon, 22 Mar 2021 19:53:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230401AbhCVXwS (ORCPT ); Mon, 22 Mar 2021 19:52:18 -0400 Received: from mail-ej1-x62a.google.com (mail-ej1-x62a.google.com [IPv6:2a00:1450:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C36DC061756; Mon, 22 Mar 2021 16:52:18 -0700 (PDT) Received: by mail-ej1-x62a.google.com with SMTP id kt15so14623342ejb.12; Mon, 22 Mar 2021 16:52:18 -0700 (PDT) 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=3j9IRf1uS0iLbr0h9QeCEpTgMc/Yj8/rDEYeUIAudAc=; b=F30raTqhVpI1HIDCM0AWkT4amevPv6V9djZa2FCvv75xrWL7yT7CyjMGf3KeVWjk8h +ADlbfGR6MVPV9suYuzKvpzuFUvwULIfR1EZpOveASu4U0aBuoAKKQtCy+EL68iE4jCb YKXCHUBu89Ls0g+wq/R0tSg8xvd1fqFFp2DRmgLwWVLpPcUCZOMVrxwtOSeqmjFMQ1QM buepLuNzzuoRrmOPKj3jGzLESGd6SLjlu9Des8zZbKEqeKeEcxwGVCDHcSEfioj13G2w VJpOG5qxXnA3Ejouz49jH/8UTGfumrF5zr9jFLMPRNQJEMpiyZk7PFEFsicWUWIchZUU 8U/Q== 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=3j9IRf1uS0iLbr0h9QeCEpTgMc/Yj8/rDEYeUIAudAc=; b=SG1wYmBLdrln4jDpl0Zq88shhIQPvmMiaYwv2X9K5InldrnwLeoo4hIqGd/dHVlo7X jWlzg1TwfAmt6P575cZSaecKR6wgz0GIoLnw/vF6LMzDO5e68l90tPlRZch3EMFgHjuE Asbv+pjBHn5bgjVDP58GGCwh98/hzRMe/WikO6WAo/5Kdj82DqQ5e7rBDYWAZ6l55P3j fE9YI7LfoT769agtWnpLRxCjGt81og3DMkWng0my17K81WUMf4KfaJVLSfbw24/Hp9Tc LZLrOZJD0ucFqifucR4uYHy193czZhyEKmjGKKg8+1jv6TScz+MQ6ywevRJ5uvRu2TkS 4yRg== X-Gm-Message-State: AOAM530sTnPW9HoC33iRrgcZYbyGUgXmSp+GLCgxoM2Av57CKevpg40P a4t3FXfIPESBshu1wrnIK8uZ7uZ5F90= X-Google-Smtp-Source: ABdhPJwdGMx9ufDQ3y8O5ClwKZ2yNT6BXZMr5NoIo/z0gd4z1fFM0R+yw5Rd4lCowYUfD2Eq7Lfeeg== X-Received: by 2002:a17:906:80ca:: with SMTP id a10mr2125859ejx.297.1616457130535; Mon, 22 Mar 2021 16:52:10 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:10 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 07/11] net: dsa: pass extack to dsa_port_{bridge, lag}_join Date: Tue, 23 Mar 2021 01:51:48 +0200 Message-Id: <20210322235152.268695-8-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean This is a pretty noisy change that was broken out of the larger change for replaying switchdev attributes and objects at bridge join time, which is when these extack objects are actually used. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Reviewed-by: Tobias Waldekranz --- net/dsa/dsa_priv.h | 6 ++++-- net/dsa/port.c | 8 +++++--- net/dsa/slave.c | 7 +++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 4c43c5406834..b8778c5d8529 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -181,12 +181,14 @@ int dsa_port_enable_rt(struct dsa_port *dp, struct phy_device *phy); int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy); void dsa_port_disable_rt(struct dsa_port *dp); void dsa_port_disable(struct dsa_port *dp); -int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br); +int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, + struct netlink_ext_ack *extack); void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br); int dsa_port_lag_change(struct dsa_port *dp, struct netdev_lag_lower_state_info *linfo); int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev, - struct netdev_lag_upper_info *uinfo); + struct netdev_lag_upper_info *uinfo, + struct netlink_ext_ack *extack); void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev); int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct netlink_ext_ack *extack); diff --git a/net/dsa/port.c b/net/dsa/port.c index d39262a9fe0e..fcbe5b1545b8 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -144,7 +144,8 @@ static void dsa_port_change_brport_flags(struct dsa_port *dp, } } -int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) +int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, + struct netlink_ext_ack *extack) { struct dsa_notifier_bridge_info info = { .tree_index = dp->ds->dst->index, @@ -241,7 +242,8 @@ int dsa_port_lag_change(struct dsa_port *dp, } int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag, - struct netdev_lag_upper_info *uinfo) + struct netdev_lag_upper_info *uinfo, + struct netlink_ext_ack *extack) { struct dsa_notifier_lag_info info = { .sw_index = dp->ds->index, @@ -263,7 +265,7 @@ int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag, if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) return 0; - err = dsa_port_bridge_join(dp, bridge_dev); + err = dsa_port_bridge_join(dp, bridge_dev, extack); if (err) goto err_bridge_join; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 992fcab4b552..1ff48be476bb 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1976,11 +1976,14 @@ static int dsa_slave_changeupper(struct net_device *dev, struct netdev_notifier_changeupper_info *info) { struct dsa_port *dp = dsa_slave_to_port(dev); + struct netlink_ext_ack *extack; int err = NOTIFY_DONE; + extack = netdev_notifier_info_to_extack(&info->info); + if (netif_is_bridge_master(info->upper_dev)) { if (info->linking) { - err = dsa_port_bridge_join(dp, info->upper_dev); + err = dsa_port_bridge_join(dp, info->upper_dev, extack); if (!err) dsa_bridge_mtu_normalization(dp); err = notifier_from_errno(err); @@ -1991,7 +1994,7 @@ static int dsa_slave_changeupper(struct net_device *dev, } else if (netif_is_lag_master(info->upper_dev)) { if (info->linking) { err = dsa_port_lag_join(dp, info->upper_dev, - info->upper_info); + info->upper_info, extack); if (err == -EOPNOTSUPP) { NL_SET_ERR_MSG_MOD(info->info.extack, "Offloading not supported"); From patchwork Mon Mar 22 23:51:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 407447 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.7 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, URIBL_BLOCKED, 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 C442EC433F4 for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 95A92619A3 for ; Mon, 22 Mar 2021 23:52:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231202AbhCVXwa (ORCPT ); Mon, 22 Mar 2021 19:52:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57652 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229622AbhCVXwN (ORCPT ); Mon, 22 Mar 2021 19:52:13 -0400 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 23A1FC061574; Mon, 22 Mar 2021 16:52:13 -0700 (PDT) Received: by mail-ej1-x636.google.com with SMTP id w3so24120203ejc.4; Mon, 22 Mar 2021 16:52:13 -0700 (PDT) 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=LYURHPgoUHC+LuUEXW8Qp3cwYVxWxmcSv0S5vH1KiMo=; b=Czc3j3n86SuF6zos4QC7IEGjnEGaD1SdHQ4QFZwNWFW2i2XjavCmgz7otxPfwkNtPe mKm0fQQ36iPvjryHqd0ruod7onfmzRJ0Z1OttMDh8t5OGn2A8agvL+NMGLj9AwR2Wun4 u/jimS+PPIUNS44Ic4YGmFmiuYyPDlBvrjH8rWLke3IkkLQJHq5/eH1y/XYUfz9QDH4/ yb4C67/6ITkTjbrZ7q6v16GWXn1DM85Y6bsnBzWl6WTYVIPu4yXxXQJ4V7rl5idkaFkw 1dP4aaPMKr9G24BKhS7CLnwGPv74FhGXUz7JsZgzL2maGJBwQXw2K2vzDDwmcXXf7HNs kL/Q== 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=LYURHPgoUHC+LuUEXW8Qp3cwYVxWxmcSv0S5vH1KiMo=; b=RrefFUmhaPQZ2ixo/4QviQeoUgGa4P3JWsmIAdYwpXv4eqDIJ36xKyqGQYbtsolA84 CXGzaAX3wdG4EBdVtvD66dLWqkgbqtGYtl07uYYiFqyqbmZv1mqlt1HscUCnsO8D6IsE rqelEhUopJFg5FS+pv8wDVTjU8rOK/ytft1iB3n5cCvhAmxUxsbAbb7w47ObPdLHvrRl BTaVeggR1z1avwSylZDoI/DG+mKJfnDnsYxUUSYIHLFsycnWI9StErP4gi4MxCvnfhYi 7UxZnt/jx3UYK8kz1EC6wXmdNlAY8ciSR49IRB47tv+nFea+kHS4k+9akh54O62BoxRq G1dw== X-Gm-Message-State: AOAM533SOiyMBqsUiGAjCMKK0mMnWZOv5IrMjUpj058eEBJDBaoZ5nyY ZNmkwZ/NuXA+uK/A0owdNdVdSuR3NPk= X-Google-Smtp-Source: ABdhPJyRKLvWj8cb75kIQ16q/PoFigip0G4FDV7Bhk2TiBlIgJx7upiJwqRK1L1pRruT2H+w0G/hWA== X-Received: by 2002:a17:906:f56:: with SMTP id h22mr2187552ejj.494.1616457131882; Mon, 22 Mar 2021 16:52:11 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:11 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 08/11] net: dsa: inherit the actual bridge port flags at join time Date: Tue, 23 Mar 2021 01:51:49 +0200 Message-Id: <20210322235152.268695-9-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean DSA currently assumes that the bridge port starts off with this constellation of bridge port flags: - learning on - unicast flooding on - multicast flooding on - broadcast flooding on just by virtue of code copy-pasta from the bridge layer (new_nbp). This was a simple enough strategy thus far, because the 'bridge join' moment always coincided with the 'bridge port creation' moment. But with sandwiched interfaces, such as: br0 | bond0 | swp0 it may happen that the user has had time to change the bridge port flags of bond0 before enslaving swp0 to it. In that case, swp0 will falsely assume that the bridge port flags are those determined by new_nbp, when in fact this can happen: ip link add br0 type bridge ip link add bond0 type bond ip link set bond0 master br0 ip link set bond0 type bridge_slave learning off ip link set swp0 master br0 Now swp0 has learning enabled, bond0 has learning disabled. Not nice. Fix this by "dumpster diving" through the actual bridge port flags with br_port_flag_is_set, at bridge join time. We use this opportunity to split dsa_port_change_brport_flags into two distinct functions called dsa_port_inherit_brport_flags and dsa_port_clear_brport_flags, now that the implementation for the two cases is no longer similar. This patch also creates two functions called dsa_port_switchdev_sync and dsa_port_switchdev_unsync which collect what we have so far, even if that's asymmetrical. More is going to be added in the next patch. Signed-off-by: Vladimir Oltean --- net/dsa/port.c | 123 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 41 deletions(-) diff --git a/net/dsa/port.c b/net/dsa/port.c index fcbe5b1545b8..c712bf3da0a0 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -122,28 +122,84 @@ void dsa_port_disable(struct dsa_port *dp) rtnl_unlock(); } -static void dsa_port_change_brport_flags(struct dsa_port *dp, - bool bridge_offload) +static int dsa_port_inherit_brport_flags(struct dsa_port *dp, + struct netlink_ext_ack *extack) { - struct switchdev_brport_flags flags; - int flag; + const unsigned long mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | + BR_BCAST_FLOOD; + struct net_device *brport_dev = dsa_port_to_bridge_port(dp); + int flag, err; - flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; - if (bridge_offload) - flags.val = flags.mask; - else - flags.val = flags.mask & ~BR_LEARNING; + for_each_set_bit(flag, &mask, 32) { + struct switchdev_brport_flags flags = {0}; + + flags.mask = BIT(flag); - for_each_set_bit(flag, &flags.mask, 32) { - struct switchdev_brport_flags tmp; + if (br_port_flag_is_set(brport_dev, BIT(flag))) + flags.val = BIT(flag); + + err = dsa_port_bridge_flags(dp, flags, extack); + if (err && err != -EOPNOTSUPP) + return err; + } - tmp.val = flags.val & BIT(flag); - tmp.mask = BIT(flag); + return 0; +} - dsa_port_bridge_flags(dp, tmp, NULL); +static void dsa_port_clear_brport_flags(struct dsa_port *dp) +{ + const unsigned long val = BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; + const unsigned long mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | + BR_BCAST_FLOOD; + int flag, err; + + for_each_set_bit(flag, &mask, 32) { + struct switchdev_brport_flags flags = {0}; + + flags.mask = BIT(flag); + flags.val = val & BIT(flag); + + err = dsa_port_bridge_flags(dp, flags, NULL); + if (err && err != -EOPNOTSUPP) + dev_err(dp->ds->dev, + "failed to clear bridge port flag %lu: %pe\n", + flags.val, ERR_PTR(err)); } } +static int dsa_port_switchdev_sync(struct dsa_port *dp, + struct netlink_ext_ack *extack) +{ + int err; + + err = dsa_port_inherit_brport_flags(dp, extack); + if (err) + return err; + + return 0; +} + +static void dsa_port_switchdev_unsync(struct dsa_port *dp) +{ + /* Configure the port for standalone mode (no address learning, + * flood everything). + * The bridge only emits SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS events + * when the user requests it through netlink or sysfs, but not + * automatically at port join or leave, so we need to handle resetting + * the brport flags ourselves. But we even prefer it that way, because + * otherwise, some setups might never get the notification they need, + * for example, when a port leaves a LAG that offloads the bridge, + * it becomes standalone, but as far as the bridge is concerned, no + * port ever left. + */ + dsa_port_clear_brport_flags(dp); + + /* 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 + */ + dsa_port_set_state_now(dp, BR_STATE_FORWARDING); +} + int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, struct netlink_ext_ack *extack) { @@ -155,24 +211,25 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, }; int err; - /* Notify the port driver to set its configurable flags in a way that - * matches the initial settings of a bridge port. - */ - dsa_port_change_brport_flags(dp, true); - /* Here the interface is already bridged. Reflect the current * configuration so that drivers can program their chips accordingly. */ dp->bridge_dev = br; err = dsa_broadcast(DSA_NOTIFIER_BRIDGE_JOIN, &info); + if (err) + goto out_rollback; - /* The bridging is rolled back on error */ - if (err) { - dsa_port_change_brport_flags(dp, false); - dp->bridge_dev = NULL; - } + err = dsa_port_switchdev_sync(dp, extack); + if (err) + goto out_rollback_unbridge; + return 0; + +out_rollback_unbridge: + dsa_broadcast(DSA_NOTIFIER_BRIDGE_LEAVE, &info); +out_rollback: + dp->bridge_dev = NULL; return err; } @@ -195,23 +252,7 @@ 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"); - /* Configure the port for standalone mode (no address learning, - * flood everything). - * The bridge only emits SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS events - * when the user requests it through netlink or sysfs, but not - * automatically at port join or leave, so we need to handle resetting - * the brport flags ourselves. But we even prefer it that way, because - * otherwise, some setups might never get the notification they need, - * for example, when a port leaves a LAG that offloads the bridge, - * it becomes standalone, but as far as the bridge is concerned, no - * port ever left. - */ - dsa_port_change_brport_flags(dp, false); - - /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer, - * so allow it to be in BR_STATE_FORWARDING to be kept functional - */ - dsa_port_set_state_now(dp, BR_STATE_FORWARDING); + dsa_port_switchdev_unsync(dp); } int dsa_port_lag_change(struct dsa_port *dp, From patchwork Mon Mar 22 23:51:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 407446 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.7 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, URIBL_BLOCKED, 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 372D3C433E1 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0F148619A9 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231189AbhCVXwu (ORCPT ); Mon, 22 Mar 2021 19:52:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57654 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230447AbhCVXwP (ORCPT ); Mon, 22 Mar 2021 19:52:15 -0400 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 7371EC061574; Mon, 22 Mar 2021 16:52:14 -0700 (PDT) Received: by mail-ej1-x636.google.com with SMTP id ce10so24107134ejb.6; Mon, 22 Mar 2021 16:52:14 -0700 (PDT) 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=2lVrwqtYZdn4Cq95K9Ax8U6MOh2RqIZ/KBKR9D/4SSA=; b=Mn9525TUMj47Z5+rhoa9T9jBlJH36uLzpE7lsxEAPnB4nVNlF6lcSheE0UEndFclDv 1SDXkMoHb0I4SNDVr1ylqcizP9zetYDZBoM+YuiVGdf90ARbq8kBNZK4UiaqSSaFoBV8 puR9RJRqPTQnHfu7JX+rp7GPOFiAScyTAbVq0MoXDnq61digha4AAM62PrOeO12rB2Br /S+QAJCID5Kk36jlaqqFBESNJMyprDsTsVNRDcwbEbZ0uCMscrP17yvIbolH+wgRoiVj VbDcu/uQ1Xe96fu56T/D7CGRDuf6IWGQT4Eu6ceB+7nZbvUFOwEMwg72u/CpGarBcuPz H1wA== 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=2lVrwqtYZdn4Cq95K9Ax8U6MOh2RqIZ/KBKR9D/4SSA=; b=ktpWoDXEGJbGzTUKC6XfqN5+EZfkrTZQnXkSAkQDGqF3OpTTHMIPnEPgUtfdoPECVC byNhMWJzQdxVGHGp0SsEJJ5bMjVZoMFjc/YSOH96n2PT6pOB0W+g3sxiCevEm5BPgNI/ 5/C3iBYLN3lfUZ/nty/8+SPG17mfw5yPZBCgMe8qSODR77Wjq9kvuaac2n/uN/xc0pgV ce3pBWO4Qau7pUmSTiPVHRJbhWrtEaN4tMR0b1ZTkuGKpkAknfL5sfojU5+L/fv2QMcF st4ibkYg23hJUE9W+z3XDEhvHeoXcniSQ16dX/JoQh1+LF5HTh20gnyL7w1sSaYfcdge F0PQ== X-Gm-Message-State: AOAM531QZtpASnuYLfXhCBAvnPC374amMlTlUuviaVzS4K5t9wlNqPOh B6LFZpVtz9cXbGLqwBJFuTY= X-Google-Smtp-Source: ABdhPJw6Z4W2eOXeu3zR1HNBC594Bag2zq+JaGAIBfYXElQK3zyFWrkvIz146REAYNi595/G96+1OQ== X-Received: by 2002:a17:906:ecaa:: with SMTP id qh10mr2121344ejb.425.1616457133153; Mon, 22 Mar 2021 16:52:13 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:12 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 09/11] net: dsa: sync up switchdev objects and port attributes when joining the bridge Date: Tue, 23 Mar 2021 01:51:50 +0200 Message-Id: <20210322235152.268695-10-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean If we join an already-created bridge port, such as a bond master interface, then we can miss the initial switchdev notifications emitted by the bridge for this port, while it wasn't offloaded by anybody. Signed-off-by: Vladimir Oltean --- net/dsa/dsa_priv.h | 3 +++ net/dsa/port.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 4 ++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index b8778c5d8529..92282de54230 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -262,6 +262,9 @@ static inline bool dsa_tree_offloads_bridge_port(struct dsa_switch_tree *dst, /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; +extern struct notifier_block dsa_slave_switchdev_notifier; +extern struct notifier_block dsa_slave_switchdev_blocking_notifier; + void dsa_slave_mii_bus_init(struct dsa_switch *ds); int dsa_slave_create(struct dsa_port *dp); void dsa_slave_destroy(struct net_device *slave_dev); diff --git a/net/dsa/port.c b/net/dsa/port.c index c712bf3da0a0..01e30264b25b 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -170,12 +170,46 @@ static void dsa_port_clear_brport_flags(struct dsa_port *dp) static int dsa_port_switchdev_sync(struct dsa_port *dp, struct netlink_ext_ack *extack) { + struct net_device *brport_dev = dsa_port_to_bridge_port(dp); + struct net_device *br = dp->bridge_dev; int err; err = dsa_port_inherit_brport_flags(dp, extack); if (err) return err; + err = dsa_port_set_state(dp, br_port_get_stp_state(brport_dev)); + if (err && err != -EOPNOTSUPP) + return err; + + err = dsa_port_vlan_filtering(dp, br_vlan_enabled(br), extack); + if (err && err != -EOPNOTSUPP) + return err; + + err = dsa_port_mrouter(dp->cpu_dp, br_multicast_router(br), extack); + if (err && err != -EOPNOTSUPP) + return err; + + err = dsa_port_ageing_time(dp, br_get_ageing_time(br)); + if (err && err != -EOPNOTSUPP) + return err; + + err = br_mdb_replay(br, brport_dev, + &dsa_slave_switchdev_blocking_notifier, + extack); + if (err && err != -EOPNOTSUPP) + return err; + + err = br_fdb_replay(br, brport_dev, &dsa_slave_switchdev_notifier); + if (err && err != -EOPNOTSUPP) + return err; + + err = br_vlan_replay(br, brport_dev, + &dsa_slave_switchdev_blocking_notifier, + extack); + if (err && err != -EOPNOTSUPP) + return err; + return 0; } @@ -198,6 +232,18 @@ static void dsa_port_switchdev_unsync(struct dsa_port *dp) * so allow it to be in BR_STATE_FORWARDING to be kept functional */ dsa_port_set_state_now(dp, BR_STATE_FORWARDING); + + /* VLAN filtering is handled by dsa_switch_bridge_leave */ + + /* Some drivers treat the notification for having a local multicast + * router by allowing multicast to be flooded to the CPU, so we should + * allow this in standalone mode too. + */ + dsa_port_mrouter(dp->cpu_dp, true, NULL); + + /* Ageing time may be global to the switch chip, so don't change it + * here because we have no good reason (or value) to change it to. + */ } int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br, diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 1ff48be476bb..c51e52418a62 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2392,11 +2392,11 @@ static struct notifier_block dsa_slave_nb __read_mostly = { .notifier_call = dsa_slave_netdevice_event, }; -static struct notifier_block dsa_slave_switchdev_notifier = { +struct notifier_block dsa_slave_switchdev_notifier = { .notifier_call = dsa_slave_switchdev_event, }; -static struct notifier_block dsa_slave_switchdev_blocking_notifier = { +struct notifier_block dsa_slave_switchdev_blocking_notifier = { .notifier_call = dsa_slave_switchdev_blocking_event, }; From patchwork Mon Mar 22 23:51:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 406467 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.7 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, URIBL_BLOCKED, 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 6CCD1C433C1 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 56B64619A4 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231332AbhCVXwz (ORCPT ); Mon, 22 Mar 2021 19:52:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57662 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230174AbhCVXwQ (ORCPT ); Mon, 22 Mar 2021 19:52:16 -0400 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 EFB94C061574; Mon, 22 Mar 2021 16:52:15 -0700 (PDT) Received: by mail-ej1-x62c.google.com with SMTP id r12so24121125ejr.5; Mon, 22 Mar 2021 16:52:15 -0700 (PDT) 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=6pdAPojJ5CzZpeJIbTb0+ylqgkWkyvqwhDkz8RlT1bc=; b=cmHU9E5uA6AtZOy4eF9EzzNq8ezxt3tMYlrlDhLp25TRjYAthecfBdDSftaRhgt+mb JUV5C/TN6wSZeHXM6oE7pTEZ2Tky+GNkSmFgt75neh4s2x45noY60I3h2DGyuP6CtIdb B7sGQbZ3llZ/gjJcxbSsFst7+NcCszJ2YwFnHo9YE1iDQVEp+hpaUMljbzzRjc/JccXI oa+H+CAbpzT2D9SOG6Aa/uPrYIH830DVpCBOF7naU+sTdUHaebEQj+zrPLYAri9fwE+m 0wyC63nopoARd3Vt4KGGzjsz6wxbXAnxk3oMwIbfQ+vmiJotrbtyxdhUGbGmW55nwrEm OFcQ== 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=6pdAPojJ5CzZpeJIbTb0+ylqgkWkyvqwhDkz8RlT1bc=; b=hJdFtKLCS524vTw2yHWApUe2oe8ciSt+Fygz9As7dK1QCXoppJmcye9daYqbValCW1 bzDHCzlbP5lWcI7CQdLHzU8cVL5RlQ9qbq/DOxQ3TotinK7e34lyNW8E1UaOeEL4HZZN gdiSX6EIFckLympp2i7M11409WQUGZqnbHp/IQ4G7ldCOTqQ4QCKormnglJqoZEnTttF yMeT9NpZZztKi1SK0bhzlwUPENTIBD2BTXFBmzIh0EOYEdIGGdn11jQVE/HU6Qxqgc9d VnFz1N6a+LuEMpQiZJHQYD9b92kuAB1TUlW+sQBDIYwr9zHs2zDcMYiZkJt+N8thbvrx By7g== X-Gm-Message-State: AOAM532lfneM77lwUUIsTyroZNJD++RZj86kIvo/CEgEnYrc2w6Egpzk lRYQY4PUo0fMBaKGEy7PJu8= X-Google-Smtp-Source: ABdhPJyXHNdQO4954pyNe0ODd3gSqVFHW7Fg3zF1frnutuVUxxGHyP8j0WCanxvX0v9ty71fBo2QhA== X-Received: by 2002:a17:906:9bdb:: with SMTP id de27mr2128841ejc.459.1616457134704; Mon, 22 Mar 2021 16:52:14 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:14 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 10/11] net: ocelot: call ocelot_netdevice_bridge_join when joining a bridged LAG Date: Tue, 23 Mar 2021 01:51:51 +0200 Message-Id: <20210322235152.268695-11-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Similar to the DSA situation, ocelot supports LAG offload but treats this scenario improperly: ip link add br0 type bridge ip link add bond0 type bond ip link set bond0 master br0 ip link set swp0 master bond0 We do the same thing as we do there, which is to simulate a 'bridge join' on 'lag join', if we detect that the bonding upper has a bridge upper. Again, same as DSA, ocelot supports software fallback for LAG, and in that case, we should avoid calling ocelot_netdevice_changeupper. Signed-off-by: Vladimir Oltean --- drivers/net/ethernet/mscc/ocelot_net.c | 111 +++++++++++++++++++------ 1 file changed, 86 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index c08164cd88f4..d1376f7b34fd 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1117,10 +1117,15 @@ static int ocelot_port_obj_del(struct net_device *dev, return ret; } -static int ocelot_netdevice_bridge_join(struct ocelot *ocelot, int port, - struct net_device *bridge) +static int ocelot_netdevice_bridge_join(struct net_device *dev, + struct net_device *bridge, + struct netlink_ext_ack *extack) { + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; struct switchdev_brport_flags flags; + int port = priv->chip_port; int err; flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; @@ -1135,10 +1140,14 @@ static int ocelot_netdevice_bridge_join(struct ocelot *ocelot, int port, return 0; } -static int ocelot_netdevice_bridge_leave(struct ocelot *ocelot, int port, +static int ocelot_netdevice_bridge_leave(struct net_device *dev, struct net_device *bridge) { + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; struct switchdev_brport_flags flags; + int port = priv->chip_port; int err; flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; @@ -1151,43 +1160,89 @@ static int ocelot_netdevice_bridge_leave(struct ocelot *ocelot, int port, return err; } -static int ocelot_netdevice_changeupper(struct net_device *dev, - struct netdev_notifier_changeupper_info *info) +static int ocelot_netdevice_lag_join(struct net_device *dev, + struct net_device *bond, + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct ocelot_port_private *priv = netdev_priv(dev); struct ocelot_port *ocelot_port = &priv->port; struct ocelot *ocelot = ocelot_port->ocelot; + struct net_device *bridge_dev; int port = priv->chip_port; + int err; + + err = ocelot_port_lag_join(ocelot, port, bond, info); + if (err == -EOPNOTSUPP) { + NL_SET_ERR_MSG_MOD(extack, "Offloading not supported"); + return 0; + } + + bridge_dev = netdev_master_upper_dev_get(bond); + if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) + return 0; + + err = ocelot_netdevice_bridge_join(dev, bridge_dev, extack); + if (err) + goto err_bridge_join; + + return 0; + +err_bridge_join: + ocelot_port_lag_leave(ocelot, port, bond); + return err; +} + +static int ocelot_netdevice_lag_leave(struct net_device *dev, + struct net_device *bond) +{ + struct ocelot_port_private *priv = netdev_priv(dev); + struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = ocelot_port->ocelot; + struct net_device *bridge_dev; + int port = priv->chip_port; + + ocelot_port_lag_leave(ocelot, port, bond); + + bridge_dev = netdev_master_upper_dev_get(bond); + if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) + return 0; + + return ocelot_netdevice_bridge_leave(dev, bridge_dev); +} + +static int ocelot_netdevice_changeupper(struct net_device *dev, + struct netdev_notifier_changeupper_info *info) +{ + struct netlink_ext_ack *extack; int err = 0; + extack = netdev_notifier_info_to_extack(&info->info); + if (netif_is_bridge_master(info->upper_dev)) { - if (info->linking) { - err = ocelot_netdevice_bridge_join(ocelot, port, - info->upper_dev); - } else { - err = ocelot_netdevice_bridge_leave(ocelot, port, - info->upper_dev); - } + if (info->linking) + err = ocelot_netdevice_bridge_join(dev, info->upper_dev, + extack); + else + err = ocelot_netdevice_bridge_leave(dev, info->upper_dev); } if (netif_is_lag_master(info->upper_dev)) { - if (info->linking) { - err = ocelot_port_lag_join(ocelot, port, - info->upper_dev, - info->upper_info); - if (err == -EOPNOTSUPP) { - NL_SET_ERR_MSG_MOD(info->info.extack, - "Offloading not supported"); - err = 0; - } - } else { - ocelot_port_lag_leave(ocelot, port, - info->upper_dev); - } + if (info->linking) + err = ocelot_netdevice_lag_join(dev, info->upper_dev, + info->upper_info, extack); + else + ocelot_netdevice_lag_leave(dev, info->upper_dev); } return notifier_from_errno(err); } +/* Treat CHANGEUPPER events on an offloaded LAG as individual CHANGEUPPER + * events for the lower physical ports of the LAG. + * If the LAG upper isn't offloaded, ignore its CHANGEUPPER events. + * In case the LAG joined a bridge, notify that we are offloading it and can do + * forwarding in hardware towards it. + */ static int ocelot_netdevice_lag_changeupper(struct net_device *dev, struct netdev_notifier_changeupper_info *info) @@ -1197,6 +1252,12 @@ ocelot_netdevice_lag_changeupper(struct net_device *dev, int err = NOTIFY_DONE; netdev_for_each_lower_dev(dev, lower, iter) { + struct ocelot_port_private *priv = netdev_priv(lower); + struct ocelot_port *ocelot_port = &priv->port; + + if (ocelot_port->bond != dev) + return NOTIFY_OK; + err = ocelot_netdevice_changeupper(lower, info); if (err) return notifier_from_errno(err); From patchwork Mon Mar 22 23:51:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 407445 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.7 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, URIBL_BLOCKED, 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 8E331C433E5 for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 778B8619CA for ; Mon, 22 Mar 2021 23:53:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231384AbhCVXxA (ORCPT ); Mon, 22 Mar 2021 19:53:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57672 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230476AbhCVXwS (ORCPT ); Mon, 22 Mar 2021 19:52:18 -0400 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 57B37C061574; Mon, 22 Mar 2021 16:52:17 -0700 (PDT) Received: by mail-ed1-x529.google.com with SMTP id h10so21393414edt.13; Mon, 22 Mar 2021 16:52:17 -0700 (PDT) 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=hFbiUL7ABXs6BfCWtiegfX2Fp+LkfCID65v2V8vWIyg=; b=VLpEciWpNnj73+AwsFpdoev+W/7JfvXO+pWYRqNcxJoJ86J6uDrflJjlSgfK5+9Flb nCzXjbloXtKu8W/4opTa8RL179JUfkRWb08CZiECZ1RiB7RkRT7v/vM3AIFRYsu02o96 w+pVe42CHZr4TQFKp4RqHpJJxlAEptTWVCfiU6BpKb6ciRfSfoz1WKSfLhfbhHepmJMu JNKMWcSxajW3xm7lO5Ot8CDa7+IZ/U73+ppF3Rdp0ES4mMwv3YL/ukpZR9rZyjQOUemp u9PF9u1Z8DadOrhYXEJDJoBNstm3Zbbr9ZYgQ4VLbdpemziFGtir4cqdmrB5jp2mxUid US+g== 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=hFbiUL7ABXs6BfCWtiegfX2Fp+LkfCID65v2V8vWIyg=; b=FXKlDZ856TAX4TE2cgLEKyC2WUB8xQYn6bPqMahvsCw7a35fwv7Xdk3nZeLfpHVSh+ 8/dwAkc0EKaeC/wHzxlZ5xEQe6ZVgbjZGXCFAhGWGJTMsV4tc4vbbDrepdiYEBAhe+bV DkkRuW+BE6jMFXglhejkFoGaDyMTrxT3Fw4OTP1Yzq92b43iVqGIyK6nT2bDVn/XNTuA AfwdaByEXVrUab6oJvn5D7ie7YmNmz7sH7CaHc2xq4uNqmnJcKODfgT0XREuNbjV7szR L+9PpsNNTsrN8C/QXTkgXTlsSALMgRDP0n6STMsvyJ2ihx5WF+TzdIEePFgR8rBsElwO HExw== X-Gm-Message-State: AOAM532vE8syPx3/eZUMZqvjtJtjCulEJXOVm6/lMu8XHcmz/ceNTzKQ Jqvrhc6/yr5ial1bI2PlzGc= X-Google-Smtp-Source: ABdhPJx/WrLhFLaeMAwner/ZUJclIhZ3h7XEY4vq/xERS8KWTcC3JOx2h6/BzBdJoUwjy1LVmB3uLA== X-Received: by 2002:aa7:d1d0:: with SMTP id g16mr1991091edp.358.1616457136064; Mon, 22 Mar 2021 16:52:16 -0700 (PDT) Received: from localhost.localdomain (5-12-16-165.residential.rdsnet.ro. [5.12.16.165]) by smtp.gmail.com with ESMTPSA id q16sm12436933edv.61.2021.03.22.16.52.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Mar 2021 16:52:15 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" Cc: Andrew Lunn , Vivien Didelot , Florian Fainelli , Tobias Waldekranz , Claudiu Manoil , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , Jiri Pirko , Ido Schimmel , Alexandre Belloni , UNGLinuxDriver@microchip.com, Ivan Vecera , linux-omap@vger.kernel.org, Vladimir Oltean Subject: [PATCH v4 net-next 11/11] net: ocelot: replay switchdev events when joining bridge Date: Tue, 23 Mar 2021 01:51:52 +0200 Message-Id: <20210322235152.268695-12-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210322235152.268695-1-olteanv@gmail.com> References: <20210322235152.268695-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean The premise of this change is that the switchdev port attributes and objects offloaded by ocelot might have been missed when we are joining an already existing bridge port, such as a bonding interface. The patch pulls these switchdev attributes and objects from the bridge, on behalf of the 'bridge port' net device which might be either the ocelot switch interface, or the bonding upper interface. The ocelot_net.c belongs strictly to the switchdev ocelot driver, while ocelot.c is part of a library shared with the DSA felix driver. The ocelot_port_bridge_leave function (part of the common library) used to call ocelot_port_vlan_filtering(false), something which is not necessary for DSA, since the framework deals with that already there. So we move this function to ocelot_switchdev_unsync, which is specific to the switchdev driver. The code movement described above makes ocelot_port_bridge_leave no longer return an error code, so we change its type from int to void. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/ocelot/felix.c | 4 +- drivers/net/ethernet/mscc/Kconfig | 3 +- drivers/net/ethernet/mscc/ocelot.c | 18 ++-- drivers/net/ethernet/mscc/ocelot_net.c | 117 +++++++++++++++++++++---- include/soc/mscc/ocelot.h | 6 +- 5 files changed, 113 insertions(+), 35 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 628afb47b579..6b5442be0230 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -719,7 +719,9 @@ static int felix_bridge_join(struct dsa_switch *ds, int port, { struct ocelot *ocelot = ds->priv; - return ocelot_port_bridge_join(ocelot, port, br); + ocelot_port_bridge_join(ocelot, port, br); + + return 0; } static void felix_bridge_leave(struct dsa_switch *ds, int port, diff --git a/drivers/net/ethernet/mscc/Kconfig b/drivers/net/ethernet/mscc/Kconfig index 05cb040c2677..2d3157e4d081 100644 --- a/drivers/net/ethernet/mscc/Kconfig +++ b/drivers/net/ethernet/mscc/Kconfig @@ -11,7 +11,7 @@ config NET_VENDOR_MICROSEMI if NET_VENDOR_MICROSEMI -# Users should depend on NET_SWITCHDEV, HAS_IOMEM +# Users should depend on NET_SWITCHDEV, HAS_IOMEM, BRIDGE config MSCC_OCELOT_SWITCH_LIB select NET_DEVLINK select REGMAP_MMIO @@ -24,6 +24,7 @@ config MSCC_OCELOT_SWITCH_LIB config MSCC_OCELOT_SWITCH tristate "Ocelot switch driver" + depends on BRIDGE || BRIDGE=n depends on NET_SWITCHDEV depends on HAS_IOMEM depends on OF_NET diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index ce57929ba3d1..1a36b416fd9b 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1514,34 +1514,28 @@ int ocelot_port_mdb_del(struct ocelot *ocelot, int port, } EXPORT_SYMBOL(ocelot_port_mdb_del); -int ocelot_port_bridge_join(struct ocelot *ocelot, int port, - struct net_device *bridge) +void ocelot_port_bridge_join(struct ocelot *ocelot, int port, + struct net_device *bridge) { struct ocelot_port *ocelot_port = ocelot->ports[port]; ocelot_port->bridge = bridge; - return 0; + ocelot_apply_bridge_fwd_mask(ocelot); } EXPORT_SYMBOL(ocelot_port_bridge_join); -int ocelot_port_bridge_leave(struct ocelot *ocelot, int port, - struct net_device *bridge) +void 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; ocelot_port->bridge = NULL; - ret = ocelot_port_vlan_filtering(ocelot, port, false); - if (ret) - return ret; - ocelot_port_set_pvid(ocelot, port, pvid); ocelot_port_set_native_vlan(ocelot, port, native_vlan); - - return 0; + ocelot_apply_bridge_fwd_mask(ocelot); } EXPORT_SYMBOL(ocelot_port_bridge_leave); diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index d1376f7b34fd..36f32a4d9b0f 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1117,47 +1117,126 @@ static int ocelot_port_obj_del(struct net_device *dev, return ret; } +static void ocelot_inherit_brport_flags(struct ocelot *ocelot, int port, + struct net_device *brport_dev) +{ + struct switchdev_brport_flags flags = {0}; + int flag; + + flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; + + for_each_set_bit(flag, &flags.mask, 32) + if (br_port_flag_is_set(brport_dev, BIT(flag))) + flags.val |= BIT(flag); + + ocelot_port_bridge_flags(ocelot, port, flags); +} + +static void ocelot_clear_brport_flags(struct ocelot *ocelot, int port) +{ + struct switchdev_brport_flags flags; + + flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; + flags.val = flags.mask & ~BR_LEARNING; + + ocelot_port_bridge_flags(ocelot, port, flags); +} + +static int ocelot_switchdev_sync(struct ocelot *ocelot, int port, + struct net_device *brport_dev, + struct net_device *bridge_dev, + struct netlink_ext_ack *extack) +{ + clock_t ageing_time; + u8 stp_state; + int err; + + ocelot_inherit_brport_flags(ocelot, port, brport_dev); + + stp_state = br_port_get_stp_state(brport_dev); + ocelot_bridge_stp_state_set(ocelot, port, stp_state); + + err = ocelot_port_vlan_filtering(ocelot, port, + br_vlan_enabled(bridge_dev)); + if (err) + return err; + + ageing_time = br_get_ageing_time(bridge_dev); + ocelot_port_attr_ageing_set(ocelot, port, ageing_time); + + err = br_mdb_replay(bridge_dev, brport_dev, + &ocelot_switchdev_blocking_nb, extack); + if (err && err != -EOPNOTSUPP) + return err; + + err = br_fdb_replay(bridge_dev, brport_dev, &ocelot_switchdev_nb); + if (err) + return err; + + err = br_vlan_replay(bridge_dev, brport_dev, + &ocelot_switchdev_blocking_nb, extack); + if (err && err != -EOPNOTSUPP) + return err; + + return 0; +} + +static int ocelot_switchdev_unsync(struct ocelot *ocelot, int port) +{ + int err; + + err = ocelot_port_vlan_filtering(ocelot, port, false); + if (err) + return err; + + ocelot_clear_brport_flags(ocelot, port); + + ocelot_bridge_stp_state_set(ocelot, port, BR_STATE_FORWARDING); + + return 0; +} + static int ocelot_netdevice_bridge_join(struct net_device *dev, + struct net_device *brport_dev, struct net_device *bridge, struct netlink_ext_ack *extack) { struct ocelot_port_private *priv = netdev_priv(dev); struct ocelot_port *ocelot_port = &priv->port; struct ocelot *ocelot = ocelot_port->ocelot; - struct switchdev_brport_flags flags; int port = priv->chip_port; int err; - flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; - flags.val = flags.mask; + ocelot_port_bridge_join(ocelot, port, bridge); - err = ocelot_port_bridge_join(ocelot, port, bridge); + err = ocelot_switchdev_sync(ocelot, port, brport_dev, bridge, extack); if (err) - return err; - - ocelot_port_bridge_flags(ocelot, port, flags); + goto err_switchdev_sync; return 0; + +err_switchdev_sync: + ocelot_port_bridge_leave(ocelot, port, bridge); + return err; } static int ocelot_netdevice_bridge_leave(struct net_device *dev, + struct net_device *brport_dev, struct net_device *bridge) { struct ocelot_port_private *priv = netdev_priv(dev); struct ocelot_port *ocelot_port = &priv->port; struct ocelot *ocelot = ocelot_port->ocelot; - struct switchdev_brport_flags flags; int port = priv->chip_port; int err; - flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; - flags.val = flags.mask & ~BR_LEARNING; + err = ocelot_switchdev_unsync(ocelot, port); + if (err) + return err; - err = ocelot_port_bridge_leave(ocelot, port, bridge); + ocelot_port_bridge_leave(ocelot, port, bridge); - ocelot_port_bridge_flags(ocelot, port, flags); - - return err; + return 0; } static int ocelot_netdevice_lag_join(struct net_device *dev, @@ -1182,7 +1261,7 @@ static int ocelot_netdevice_lag_join(struct net_device *dev, if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) return 0; - err = ocelot_netdevice_bridge_join(dev, bridge_dev, extack); + err = ocelot_netdevice_bridge_join(dev, bond, bridge_dev, extack); if (err) goto err_bridge_join; @@ -1208,7 +1287,7 @@ static int ocelot_netdevice_lag_leave(struct net_device *dev, if (!bridge_dev || !netif_is_bridge_master(bridge_dev)) return 0; - return ocelot_netdevice_bridge_leave(dev, bridge_dev); + return ocelot_netdevice_bridge_leave(dev, bond, bridge_dev); } static int ocelot_netdevice_changeupper(struct net_device *dev, @@ -1221,10 +1300,12 @@ static int ocelot_netdevice_changeupper(struct net_device *dev, if (netif_is_bridge_master(info->upper_dev)) { if (info->linking) - err = ocelot_netdevice_bridge_join(dev, info->upper_dev, + err = ocelot_netdevice_bridge_join(dev, dev, + info->upper_dev, extack); else - err = ocelot_netdevice_bridge_leave(dev, info->upper_dev); + err = ocelot_netdevice_bridge_leave(dev, dev, + info->upper_dev); } if (netif_is_lag_master(info->upper_dev)) { if (info->linking) diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index ce7e5c1bd90d..68cdc7ceaf4d 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -803,10 +803,10 @@ int ocelot_port_pre_bridge_flags(struct ocelot *ocelot, int port, struct switchdev_brport_flags val); void 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, +void ocelot_port_bridge_join(struct ocelot *ocelot, int port, struct net_device *bridge); +void ocelot_port_bridge_leave(struct ocelot *ocelot, int port, + struct net_device *bridge); int ocelot_fdb_dump(struct ocelot *ocelot, int port, dsa_fdb_dump_cb_t *cb, void *data); int ocelot_fdb_add(struct ocelot *ocelot, int port,