From patchwork Mon May 23 10:42:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858779 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60DE7C433F5 for ; Mon, 23 May 2022 10:43:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234165AbiEWKnJ (ORCPT ); Mon, 23 May 2022 06:43:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53148 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234149AbiEWKnG (ORCPT ); Mon, 23 May 2022 06:43:06 -0400 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E18B0274 for ; Mon, 23 May 2022 03:43:04 -0700 (PDT) Received: by mail-ej1-x62b.google.com with SMTP id f9so27956400ejc.0 for ; Mon, 23 May 2022 03:43:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=01WA8pFyMHR9NLJ1obeHNHl3D1QwsyhGDKgeQr7KWj0=; b=CxsHJazkmmqnzmU/GwqTK5sF+Ek2T19rG4ni+IXWLYrHnNuBPSGv35OQrWw53c2BFc puv2NbHZYK8s+KC1KuvXjcZXN+Z84Feq0UWpllNsfub1VvtQ9jwefG5ZggXbICmtd/XT DSjxOgbwgWaVUKXFiU/avkRZJ4kQZZ+EjHHi6rWOfvg6lU+43ZcnS8h6M7jmWavBorHV LEIfgE8IZZB8HG5NiD1mfDMfKVogxNfrP91lraQF0KAKrDdeaI4FgJVZGk1T/9YSXqtK 84E5eqDMapGPjHe5ccrlk82v86tnKV7RKMTn4Jn78clYP3o53Bk3OgU+8Nl5DYIs3pef 1vrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=01WA8pFyMHR9NLJ1obeHNHl3D1QwsyhGDKgeQr7KWj0=; b=J+DAQXIhVRk+lVWX4arvao60CU8pxe33IDI1SHF/KeYez2oyNVXU1rXc16ZlibX0P4 LMrtBY4mCuMOCZetaaZZXvZosEuimU6LPDbEmp55RGPh8glhZrC6UEZVaMLyDrR9ihhy MNNfIjqYebGGDsxAPreKZjkx0PFcAU3Ijd1VSuRPtYMYnFAkPBmlUHsenuxyuDLE+MT+ hVIVSt2TwdXHL6p5QBp6r8JwDZrV54WP0KmhpSUY+g+IZ2Ns+luuX8gCV6XWyIIBMQ+2 5pkCvO7BGyjst/gi1kk5C4qNMUcfLzp3qq/muY5BJq4+rzgbPk4JG45txzu4z+w1hCsp Z0xg== X-Gm-Message-State: AOAM530bzHsFvEXWA7bxKQQBmpygiR3MId8eaHCWoD0NBvjP5eFhJd4z 84j8ZfPbmtZYjy+8T9w/03P38zZWl4Y= X-Google-Smtp-Source: ABdhPJwX8X8AAn8vCqtoBQ0zXs0Q9kx/2EKL6sfoE+XBVYXpk6nsIL7M875iVi8AuTlHjIcObHawMQ== X-Received: by 2002:a17:907:7ea0:b0:6fe:f024:d006 with SMTP id qb32-20020a1709077ea000b006fef024d006mr2226380ejc.248.1653302582998; Mon, 23 May 2022 03:43:02 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:02 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 01/12] net: introduce iterators over synced hw addresses Date: Mon, 23 May 2022 13:42:45 +0300 Message-Id: <20220523104256.3556016-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean Some network drivers use __dev_mc_sync()/__dev_uc_sync() and therefore program the hardware only with addresses with a non-zero sync_cnt. Some of the above drivers also need to save/restore the address filtering lists when certain events happen, and they need to walk through the struct net_device :: uc and struct net_device :: mc lists. But these lists contain unsynced addresses too. To keep the appearance of an elementary form of data encapsulation, provide iterators through these lists that only look at entries with a non-zero sync_cnt, instead of filtering entries out from device drivers. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- include/linux/netdevice.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f615a66c89e9..47b59f99b037 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -253,11 +253,17 @@ struct netdev_hw_addr_list { #define netdev_uc_empty(dev) netdev_hw_addr_list_empty(&(dev)->uc) #define netdev_for_each_uc_addr(ha, dev) \ netdev_hw_addr_list_for_each(ha, &(dev)->uc) +#define netdev_for_each_synced_uc_addr(_ha, _dev) \ + netdev_for_each_uc_addr((_ha), (_dev)) \ + if ((_ha)->sync_cnt) #define netdev_mc_count(dev) netdev_hw_addr_list_count(&(dev)->mc) #define netdev_mc_empty(dev) netdev_hw_addr_list_empty(&(dev)->mc) #define netdev_for_each_mc_addr(ha, dev) \ netdev_hw_addr_list_for_each(ha, &(dev)->mc) +#define netdev_for_each_synced_mc_addr(_ha, _dev) \ + netdev_for_each_mc_addr((_ha), (_dev)) \ + if ((_ha)->sync_cnt) struct hh_cache { unsigned int hh_len; From patchwork Mon May 23 10:42:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858780 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 772DDC433EF for ; Mon, 23 May 2022 10:43:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234188AbiEWKnO (ORCPT ); Mon, 23 May 2022 06:43:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53170 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234146AbiEWKnI (ORCPT ); Mon, 23 May 2022 06:43:08 -0400 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A3AB260C3 for ; Mon, 23 May 2022 03:43:06 -0700 (PDT) Received: by mail-ed1-x52f.google.com with SMTP id en5so18568882edb.1 for ; Mon, 23 May 2022 03:43:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IG2S0IJHtK1yhe2JNCNBtiyLUGz9p1p+4jsu2s1WXKc=; b=R09++ZvwfG6IODhGk8irupCPYJvPmXQkY8FzByolTAZb3A/3zx6WbNXWxq3EyDBdRx XD+9iM7k/T57fS0e0wo8cVpldPRzBqiq0DMTPm30JwMoX3SMfcl1/d2yorBRCYiL0Gdh D+wGnOYwIn3yhOodvxFQBNYTyBiGPSsZZOE2wrW0emrCnPOiO0n5/Q5Mwc+pkq2qqxIz GoEX6QAv8nltXtTJJ9J+Rl9qCLuK6FYigCZVQJRO4K5AQpWAXCJlEIbbz6CS02Ovbb87 u1/9H4zxwhqL12CeTTbdBU05GwDwklPVOaEfRgimsPJYwyA2kRI9LZx0ueQe2MNdJxhe qwDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IG2S0IJHtK1yhe2JNCNBtiyLUGz9p1p+4jsu2s1WXKc=; b=dwCAmjPb6wbUR+ylwOj6MfSVwrG8JpM3nHqQE1mHojGXdGPu62CBcGJA2RZp3JuBVy mRPxugakngnIeg1bodo8GDCaOaMWk+aLb5LBlZugaHMMUmKgPYq0Je52i6FgZRfJpo2l gn9aXYSi7ZjkFwsJotVzU1hT8qKZA8cBTYaOYAxzYsDU0fsYuqfrgA9HAINieDLeaIwf L3tX8lQkWnriklJxfJf46YGZOdd7Vjqde2/QC72XJCOuXOiNsK/CvOkbm2CqruEIuxC3 K/U8xH4MuxFrPPPbH3Zr+laBOMRA/nFmoK5l/7pPR6UwxB/k0rIP4h7ZvuEANUNMzeoe c51A== X-Gm-Message-State: AOAM531qBCg44hEXYukXR08pKOHT4AyQUnp7A7Jv/EBAW5hknSWc/8nL tCOL7XxVykel9XtcYFqqDwTGISiXtm4= X-Google-Smtp-Source: ABdhPJzMt9yVvv7b4rbymzS4rq3+kTyQ22Nn/90CbkcTFQe53yxOoM6ko0gQvG32zX4TaFGioitcoQ== X-Received: by 2002:aa7:d04d:0:b0:42a:acac:2cf7 with SMTP id n13-20020aa7d04d000000b0042aacac2cf7mr23362552edo.424.1653302584832; Mon, 23 May 2022 03:43:04 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:04 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 02/12] net: dsa: walk through all changeupper notifier functions Date: Mon, 23 May 2022 13:42:46 +0300 Message-Id: <20220523104256.3556016-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean Traditionally, DSA has had a single netdev notifier handling function for each device type. For the sake of code cleanliness, we would like to introduce more handling functions which do one thing, but the conditions for entering these functions start to overlap. Example: a handling function which tracks whether any bridges contain both DSA and non-DSA interfaces. Either this is placed before dsa_slave_changeupper(), case in which it will prevent that function from executing, or we place it after dsa_slave_changeupper(), case in which we will prevent it from executing. The other alternative is to ignore errors from the new handling function (not ideal). To support this usage, we need to change the pattern. In the new model, we enter all notifier handling sub-functions, and exit with NOTIFY_DONE if there is nothing to do. This allows the sub-functions to be relatively free-form and independent from each other. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- net/dsa/slave.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 17c7ec8b2245..8d62c634c331 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2452,6 +2452,9 @@ static int dsa_slave_changeupper(struct net_device *dev, struct netlink_ext_ack *extack; int err = NOTIFY_DONE; + if (!dsa_slave_dev_check(dev)) + return err; + extack = netdev_notifier_info_to_extack(&info->info); if (netif_is_bridge_master(info->upper_dev)) { @@ -2506,6 +2509,9 @@ static int dsa_slave_prechangeupper(struct net_device *dev, { struct dsa_port *dp = dsa_slave_to_port(dev); + if (!dsa_slave_dev_check(dev)) + return NOTIFY_DONE; + if (netif_is_bridge_master(info->upper_dev) && !info->linking) dsa_port_pre_bridge_leave(dp, info->upper_dev); else if (netif_is_lag_master(info->upper_dev) && !info->linking) @@ -2526,6 +2532,9 @@ dsa_slave_lag_changeupper(struct net_device *dev, int err = NOTIFY_DONE; struct dsa_port *dp; + if (!netif_is_lag_master(dev)) + return err; + netdev_for_each_lower_dev(dev, lower, iter) { if (!dsa_slave_dev_check(lower)) continue; @@ -2555,6 +2564,9 @@ dsa_slave_lag_prechangeupper(struct net_device *dev, int err = NOTIFY_DONE; struct dsa_port *dp; + if (!netif_is_lag_master(dev)) + return err; + netdev_for_each_lower_dev(dev, lower, iter) { if (!dsa_slave_dev_check(lower)) continue; @@ -2676,22 +2688,29 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, if (err != NOTIFY_DONE) return err; - if (dsa_slave_dev_check(dev)) - return dsa_slave_prechangeupper(dev, ptr); + err = dsa_slave_prechangeupper(dev, ptr); + if (notifier_to_errno(err)) + return err; - if (netif_is_lag_master(dev)) - return dsa_slave_lag_prechangeupper(dev, ptr); + err = dsa_slave_lag_prechangeupper(dev, ptr); + if (notifier_to_errno(err)) + return err; break; } - case NETDEV_CHANGEUPPER: - if (dsa_slave_dev_check(dev)) - return dsa_slave_changeupper(dev, ptr); + case NETDEV_CHANGEUPPER: { + int err; + + err = dsa_slave_changeupper(dev, ptr); + if (notifier_to_errno(err)) + return err; - if (netif_is_lag_master(dev)) - return dsa_slave_lag_changeupper(dev, ptr); + err = dsa_slave_lag_changeupper(dev, ptr); + if (notifier_to_errno(err)) + return err; break; + } case NETDEV_CHANGELOWERSTATE: { struct netdev_notifier_changelowerstate_info *info = ptr; struct dsa_port *dp; From patchwork Mon May 23 10:42:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858782 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CA38CC433EF for ; Mon, 23 May 2022 10:43:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234185AbiEWKn1 (ORCPT ); Mon, 23 May 2022 06:43:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53406 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234159AbiEWKnL (ORCPT ); Mon, 23 May 2022 06:43:11 -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 981CC15813 for ; Mon, 23 May 2022 03:43:09 -0700 (PDT) Received: by mail-ej1-x62d.google.com with SMTP id m20so27841498ejj.10 for ; Mon, 23 May 2022 03:43:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SA7kBUptP8owYsc/aym4C6KLeT4j+GV9lz0/ZYTVUvQ=; b=gsB/gfxA3ZZHAMA6Zpzh5QuZ4Sjr/R1YN0tXsyivGIVCHfiFO6sBn0htt/ugOVKXKV GRbS7esABsM3TXx/KRpYPoD092ZfkqaL38SW2dhP7xg8Ukhjy8X+QRxb65y5a5hAsqSp b9iod8EQfLcacWmpzinURdGemcv+wlUXkPPQvVVe23H2z6zf5kd/dMh6KpHXvux+Dw4h cQFidIl7gdyEWI6oHTfg/v9ZS4tgKe4pQiSsVAqfysk2KeI4MDlDRkZnqRzvzDtAkKC1 T/oVerFP1n0GGzyBPGnd3X+oj4ZM520BlINR3B+hvRH9yJ5bXs5yQluQ9dbk3ML81s+J ZVHw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SA7kBUptP8owYsc/aym4C6KLeT4j+GV9lz0/ZYTVUvQ=; b=bjacq5GUwi/Ro3T1P0YeEnMdx42UQiZjND0kHA0sk+wo9xTXxlS+II3wvzfFoAVo2Y TJUvd5UDRi8H20dymomb+GGCR8KDsrVKaiq3LoSvpMuQg/HySDqqL3CvgDCTmdYkV9sI WeNcLd+4vfXxGGe4HGVj39rB1hYiRnupXrQJ2raD+ejJZQMzjC/lagEY9f30Ek8nseFw 837rUdbDYEvICpp3tOidaIGL/zxvplZgmcYBIe2z8qPbwfc0mOzJjRpCMeR5soBJGlBX IH99agGNxgwaoJVzFUqlq7b9r/Ov02E7QqmE60Hj3nb9HjVnHhG3PsA2pfiUW0sja4ua Dl1g== X-Gm-Message-State: AOAM533bkIyJ9+LUzD9IgPGADkyf5yez1AEt7sW5Yjyc6rYDfK6Cvgtz 2Ez+aWbpYbx1DL1mT7Io1AFRlP4zdXg= X-Google-Smtp-Source: ABdhPJzgS6RYQOTX0AQzQsbFVb95dzMJUj7AEv5qUahGoMpTFDCxkMJiuyzV2fGZqF81dPPlaWIc5A== X-Received: by 2002:a17:906:544e:b0:6f3:bd59:1a93 with SMTP id d14-20020a170906544e00b006f3bd591a93mr18705421ejp.421.1653302587023; Mon, 23 May 2022 03:43:07 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:06 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 03/12] net: dsa: don't stop at NOTIFY_OK when calling ds->ops->port_prechangeupper Date: Mon, 23 May 2022 13:42:47 +0300 Message-Id: <20220523104256.3556016-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean dsa_slave_prechangeupper_sanity_check() is supposed to enforce some adjacency restrictions, and calls ds->ops->port_prechangeupper if the driver implements it. We convert the error code from the port_prechangeupper() call to a notifier code, and 0 is converted to NOTIFY_OK, but the caller of dsa_slave_prechangeupper_sanity_check() stops at any notifier code different from NOTIFY_DONE. Avoid this by converting back the notifier code to an error code, so that both NOTIFY_OK and NOTIFY_DONE will be seen as 0. This allows more parallel sanity check functions to be added. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- net/dsa/slave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 8d62c634c331..d8768e8f7862 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2685,7 +2685,7 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, int err; err = dsa_slave_prechangeupper_sanity_check(dev, info); - if (err != NOTIFY_DONE) + if (notifier_to_errno(err)) return err; err = dsa_slave_prechangeupper(dev, ptr); From patchwork Mon May 23 10:42:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858781 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DD19AC433F5 for ; Mon, 23 May 2022 10:43:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234182AbiEWKnZ (ORCPT ); Mon, 23 May 2022 06:43:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234146AbiEWKnX (ORCPT ); Mon, 23 May 2022 06:43:23 -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 3773F2458D for ; Mon, 23 May 2022 03:43:11 -0700 (PDT) Received: by mail-ej1-x636.google.com with SMTP id jx22so14424756ejb.12 for ; Mon, 23 May 2022 03:43:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8U0JbIv2eD/dHwgHzViQz0b6VPekMW4JDJchg5/en9Y=; b=FPrBsncOVKyAMz7yoch9GqLr3u5dCG2WqMf/bynwfa+VR4q8Ae1doMeEJ0NJFo8qk7 M3WjKBpoCqMLibPgUSt7L+WJf8pnCpHgpySSe63EwDNF4zcwMIvU5x00F4IYOlQka7D8 dlAj0lh109fIB6cQUI+V8MFlhqF9iiwyr6pMToO4D4+ncBoV/nQH/JC7i9douPrVdLBE Bp8/saPmrKm9N6eKv/fZdJ0MDx9XWTmR85kDPCodn7iZrqGmDzA59VK41QohO/2Rkao/ DYWvcsknFC+Yi9nfwdjudPRnkT6TvtM6oxBuIR6M3H9Db+hCj39+5y7Uzyd6ppOghm+Z xqXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8U0JbIv2eD/dHwgHzViQz0b6VPekMW4JDJchg5/en9Y=; b=3Cd0HTyNP/6lPf96cHWulHnxGKppojTHtCeoK1wJBPinZMhhK/NkR3sdsJGAN5Swpd nvH0XZ6+RjWoAFkNKVbmNuJo+yJe7EyIiA37t0FyHKZ9frcIkA67DFGvh7AS441bv2kD f8FPK/b1/HT7QqRWOYtEXbDiXN+sgRjxt+1uiWlL9kX6gKoVP68TFrAv4rlEFrTft7uD TR8tp54aN2hycJ0b0qQL345lQ0XRG1JEv7IZnparCNmOMoaHcsXFYOpnq3A66mMcLl2E 7waQY2/SzJtu/hrK63Sf/iIQcfmNcTBvEDM607riL10ky+8dm00EmgWrAchz5MqyeaHB sGvg== X-Gm-Message-State: AOAM53325rZL6NPDrzDdkzXSMxU49NES3req5urliDVkoQYLnzsz68o9 gsDEV2Vzc9rJP6yEmG+Ns8xiw5Y51mQ= X-Google-Smtp-Source: ABdhPJzVIIempDtEV13XMfGwjM23lb5ZJURZnuCpxs7Jn3y0PTu5tLcCwaYuPPl9fopDeLHk9TH19w== X-Received: by 2002:a17:907:62a9:b0:6da:7953:4df0 with SMTP id nd41-20020a17090762a900b006da79534df0mr18916117ejc.316.1653302588908; Mon, 23 May 2022 03:43:08 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:08 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 04/12] net: bridge: move DSA master bridging restriction to DSA Date: Mon, 23 May 2022 13:42:48 +0300 Message-Id: <20220523104256.3556016-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean When DSA gains support for multiple CPU ports in a LAG, it will become mandatory to monitor the changeupper events for the DSA master. In fact, there are already some restrictions to be imposed in that area, namely that a DSA master cannot be a bridge port except in some special circumstances. Centralize the restrictions at the level of the DSA layer as a preliminary step. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Acked-by: Nikolay Aleksandrov --- net/bridge/br_if.c | 20 -------------------- net/dsa/slave.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 47fcbade7389..916c051f0f0b 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -568,26 +568,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev, !is_valid_ether_addr(dev->dev_addr)) return -EINVAL; - /* Also don't allow bridging of net devices that are DSA masters, since - * the bridge layer rx_handler prevents the DSA fake ethertype handler - * to be invoked, so we don't get the chance to strip off and parse the - * DSA switch tag protocol header (the bridge layer just returns - * RX_HANDLER_CONSUMED, stopping RX processing for these frames). - * The only case where that would not be an issue is when bridging can - * already be offloaded, such as when the DSA master is itself a DSA - * or plain switchdev port, and is bridged only with other ports from - * the same hardware device. - */ - if (netdev_uses_dsa(dev)) { - list_for_each_entry(p, &br->port_list, list) { - if (!netdev_port_same_parent_id(dev, p->dev)) { - NL_SET_ERR_MSG(extack, - "Cannot do software bridging with a DSA master"); - return -EINVAL; - } - } - } - /* No bridging of bridges */ if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) { NL_SET_ERR_MSG(extack, diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d8768e8f7862..309d8dde0179 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2674,6 +2674,46 @@ dsa_slave_prechangeupper_sanity_check(struct net_device *dev, return NOTIFY_DONE; } +/* Don't allow bridging of DSA masters, since the bridge layer rx_handler + * prevents the DSA fake ethertype handler to be invoked, so we don't get the + * chance to strip off and parse the DSA switch tag protocol header (the bridge + * layer just returns RX_HANDLER_CONSUMED, stopping RX processing for these + * frames). + * The only case where that would not be an issue is when bridging can already + * be offloaded, such as when the DSA master is itself a DSA or plain switchdev + * port, and is bridged only with other ports from the same hardware device. + */ +static int +dsa_bridge_prechangelower_sanity_check(struct net_device *new_lower, + struct netdev_notifier_changeupper_info *info) +{ + struct net_device *br = info->upper_dev; + struct netlink_ext_ack *extack; + struct net_device *lower; + struct list_head *iter; + + if (!netif_is_bridge_master(br)) + return NOTIFY_DONE; + + if (!info->linking) + return NOTIFY_DONE; + + extack = netdev_notifier_info_to_extack(&info->info); + + netdev_for_each_lower_dev(br, lower, iter) { + if (!netdev_uses_dsa(new_lower) && !netdev_uses_dsa(lower)) + continue; + + if (!netdev_port_same_parent_id(lower, new_lower)) { + NL_SET_ERR_MSG(extack, + "Cannot do software bridging with a DSA master"); + return notifier_from_errno(-EINVAL); + } + } + + return NOTIFY_DONE; +} + static int dsa_slave_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -2688,6 +2728,10 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, if (notifier_to_errno(err)) return err; + err = dsa_bridge_prechangelower_sanity_check(dev, info); + if (notifier_to_errno(err)) + return err; + err = dsa_slave_prechangeupper(dev, ptr); if (notifier_to_errno(err)) return err; From patchwork Mon May 23 10:42:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858783 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C3C5C433EF for ; Mon, 23 May 2022 10:43:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234209AbiEWKnc (ORCPT ); Mon, 23 May 2022 06:43:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234206AbiEWKnY (ORCPT ); Mon, 23 May 2022 06:43:24 -0400 Received: from mail-ej1-x630.google.com (mail-ej1-x630.google.com [IPv6:2a00:1450:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBC31245A7 for ; Mon, 23 May 2022 03:43:12 -0700 (PDT) Received: by mail-ej1-x630.google.com with SMTP id m20so27841795ejj.10 for ; Mon, 23 May 2022 03:43:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=icSnCHuOPlD4V5+tswNuOL7gl86u5U7QFKaufHVUslg=; b=QgAO1M+XVOzLeIe9o1Qi0pLPfPLV+5+7mgrIp8C3XgFXRjmXU3lLaRgNyS9pZorrFo HmWrRP9AIVRW8/WKbU5kgE/z2U/1LylgMzR+uMruUPaMSZExsmsw7IR9Bbe97tE5Y5bk yjsAuTBBx/QCFzPg4WmOZX7VVh0fUY5agQFfUbfeCL7fn7qsTQpNUdv4VGlSjCcR1M6K xeNbPFoaUyT85h6kDCB6zubq7ZDp0B89iBfDpPaAHG/euId9L1gJKsZJ2WtcAr1w5ODS WZdPuNKI2BCX9CjDD6ZhMNYuj5Vv0FtKaeXWBDj4esVWY6pOVJh/ZD06V35kdgW1s0Hu CWMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=icSnCHuOPlD4V5+tswNuOL7gl86u5U7QFKaufHVUslg=; b=1T+4ZEJ+waOxYtJ3VDIaJzmIpJlTSXFoj7UCoJfcFYvhcErhqIe1b+zf+LdhwqUGDW yoe+Nf/FnWyZQ+i/lsJYbq3d3m0lIy2sJKs4WFbzR6PHUdf+mCt/QIghhzkHifapnm/0 2aR94vlkbygTj8BtVf1SipSxTlM9zwgI6WNtHQSGvzoGzK4ezcgoN5S6CYpOAHXPD/St YyW/fPb07W6m0xxNedyJkvnan8jvngBes2UWu2S3/zYU8XlRez2c23Y1829CCBE8cMsr dVXgzIIwsklkHVmtQwYxzoLZvWpC6vaZgyv7L0te0NuBkL7aBWjmLC0/htJ8EIrvlsbu HdLw== X-Gm-Message-State: AOAM530oD2hVL+Udy6NwDN7lSY4trEkXGgGqk68VK+xL5wfTs3ctu3ff EeDRbHQG0eUYLPKnWKv2hptOeaI9e5w= X-Google-Smtp-Source: ABdhPJyf9EqB4KV/W3UYWxqrgeamy1EqOk1XUWRra2baxk8eTR2h6Dy69M2dpTTLD7tdm20rqjkRFg== X-Received: by 2002:a17:907:9490:b0:6fe:a4bc:b71e with SMTP id dm16-20020a170907949000b006fea4bcb71emr14120492ejc.39.1653302590862; Mon, 23 May 2022 03:43:10 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:10 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 05/12] net: dsa: existing DSA masters cannot join upper interfaces Date: Mon, 23 May 2022 13:42:49 +0300 Message-Id: <20220523104256.3556016-6-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean All the traffic to/from a DSA master is supposed to be distributed among its DSA switch upper interfaces, so we should not allow other upper device kinds. An exception to this is DSA_TAG_PROTO_NONE (switches with no DSA tags), and in that case it is actually expected to create e.g. VLAN interfaces on the master. But for those, netdev_uses_dsa(master) returns false, so the restriction doesn't apply. The motivation for this change is to allow LAG interfaces of DSA masters to be DSA masters themselves. We want to restrict the user's degrees of freedom by 1: the LAG should already have all DSA masters as lowers, and while lower ports of the LAG can be removed, none can be added after the fact. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- net/dsa/slave.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 309d8dde0179..0455fb3cf03d 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2674,6 +2674,35 @@ dsa_slave_prechangeupper_sanity_check(struct net_device *dev, return NOTIFY_DONE; } +static int +dsa_master_prechangeupper_sanity_check(struct net_device *master, + struct netdev_notifier_changeupper_info *info) +{ + struct netlink_ext_ack *extack; + + if (!netdev_uses_dsa(master)) + return NOTIFY_DONE; + + if (!info->linking) + return NOTIFY_DONE; + + /* Allow DSA switch uppers */ + if (dsa_slave_dev_check(info->upper_dev)) + return NOTIFY_DONE; + + /* Allow bridge uppers of DSA masters, subject to further + * restrictions in dsa_bridge_prechangelower_sanity_check() + */ + if (netif_is_bridge_master(info->upper_dev)) + return NOTIFY_DONE; + + extack = netdev_notifier_info_to_extack(&info->info); + + NL_SET_ERR_MSG_MOD(extack, + "DSA master cannot join unknown upper interfaces"); + return notifier_from_errno(-EBUSY); +} + /* Don't allow bridging of DSA masters, since the bridge layer rx_handler * prevents the DSA fake ethertype handler to be invoked, so we don't get the * chance to strip off and parse the DSA switch tag protocol header (the bridge @@ -2728,6 +2757,10 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, if (notifier_to_errno(err)) return err; + err = dsa_master_prechangeupper_sanity_check(dev, info); + if (notifier_to_errno(err)) + return err; + err = dsa_bridge_prechangelower_sanity_check(dev, info); if (notifier_to_errno(err)) return err; From patchwork Mon May 23 10:42:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858784 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 31E83C433EF for ; Mon, 23 May 2022 10:43:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234217AbiEWKne (ORCPT ); Mon, 23 May 2022 06:43:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53356 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234225AbiEWKnY (ORCPT ); Mon, 23 May 2022 06:43:24 -0400 Received: from mail-ej1-x62e.google.com (mail-ej1-x62e.google.com [IPv6:2a00:1450:4864:20::62e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA1CCFC7 for ; Mon, 23 May 2022 03:43:14 -0700 (PDT) Received: by mail-ej1-x62e.google.com with SMTP id rs12so16136186ejb.13 for ; Mon, 23 May 2022 03:43:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9b8E4PRx8BrnW1sgEjVk4LHh4D9piAhyes9wV5gbLT4=; b=ITmwBszaldoMBsXIkHaKjCYbI4aP3VzacNm61DWwP+w+VkM3fMDGk9tgFPe7zfj4/M dMrXza430//ZsnWf4/jgUL7DNMSQ7hnkMUtRpltgaA3j216Pw76L3VYxQPCRTdMRPn8E L96rKV4aN4r+lA5TWTqRgPQvAg9Rpl+hotLbbK8dD+wVDrmTKmPRjgA/GUgKMMmwg+jg ZzOAx47rd4B77Y5h906GKtaGyb+HAMztWjrn/lP5ri/Z5v/wbtO9q7fJXEWHT6uXRTgJ lYda7E1uoGRTVpjvOZIEWFkHW2+u5vWrWnE36J14GbAZDnso8BwgntybDJvA3GrcI4nK iXmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9b8E4PRx8BrnW1sgEjVk4LHh4D9piAhyes9wV5gbLT4=; b=dUnKDsHVL8e9xJYEOWfZL8WWvSPxVjFk+ZwS0MxXUOeUngEZ4fsGXrFHRHiLxcHP2c k9wg2VyjBi+dpkOk739BxbZo5bzruWMFQTRBXWXkiQORSYLK5FcLrcMUy17F/C2qJ2FB +nQFNCPQvb7gzce7QGj2CZSu/mDKQMl0hcjCindZiUmKNP/IEaJwibTWvjDu0lMkpphn cw4lUi4ArJeEXOE20Zzq5Iq5/8hynUX7ZDMTwPqOd1MnZI+K/pw4LoWfSUPN2/WKbvZZ Ejfcsu7+p1jz3F8rFjwi4OYC8IQLq9QwAsoqHWf4REcseL8dpu8CHo3aMBC83shWv960 xZ9Q== X-Gm-Message-State: AOAM532PgUrj/zp+qWjDTgfRIFZbaLQjLNGsHZWMGk+MdlhgqjUktkY3 8lZVTpKrZaOqERLVIgA3BQDkxcF3Amg= X-Google-Smtp-Source: ABdhPJyorbpDeYvxLfO1inJDQwxtC9mUgtncwQMjN6MSnX3rv9pgZ9zytBwDTyE6JMJQNTQvwvBtyA== X-Received: by 2002:a17:906:4b55:b0:6fe:c52c:68c9 with SMTP id j21-20020a1709064b5500b006fec52c68c9mr7274113ejv.491.1653302592700; Mon, 23 May 2022 03:43:12 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:12 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 06/12] net: dsa: only bring down user ports assigned to a given DSA master Date: Mon, 23 May 2022 13:42:50 +0300 Message-Id: <20220523104256.3556016-7-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean This is an adaptation of commit c0a8a9c27493 ("net: dsa: automatically bring user ports down when master goes down") for multiple DSA masters. When a DSA master goes down, only the user ports under its control should go down too, the others can still send/receive traffic. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- net/dsa/slave.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 0455fb3cf03d..c0be747c66ac 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2848,6 +2848,9 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, if (!dsa_port_is_user(dp)) continue; + if (dp->cpu_dp != cpu_dp) + continue; + list_add(&dp->slave->close_list, &close_list); } From patchwork Mon May 23 10:42:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858785 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CE73C433EF for ; Mon, 23 May 2022 10:43:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234187AbiEWKno (ORCPT ); Mon, 23 May 2022 06:43:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54152 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234240AbiEWKnY (ORCPT ); Mon, 23 May 2022 06:43:24 -0400 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BB0749F11 for ; Mon, 23 May 2022 03:43:15 -0700 (PDT) Received: by mail-ej1-x62b.google.com with SMTP id f9so27956400ejc.0 for ; Mon, 23 May 2022 03:43:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=50niX/FM4H+njvGscV8qhuvnFKUkuRbOE6cNDO+7lms=; b=Y+dk4ydtwlOWmKVU9EFl01/ndztmUGbKsYKIWX5bHhvWYgUvPjDcAdN5S+1/Z4nobv 3YSz5OVyS/IDuIWc6bvKC7ay/3xwJB1futK5ID7XICecNhKi16011evZ7eAtNfDjrdrg lwbaUwVzqgXtJZgEf3ia1iqBSGyxx80DKRd+iZnzRLyb7W/ye7/rEdcok3a6LtppvxVR 6gaDL/jIiOMvK0V2EI4v69ZeL5BtsORAU3OE6tFDLrZeJbouDjVotuKE3H+0832NnnqV 2whxzoU/t/G0IY8ueWV/I2gncrg4SIgxrdlmzyEOPvBiJtHrKnSltEQjBd/YrxAWqVHv JBYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=50niX/FM4H+njvGscV8qhuvnFKUkuRbOE6cNDO+7lms=; b=ZbI4s8VkNE+LMT5hosA3ituBGmwWMrje5b688mWfKDzAheklZWNn+elhAiO3pNfvEW 4Si5yoOR6mT+hMNMcxn0FbSih97GLpLUibqJhJUAXj53IwvzZxWvk+U+dgjxr3i15co1 opfbgOkxDxH45g6RW9KbWKC6SZSNI92b0wEmD9e7EC14cKS4RBOUN92ZWnokY3MpMXGs ZRqdn5FlGKHlRwrevL7qjPVvkCvW/50vBDXPPYgL003XJo3XDCfYsTtb0k+fEAh7wxCV vSacGfQMoNyxCnqVgQmpyBAFUZnuEYxQDs8paKJqNRbmLs9EBrO2nJZsk53NVZ+2j8HO xUGg== X-Gm-Message-State: AOAM532ifjocRypSi4Q7+Xz+ZS38Uo26ICzRtn8OKxV5/rSgtyDSeXEK 08k9YIFq12G8P4BcUmS8Ircg68aKIUk= X-Google-Smtp-Source: ABdhPJzDGCsHfdOeTPzHSzrdo1GJt2lJYWBK6tpAWa8XhIdQHgAWgHEq8dvTswB3CZENEqEAKF4d8w== X-Received: by 2002:a17:906:f24f:b0:6fe:9b70:6d63 with SMTP id gy15-20020a170906f24f00b006fe9b706d63mr17634645ejb.255.1653302594684; Mon, 23 May 2022 03:43:14 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:13 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 07/12] net: dsa: all DSA masters must be down when changing the tagging protocol Date: Mon, 23 May 2022 13:42:51 +0300 Message-Id: <20220523104256.3556016-8-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean The fact that the tagging protocol is set and queried from the /sys/class/net//dsa/tagging file is a bit of a quirk from the single CPU port days which isn't aging very well now that DSA can have more than a single CPU port. This is because the tagging protocol is a switch property, yet in the presence of multiple CPU ports it can be queried and set from multiple sysfs files, all of which are handled by the same implementation. The current logic ensures that the net device whose sysfs file we're changing the tagging protocol through must be down. That net device is the DSA master, and this is fine for single DSA master / CPU port setups. But exactly because the tagging protocol is per switch [ tree, in fact ] and not per DSA master, this isn't fine any longer with multiple CPU ports, and we must iterate through the tree and find all DSA masters, and make sure that all of them are down. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- net/dsa/dsa2.c | 10 +++------- net/dsa/dsa_priv.h | 1 - net/dsa/master.c | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index ec0df4e498d6..4f0042339d4f 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -1235,7 +1235,6 @@ static int dsa_tree_bind_tag_proto(struct dsa_switch_tree *dst, * they would have formed disjoint trees (different "dsa,member" values). */ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, - struct net_device *master, const struct dsa_device_ops *tag_ops, const struct dsa_device_ops *old_tag_ops) { @@ -1251,14 +1250,11 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, * attempts to change the tagging protocol. If we ever lift the IFF_UP * restriction, there needs to be another mutex which serializes this. */ - if (master->flags & IFF_UP) - goto out_unlock; - list_for_each_entry(dp, &dst->ports, list) { - if (!dsa_port_is_user(dp)) - continue; + if (dsa_port_is_cpu(dp) && (dp->master->flags & IFF_UP)) + goto out_unlock; - if (dp->slave->flags & IFF_UP) + if (dsa_port_is_user(dp) && (dp->slave->flags & IFF_UP)) goto out_unlock; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index d9722e49864b..cc1cc866dc42 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -545,7 +545,6 @@ struct dsa_lag *dsa_tree_lag_find(struct dsa_switch_tree *dst, int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v); int dsa_broadcast(unsigned long e, void *v); int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, - struct net_device *master, const struct dsa_device_ops *tag_ops, const struct dsa_device_ops *old_tag_ops); void dsa_tree_master_admin_state_change(struct dsa_switch_tree *dst, diff --git a/net/dsa/master.c b/net/dsa/master.c index 2851e44c4cf0..32c0a00a8b92 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -307,7 +307,7 @@ static ssize_t tagging_store(struct device *d, struct device_attribute *attr, */ goto out; - err = dsa_tree_change_tag_proto(cpu_dp->ds->dst, dev, new_tag_ops, + err = dsa_tree_change_tag_proto(cpu_dp->ds->dst, new_tag_ops, old_tag_ops); if (err) { /* On failure the old tagger is restored, so we don't need the From patchwork Mon May 23 10:42:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858786 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D98A8C433FE for ; Mon, 23 May 2022 10:43:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234208AbiEWKnq (ORCPT ); Mon, 23 May 2022 06:43:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234183AbiEWKnY (ORCPT ); Mon, 23 May 2022 06:43:24 -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 523022BD6 for ; Mon, 23 May 2022 03:43:18 -0700 (PDT) Received: by mail-ej1-x62d.google.com with SMTP id y13so27139744eje.2 for ; Mon, 23 May 2022 03:43:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lk4CKsVvL554+L9fQG+qTH0J4TsxGfQO7J7jsNhiAjc=; b=Dg6bulwu1nrikxDun85V5sdoDDHbkXYoFb5WINlSG0Ufwrum5pC1cZO2/Tn0+xV9RV h/wqE2y0ifEs3defl34ylkub1TOSqTWs7bK/jF03n6yzPUp3NYyFXB8HaLi9Z1XZw++9 nBkqc13JBeKDBNPoFeUlR7x7nWuYvTxY6VAyKp8SkPjEQQ/QoRgZwIRSPxzNavE4dlty epb7vTP6hcL5jnMQ5CkLwSWTQz6XSrDDdg3SUWpzkJBxNI5+QSvR9WMOylOLOQiigEPr cYdyeXeIvTdLKuX92AoNR3WvKQprBFHqruTFdmQgxpNJnZT4ioSAsEECKmB3xU1dxSET lJ5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lk4CKsVvL554+L9fQG+qTH0J4TsxGfQO7J7jsNhiAjc=; b=ESQPJCC1RXSEzgVAzgdPDtFjsczu/u4FxlEc+MCQQ+mp9vn+2STkyTKAPn+O8+OwWT OZMhpLqeqgvG4G/DwAmwrC3UMkl0wUoZ1goD1la2mdq5jXF1pBwONc5bmIhgEZeS+f57 gfMEABuM6QhGLUPIYqIBrOyVNXYkPujF+XbsSSA6nLxJqRtgJcD9n8fJuaEWJo05wvNC ylofN/lWTXLTXZXhYR7cQDqsb4AHumKcWl26R0/PiKeMnpQ8JsnJkwDJMShZPq5bUlmj 2ApPZt/HIGgGSkBBcN8VdeyMWrx6o1AIwYbdGWaRE+h6NZGp2rOBTVViynALAPvDf9HL BUUA== X-Gm-Message-State: AOAM5328cKfVIbL2k74MLor5vLSbyFgJdiXk0cO5RsI5Eh07dMjzuLjK 01UGwhJfYXfsu/oo//Ok07i5lL0TzV8= X-Google-Smtp-Source: ABdhPJw1Uj320czDjbKI1lh3+C9TFhTXSx7sDx0nyMBY/QZgUQkEZDd1+Vk+xQbVK3snI+JxhgM9Jg== X-Received: by 2002:a17:907:7f19:b0:6fe:ce26:8f0d with SMTP id qf25-20020a1709077f1900b006fece268f0dmr5448261ejc.27.1653302597032; Mon, 23 May 2022 03:43:17 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:15 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 08/12] net: dsa: use dsa_tree_for_each_cpu_port in dsa_tree_{setup,teardown}_master Date: Mon, 23 May 2022 13:42:52 +0300 Message-Id: <20220523104256.3556016-9-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean More logic will be added to dsa_tree_setup_master() and dsa_tree_teardown_master() in upcoming changes. Reduce the indentation by one level in these functions by introducing and using a dedicated iterator for CPU ports of a tree. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- include/net/dsa.h | 4 ++++ net/dsa/dsa2.c | 46 +++++++++++++++++++++------------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 14f07275852b..ad345fa17297 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -555,6 +555,10 @@ static inline bool dsa_is_user_port(struct dsa_switch *ds, int p) list_for_each_entry((_dp), &(_dst)->ports, list) \ if (dsa_port_is_user((_dp))) +#define dsa_tree_for_each_cpu_port(_dp, _dst) \ + list_for_each_entry((_dp), &(_dst)->ports, list) \ + if (dsa_port_is_cpu((_dp))) + #define dsa_switch_for_each_port(_dp, _ds) \ list_for_each_entry((_dp), &(_ds)->dst->ports, list) \ if ((_dp)->ds == (_ds)) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 4f0042339d4f..74167bf0fbe5 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -1043,26 +1043,24 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) static int dsa_tree_setup_master(struct dsa_switch_tree *dst) { - struct dsa_port *dp; + struct dsa_port *cpu_dp; int err = 0; rtnl_lock(); - list_for_each_entry(dp, &dst->ports, list) { - if (dsa_port_is_cpu(dp)) { - struct net_device *master = dp->master; - bool admin_up = (master->flags & IFF_UP) && - !qdisc_tx_is_noop(master); + dsa_tree_for_each_cpu_port(cpu_dp, dst) { + struct net_device *master = cpu_dp->master; + bool admin_up = (master->flags & IFF_UP) && + !qdisc_tx_is_noop(master); - err = dsa_master_setup(master, dp); - if (err) - break; + err = dsa_master_setup(master, cpu_dp); + if (err) + break; - /* Replay master state event */ - dsa_tree_master_admin_state_change(dst, master, admin_up); - dsa_tree_master_oper_state_change(dst, master, - netif_oper_up(master)); - } + /* Replay master state event */ + dsa_tree_master_admin_state_change(dst, master, admin_up); + dsa_tree_master_oper_state_change(dst, master, + netif_oper_up(master)); } rtnl_unlock(); @@ -1072,22 +1070,20 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) static void dsa_tree_teardown_master(struct dsa_switch_tree *dst) { - struct dsa_port *dp; + struct dsa_port *cpu_dp; rtnl_lock(); - list_for_each_entry(dp, &dst->ports, list) { - if (dsa_port_is_cpu(dp)) { - struct net_device *master = dp->master; + dsa_tree_for_each_cpu_port(cpu_dp, dst) { + struct net_device *master = cpu_dp->master; - /* Synthesizing an "admin down" state is sufficient for - * the switches to get a notification if the master is - * currently up and running. - */ - dsa_tree_master_admin_state_change(dst, master, false); + /* Synthesizing an "admin down" state is sufficient for + * the switches to get a notification if the master is + * currently up and running. + */ + dsa_tree_master_admin_state_change(dst, master, false); - dsa_master_teardown(master); - } + dsa_master_teardown(master); } rtnl_unlock(); From patchwork Mon May 23 10:42:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858787 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6EBCBC433F5 for ; Mon, 23 May 2022 10:43:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234189AbiEWKnr (ORCPT ); Mon, 23 May 2022 06:43:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234256AbiEWKnZ (ORCPT ); Mon, 23 May 2022 06:43:25 -0400 Received: from mail-ej1-x631.google.com (mail-ej1-x631.google.com [IPv6:2a00:1450:4864:20::631]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 621BE3150D for ; Mon, 23 May 2022 03:43:21 -0700 (PDT) Received: by mail-ej1-x631.google.com with SMTP id wh22so27739825ejb.7 for ; Mon, 23 May 2022 03:43:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=T12dTiKTwaKzbwS7CxIAt6TR3zoC9o8zO5xudjwnx/g=; b=XVAqnC8jAKHOoTvoaehLaHSNt8+dAyKUY1o1BVux/9NyZzdvh2k+FXkpU5oFzFcrUy JMQr8dgBvBpvJY1x4RR3gncoGKOBdIGI2QPPCNQ9Kj+LxhlqIR0ktQbcTL4X67jieIXu NkzHSA/Ienwzfy4C1xTia+zs3WvP8e5HV5KMN+izyD0e+sVwKBZqGRc/rQxX1ZRp/avk d02/NQ1XA0AOnc68tHsCsrFQqN/knfjXhf2mXv3IxD/rlzkW1uTBjSZ6WtbxIIjKdIwV WAGaFjC+IEtSMICL1mHkECb3Zj2PtOHs60nG1liHuJ1LsepHMEkMsUg+2BMovhvG27xL DauA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=T12dTiKTwaKzbwS7CxIAt6TR3zoC9o8zO5xudjwnx/g=; b=46pZ2r8agTfdZeYt/9eqBKiFWwwc9dznlXig3sOxMQ3DXQkMfAqs0+EgLepkDOV5oP TRJqcvYFBagTuWNXKlPK+opg80cY3MtUfzBD6b4usQHxTgANN5JjkTclFdAFFWQA3Bo8 t9O1xFyHjFqxfielkqQIhAUyVKTnDni1k8w/3enl6d8v/xasKY4iXbejP700DPrzvqXM ghHYs+Sjcryq2fHA+cVO0xL4P7QpcOkFBDjGu00Cm2DiiLjgT7YiM8ob1WoDl6lTiq38 YIdo4SGuxSpNvBgNh2L8pI42XP1mCJz26/McjuS0KkcTo4niNETR0WkTX19Cts16IyGE tpVA== X-Gm-Message-State: AOAM532XQoY+eM1v8XPAQFj7p6FfFcA1ABQkyzPBe6SD54LWCmkG/XTo 7PDEEuXqQwRtD7QYOw3zbtZEHgK8XWk= X-Google-Smtp-Source: ABdhPJwz3dTBRCDXz+ybBlW+dhvJDL1K1b2moGZzs3BT6/GODw5MtO7qmw2kNpgefeVlLmht3NBH/A== X-Received: by 2002:a17:907:1b25:b0:6da:8206:fc56 with SMTP id mp37-20020a1709071b2500b006da8206fc56mr18424228ejc.81.1653302599341; Mon, 23 May 2022 03:43:19 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:18 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 09/12] net: dsa: introduce dsa_port_get_master() Date: Mon, 23 May 2022 13:42:53 +0300 Message-Id: <20220523104256.3556016-10-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean There is a desire to support for DSA masters in a LAG. That configuration is intended to work by simply enslaving the master to a bonding/team device. But the physical DSA master (the LAG slave) still has a dev->dsa_ptr, and that cpu_dp still corresponds to the physical CPU port. However, we would like to be able to retrieve the LAG that's the upper of the physical DSA master. In preparation for that, introduce a helper called dsa_port_get_master() that replaces all occurrences of the dp->cpu_dp->master pattern. The distinction between LAG and non-LAG will be made later within the helper itself. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- drivers/net/dsa/bcm_sf2.c | 4 +-- drivers/net/dsa/bcm_sf2_cfp.c | 4 +-- drivers/net/dsa/lan9303-core.c | 4 +-- .../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +- include/net/dsa.h | 5 ++++ net/dsa/dsa2.c | 8 +++--- net/dsa/dsa_priv.h | 2 +- net/dsa/port.c | 28 +++++++++---------- net/dsa/slave.c | 11 ++++---- net/dsa/tag_8021q.c | 4 +-- 10 files changed, 38 insertions(+), 34 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 87e81c636339..4551528d822c 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -982,7 +982,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port, struct ethtool_wolinfo *wol) { - struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master; + struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port)); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); struct ethtool_wolinfo pwol = { }; @@ -1006,7 +1006,7 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port, static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port, struct ethtool_wolinfo *wol) { - struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master; + struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port)); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index; struct ethtool_wolinfo pwol = { }; diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c index edbe5e7f1cb6..90636ae3db98 100644 --- a/drivers/net/dsa/bcm_sf2_cfp.c +++ b/drivers/net/dsa/bcm_sf2_cfp.c @@ -1102,7 +1102,7 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv, int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port, struct ethtool_rxnfc *nfc, u32 *rule_locs) { - struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master; + struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port)); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); int ret = 0; @@ -1145,7 +1145,7 @@ int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port, int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port, struct ethtool_rxnfc *nfc) { - struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master; + struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port)); struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); int ret = 0; diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index e03ff1f267bb..181e082b0919 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1090,7 +1090,7 @@ static int lan9303_port_enable(struct dsa_switch *ds, int port, if (!dsa_port_is_user(dp)) return 0; - vlan_vid_add(dp->cpu_dp->master, htons(ETH_P_8021Q), port); + vlan_vid_add(dsa_port_to_master(dp), htons(ETH_P_8021Q), port); return lan9303_enable_processing_port(chip, port); } @@ -1103,7 +1103,7 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port) if (!dsa_port_is_user(dp)) return; - vlan_vid_del(dp->cpu_dp->master, htons(ETH_P_8021Q), port); + vlan_vid_del(dsa_port_to_master(dp), htons(ETH_P_8021Q), port); lan9303_disable_processing_port(chip, port); lan9303_phy_write(ds, chip->phy_addr_base + port, MII_BMCR, BMCR_PDOWN); diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c index c9353071f96a..632af8c97043 100644 --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c @@ -174,7 +174,7 @@ mtk_flow_get_dsa_port(struct net_device **dev) if (dp->cpu_dp->tag_ops->proto != DSA_TAG_PROTO_MTK) return -ENODEV; - *dev = dp->cpu_dp->master; + *dev = dsa_port_to_master(dp); return dp->index; #else diff --git a/include/net/dsa.h b/include/net/dsa.h index ad345fa17297..7f6ca944c092 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -714,6 +714,11 @@ static inline bool dsa_port_offloads_lag(struct dsa_port *dp, return dsa_port_lag_dev_get(dp) == lag->dev; } +static inline struct net_device *dsa_port_to_master(const struct dsa_port *dp) +{ + return dp->cpu_dp->master; +} + static inline struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp) { diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 74167bf0fbe5..8ff5467ac3e2 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -1246,11 +1246,11 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, * attempts to change the tagging protocol. If we ever lift the IFF_UP * restriction, there needs to be another mutex which serializes this. */ - list_for_each_entry(dp, &dst->ports, list) { - if (dsa_port_is_cpu(dp) && (dp->master->flags & IFF_UP)) + dsa_tree_for_each_user_port(dp, dst) { + if (dsa_port_to_master(dp)->flags & IFF_UP) goto out_unlock; - if (dsa_port_is_user(dp) && (dp->slave->flags & IFF_UP)) + if (dp->slave->flags & IFF_UP) goto out_unlock; } @@ -1780,7 +1780,7 @@ void dsa_switch_shutdown(struct dsa_switch *ds) rtnl_lock(); dsa_switch_for_each_user_port(dp, ds) { - master = dp->cpu_dp->master; + master = dsa_port_to_master(dp); slave_dev = dp->slave; netdev_upper_dev_unlink(master, slave_dev); diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index cc1cc866dc42..f3562cef32ad 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -322,7 +322,7 @@ dsa_slave_to_master(const struct net_device *dev) { struct dsa_port *dp = dsa_slave_to_port(dev); - return dp->cpu_dp->master; + return dsa_port_to_master(dp); } /* If under a bridge with vlan_filtering=0, make sure to send pvid-tagged diff --git a/net/dsa/port.c b/net/dsa/port.c index 85cac22cb056..8557217ed5de 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -1022,7 +1022,7 @@ int dsa_port_standalone_host_fdb_add(struct dsa_port *dp, int dsa_port_bridge_host_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid) { - struct dsa_port *cpu_dp = dp->cpu_dp; + struct net_device *master = dsa_port_to_master(dp); struct dsa_db db = { .type = DSA_DB_BRIDGE, .bridge = *dp->bridge, @@ -1033,8 +1033,8 @@ int dsa_port_bridge_host_fdb_add(struct dsa_port *dp, * requires rtnl_lock(), since we can't guarantee that is held here, * and we can't take it either. */ - if (cpu_dp->master->priv_flags & IFF_UNICAST_FLT) { - err = dev_uc_add(cpu_dp->master, addr); + if (master->priv_flags & IFF_UNICAST_FLT) { + err = dev_uc_add(master, addr); if (err) return err; } @@ -1073,15 +1073,15 @@ int dsa_port_standalone_host_fdb_del(struct dsa_port *dp, int dsa_port_bridge_host_fdb_del(struct dsa_port *dp, const unsigned char *addr, u16 vid) { - struct dsa_port *cpu_dp = dp->cpu_dp; + struct net_device *master = dsa_port_to_master(dp); struct dsa_db db = { .type = DSA_DB_BRIDGE, .bridge = *dp->bridge, }; int err; - if (cpu_dp->master->priv_flags & IFF_UNICAST_FLT) { - err = dev_uc_del(cpu_dp->master, addr); + if (master->priv_flags & IFF_UNICAST_FLT) { + err = dev_uc_del(master, addr); if (err) return err; } @@ -1204,14 +1204,14 @@ int dsa_port_standalone_host_mdb_add(const struct dsa_port *dp, int dsa_port_bridge_host_mdb_add(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb) { - struct dsa_port *cpu_dp = dp->cpu_dp; + struct net_device *master = dsa_port_to_master(dp); struct dsa_db db = { .type = DSA_DB_BRIDGE, .bridge = *dp->bridge, }; int err; - err = dev_mc_add(cpu_dp->master, mdb->addr); + err = dev_mc_add(master, mdb->addr); if (err) return err; @@ -1248,14 +1248,14 @@ int dsa_port_standalone_host_mdb_del(const struct dsa_port *dp, int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb) { - struct dsa_port *cpu_dp = dp->cpu_dp; + struct net_device *master = dsa_port_to_master(dp); struct dsa_db db = { .type = DSA_DB_BRIDGE, .bridge = *dp->bridge, }; int err; - err = dev_mc_del(cpu_dp->master, mdb->addr); + err = dev_mc_del(master, mdb->addr); if (err) return err; @@ -1290,19 +1290,19 @@ int dsa_port_host_vlan_add(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan, struct netlink_ext_ack *extack) { + struct net_device *master = dsa_port_to_master(dp); struct dsa_notifier_vlan_info info = { .dp = dp, .vlan = vlan, .extack = extack, }; - struct dsa_port *cpu_dp = dp->cpu_dp; int err; err = dsa_port_notify(dp, DSA_NOTIFIER_HOST_VLAN_ADD, &info); if (err && err != -EOPNOTSUPP) return err; - vlan_vid_add(cpu_dp->master, htons(ETH_P_8021Q), vlan->vid); + vlan_vid_add(master, htons(ETH_P_8021Q), vlan->vid); return err; } @@ -1310,18 +1310,18 @@ int dsa_port_host_vlan_add(struct dsa_port *dp, int dsa_port_host_vlan_del(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan) { + struct net_device *master = dsa_port_to_master(dp); struct dsa_notifier_vlan_info info = { .dp = dp, .vlan = vlan, }; - struct dsa_port *cpu_dp = dp->cpu_dp; int err; err = dsa_port_notify(dp, DSA_NOTIFIER_HOST_VLAN_DEL, &info); if (err && err != -EOPNOTSUPP) return err; - vlan_vid_del(cpu_dp->master, htons(ETH_P_8021Q), vlan->vid); + vlan_vid_del(master, htons(ETH_P_8021Q), vlan->vid); return err; } diff --git a/net/dsa/slave.c b/net/dsa/slave.c index c0be747c66ac..0d0deca99eba 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1481,8 +1481,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev, static int dsa_slave_setup_ft_block(struct dsa_switch *ds, int port, void *type_data) { - struct dsa_port *cpu_dp = dsa_to_port(ds, port)->cpu_dp; - struct net_device *master = cpu_dp->master; + struct net_device *master = dsa_port_to_master(dsa_to_port(ds, port)); if (!master->netdev_ops->ndo_setup_tc) return -EOPNOTSUPP; @@ -2123,13 +2122,14 @@ static int dsa_slave_fill_forward_path(struct net_device_path_ctx *ctx, struct net_device_path *path) { struct dsa_port *dp = dsa_slave_to_port(ctx->dev); + struct net_device *master = dsa_port_to_master(dp); struct dsa_port *cpu_dp = dp->cpu_dp; path->dev = ctx->dev; path->type = DEV_PATH_DSA; path->dsa.proto = cpu_dp->tag_ops->proto; path->dsa.port = dp->index; - ctx->dev = cpu_dp->master; + ctx->dev = master; return 0; } @@ -2247,9 +2247,9 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev) void dsa_slave_setup_tagger(struct net_device *slave) { struct dsa_port *dp = dsa_slave_to_port(slave); + struct net_device *master = dsa_port_to_master(dp); struct dsa_slave_priv *p = netdev_priv(slave); const struct dsa_port *cpu_dp = dp->cpu_dp; - struct net_device *master = cpu_dp->master; const struct dsa_switch *ds = dp->ds; slave->needed_headroom = cpu_dp->tag_ops->needed_headroom; @@ -2306,8 +2306,7 @@ int dsa_slave_resume(struct net_device *slave_dev) int dsa_slave_create(struct dsa_port *port) { - const struct dsa_port *cpu_dp = port->cpu_dp; - struct net_device *master = cpu_dp->master; + struct net_device *master = dsa_port_to_master(port); struct dsa_switch *ds = port->ds; const char *name = port->name; struct net_device *slave_dev; diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 01a427800797..b91c2894b6fd 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -332,7 +332,7 @@ static int dsa_tag_8021q_port_setup(struct dsa_switch *ds, int port) if (!dsa_port_is_user(dp)) return 0; - master = dp->cpu_dp->master; + master = dsa_port_to_master(dp); err = dsa_port_tag_8021q_vlan_add(dp, vid, false); if (err) { @@ -361,7 +361,7 @@ static void dsa_tag_8021q_port_teardown(struct dsa_switch *ds, int port) if (!dsa_port_is_user(dp)) return; - master = dp->cpu_dp->master; + master = dsa_port_to_master(dp); dsa_port_tag_8021q_vlan_del(dp, vid, false); From patchwork Mon May 23 10:42:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858788 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76F04C433EF for ; Mon, 23 May 2022 10:43:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234211AbiEWKnu (ORCPT ); Mon, 23 May 2022 06:43:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53356 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234154AbiEWKnZ (ORCPT ); Mon, 23 May 2022 06:43:25 -0400 Received: from mail-ed1-x535.google.com (mail-ed1-x535.google.com [IPv6:2a00:1450:4864:20::535]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 78F0A101CD for ; Mon, 23 May 2022 03:43:23 -0700 (PDT) Received: by mail-ed1-x535.google.com with SMTP id h11so17391829eda.8 for ; Mon, 23 May 2022 03:43:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1f4qwhCWad2RUVSkCmBNNn90N38xaiuIXetdHY6xBWs=; b=NqCu0zYA6D31IXeEsV3Rey/23Gnc0ApE59WJKR+VUByC7W1fwbuLDRc+PK/uJBCQEQ RO/vhDhZxCIGX+5/JshDqmK5VDvbEYyJk3dP9j+eHtTKyJa3AyBR+5wkHBlxQ/Qg/RA9 be3yu2/kvYH6YVvAKDhyttHRXXD3CcBIumlmbK5DFRagHhJSIxH1Ows1RAL44KjWJmCB GFVw5NWNxvozBvSsSiDNcpTlVj6/MtgHUaYSnghM5n1BHgHh9jYUD6e1lxUbLmuG+5R0 6AaRNXAw50P2/1kG/OfuFug4Op8V2EGg35l3NEi1fuepPh9nwhAxwZq9fwfd4bbsFvqC mnAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1f4qwhCWad2RUVSkCmBNNn90N38xaiuIXetdHY6xBWs=; b=vShQeO5Invr//nkOHpprUAXJRXx4+TjjPWnFwlKvoVbGQ9MbcQj5PT9KRoS/YMjl7K xc+vNMIkloeMXKbpjlWLoKH4Hspuyxz6Imi05pHjknvGNp1u+OlPtGXjf7eC51ORVe45 NtWdsQB6IeHVChueJnY6K2vHzttP+F8yRxPZuZweEzekq94u2gqZdAUzhf0xhRrz5q5W 3cwp/0cC9DHlcKr3gzafqJuC6j7DECCPnwCtcoF1eegwQeFmkPQDeTUVYuD3hQdSxZVD 3/24D1o1AVwx/wDb2+1ghUebZSbTh9Fkl+sADrP1nFMYUsdPjmXLkpiH0nqtavaaz60K bRdA== X-Gm-Message-State: AOAM530ytirU0P9so53qKDXhB1dSUX5GfLI3MI2rrahacN2eQScaHNBZ t64gO3RGRa7l2B5Iz5PNxO3/8yGX8O4= X-Google-Smtp-Source: ABdhPJzVFEyh4oPX/mXm9+acpyP6gOdAQ6uK1JbuzJjXm10ISbixB7pfqYOTat4q/ci+vOUDZzrU4Q== X-Received: by 2002:a05:6402:293:b0:42a:aece:5c5c with SMTP id l19-20020a056402029300b0042aaece5c5cmr23136984edv.108.1653302601425; Mon, 23 May 2022 03:43:21 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:20 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 10/12] net: dsa: allow the DSA master to be seen and changed through rtnetlink Date: Mon, 23 May 2022 13:42:54 +0300 Message-Id: <20220523104256.3556016-11-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean Some DSA switches have multiple CPU ports, which can be used to improve CPU termination throughput, but DSA, through dsa_tree_setup_cpu_ports(), sets up only the first one, leading to suboptimal use of hardware. The desire is to not change the default configuration but to permit the user to create a dynamic mapping between individual user ports and the CPU port that they are served by, configurable through rtnetlink. It is also intended to permit load balancing between CPU ports, and in that case, the foreseen model is for the DSA master to be a bonding interface whose lowers are the physical DSA masters. To that end, we create a struct rtnl_link_ops for DSA user ports with the "dsa" kind. We expose the IFLA_DSA_MASTER link attribute that contains the ifindex of the newly desired DSA master. Signed-off-by: Vladimir Oltean --- include/net/dsa.h | 8 +++ include/uapi/linux/if_link.h | 10 +++ net/dsa/Makefile | 10 ++- net/dsa/dsa.c | 9 +++ net/dsa/dsa2.c | 14 ++++ net/dsa/dsa_priv.h | 10 +++ net/dsa/master.c | 1 + net/dsa/netlink.c | 62 ++++++++++++++++ net/dsa/port.c | 133 +++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 117 ++++++++++++++++++++++++++++++ 10 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 net/dsa/netlink.c diff --git a/include/net/dsa.h b/include/net/dsa.h index 7f6ca944c092..0958ad3289c9 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -555,6 +555,10 @@ static inline bool dsa_is_user_port(struct dsa_switch *ds, int p) list_for_each_entry((_dp), &(_dst)->ports, list) \ if (dsa_port_is_user((_dp))) +#define dsa_tree_for_each_user_port_continue_reverse(_dp, _dst) \ + list_for_each_entry_continue_reverse((_dp), &(_dst)->ports, list) \ + if (dsa_port_is_user((_dp))) + #define dsa_tree_for_each_cpu_port(_dp, _dst) \ list_for_each_entry((_dp), &(_dst)->ports, list) \ if (dsa_port_is_cpu((_dp))) @@ -826,6 +830,10 @@ struct dsa_switch_ops { int (*connect_tag_protocol)(struct dsa_switch *ds, enum dsa_tag_protocol proto); + int (*port_change_master)(struct dsa_switch *ds, int port, + struct net_device *master, + struct netlink_ext_ack *extack); + /* Optional switch-wide initialization and destruction methods */ int (*setup)(struct dsa_switch *ds); void (*teardown)(struct dsa_switch *ds); diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 5f58dcfe2787..f0a7797924ea 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -1373,4 +1373,14 @@ enum { #define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1) +/* DSA section */ + +enum { + IFLA_DSA_UNSPEC, + IFLA_DSA_MASTER, + __IFLA_DSA_MAX, +}; + +#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1) + #endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 9f75820e7c98..d0ed170bb7aa 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -1,7 +1,15 @@ # SPDX-License-Identifier: GPL-2.0 # the core obj-$(CONFIG_NET_DSA) += dsa_core.o -dsa_core-y += dsa.o dsa2.o master.o port.o slave.o switch.o tag_8021q.o +dsa_core-y += \ + dsa.o \ + dsa2.o \ + master.o \ + netlink.o \ + port.o \ + slave.o \ + switch.o \ + tag_8021q.o # tagging formats obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_ar9331.o diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index be7b320cda76..64b14f655b23 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -536,8 +536,16 @@ static int __init dsa_init_module(void) dsa_tag_driver_register(&DSA_TAG_DRIVER_NAME(none_ops), THIS_MODULE); + rc = rtnl_link_register(&dsa_link_ops); + if (rc) + goto netlink_register_fail; + return 0; +netlink_register_fail: + dsa_tag_driver_unregister(&DSA_TAG_DRIVER_NAME(none_ops)); + dsa_slave_unregister_notifier(); + dev_remove_pack(&dsa_pack_type); register_notifier_fail: destroy_workqueue(dsa_owq); @@ -547,6 +555,7 @@ module_init(dsa_init_module); static void __exit dsa_cleanup_module(void) { + rtnl_link_unregister(&dsa_link_ops); dsa_tag_driver_unregister(&DSA_TAG_DRIVER_NAME(none_ops)); dsa_slave_unregister_notifier(); diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 8ff5467ac3e2..32d5a5413bb9 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -386,6 +386,20 @@ static struct dsa_port *dsa_tree_find_first_cpu(struct dsa_switch_tree *dst) return NULL; } +struct net_device *dsa_tree_find_first_master(struct dsa_switch_tree *dst) +{ + struct device_node *ethernet; + struct net_device *master; + struct dsa_port *cpu_dp; + + cpu_dp = dsa_tree_find_first_cpu(dst); + ethernet = of_parse_phandle(cpu_dp->dn, "ethernet", 0); + master = of_find_net_device_by_node(ethernet); + of_node_put(ethernet); + + return master; +} + /* Assign the default CPU port (the first one in the tree) to all ports of the * fabric which don't already have one as part of their own switch. */ diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index f3562cef32ad..1ce0e48d5a92 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -200,6 +200,9 @@ static inline struct net_device *dsa_master_find_slave(struct net_device *dev, return NULL; } +/* netlink.c */ +extern struct rtnl_link_ops dsa_link_ops __read_mostly; + /* port.c */ void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp, const struct dsa_device_ops *tag_ops); @@ -292,6 +295,8 @@ void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr); int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast); void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast); void dsa_port_set_host_flood(struct dsa_port *dp, bool uc, bool mc); +int dsa_port_change_master(struct dsa_port *dp, struct net_device *master, + struct netlink_ext_ack *extack); /* slave.c */ extern const struct dsa_device_ops notag_netdev_ops; @@ -305,8 +310,12 @@ int dsa_slave_suspend(struct net_device *slave_dev); int dsa_slave_resume(struct net_device *slave_dev); int dsa_slave_register_notifier(void); void dsa_slave_unregister_notifier(void); +void dsa_slave_sync_ha(struct net_device *dev); +void dsa_slave_unsync_ha(struct net_device *dev); void dsa_slave_setup_tagger(struct net_device *slave); int dsa_slave_change_mtu(struct net_device *dev, int new_mtu); +int dsa_slave_change_master(struct net_device *dev, struct net_device *master, + struct netlink_ext_ack *extack); int dsa_slave_manage_vlan_filtering(struct net_device *dev, bool vlan_filtering); @@ -542,6 +551,7 @@ void dsa_lag_map(struct dsa_switch_tree *dst, struct dsa_lag *lag); void dsa_lag_unmap(struct dsa_switch_tree *dst, struct dsa_lag *lag); struct dsa_lag *dsa_tree_lag_find(struct dsa_switch_tree *dst, const struct net_device *lag_dev); +struct net_device *dsa_tree_find_first_master(struct dsa_switch_tree *dst); int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v); int dsa_broadcast(unsigned long e, void *v); int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst, diff --git a/net/dsa/master.c b/net/dsa/master.c index 32c0a00a8b92..a7420bad0a0a 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -6,6 +6,7 @@ * Vivien Didelot */ +#include #include "dsa_priv.h" static int dsa_master_get_regs_len(struct net_device *dev) diff --git a/net/dsa/netlink.c b/net/dsa/netlink.c new file mode 100644 index 000000000000..0f43bbb94769 --- /dev/null +++ b/net/dsa/netlink.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2022 NXP + */ +#include +#include + +#include "dsa_priv.h" + +static const struct nla_policy dsa_policy[IFLA_DSA_MAX + 1] = { + [IFLA_DSA_MASTER] = { .type = NLA_U32 }, +}; + +static int dsa_changelink(struct net_device *dev, struct nlattr *tb[], + struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + int err; + + if (!data) + return 0; + + if (data[IFLA_DSA_MASTER]) { + u32 ifindex = nla_get_u32(data[IFLA_DSA_MASTER]); + struct net_device *master; + + master = __dev_get_by_index(dev_net(dev), ifindex); + if (!master) + return -EINVAL; + + err = dsa_slave_change_master(dev, master, extack); + if (err) + return err; + } + + return 0; +} + +static size_t dsa_get_size(const struct net_device *dev) +{ + return nla_total_size(sizeof(u32)) + /* IFLA_DSA_MASTER */ + 0; +} + +static int dsa_fill_info(struct sk_buff *skb, const struct net_device *dev) +{ + struct net_device *master = dsa_slave_to_master(dev); + + if (nla_put_u32(skb, IFLA_DSA_MASTER, master->ifindex)) + return -EMSGSIZE; + + return 0; +} + +struct rtnl_link_ops dsa_link_ops __read_mostly = { + .kind = "dsa", + .priv_size = sizeof(struct dsa_port), + .maxtype = IFLA_DSA_MAX, + .policy = dsa_policy, + .changelink = dsa_changelink, + .get_size = dsa_get_size, + .fill_info = dsa_fill_info, +}; diff --git a/net/dsa/port.c b/net/dsa/port.c index 8557217ed5de..ced7f8d8ec62 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -1370,6 +1371,138 @@ int dsa_port_mrp_del_ring_role(const struct dsa_port *dp, return ds->ops->port_mrp_del_ring_role(ds, dp->index, mrp); } +static int dsa_port_assign_master(struct dsa_port *dp, + struct net_device *master, + struct netlink_ext_ack *extack, + bool fail_on_err) +{ + struct dsa_switch *ds = dp->ds; + int port = dp->index, err; + + err = ds->ops->port_change_master(ds, port, master, extack); + if (err && !fail_on_err) + dev_err(ds->dev, "port %d failed to assign master %s: %pe\n", + port, master->name, ERR_PTR(err)); + + if (err && fail_on_err) + return err; + + dp->cpu_dp = master->dsa_ptr; + + return 0; +} + +/* Change the dp->cpu_dp affinity for a user port. Note that both cross-chip + * notifiers and drivers have implicit assumptions about user-to-CPU-port + * mappings, so we unfortunately cannot delay the deletion of the objects + * (switchdev, standalone addresses, standalone VLANs) on the old CPU port + * until the new CPU port has been set up. So we need to completely tear down + * the old CPU port before changing it, and restore it on errors during the + * bringup of the new one. + */ +int dsa_port_change_master(struct dsa_port *dp, struct net_device *master, + struct netlink_ext_ack *extack) +{ + struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp); + struct net_device *old_master = dsa_port_to_master(dp); + struct net_device *dev = dp->slave; + struct dsa_switch *ds = dp->ds; + int port = dp->index; + bool vlan_filtering; + int err, tmp; + + /* Bridges may hold host FDB, MDB and VLAN objects. These need to be + * migrated, so dynamically unoffload and later reoffload the bridge + * port. + */ + if (bridge_dev) { + dsa_port_pre_bridge_leave(dp, bridge_dev); + dsa_port_bridge_leave(dp, bridge_dev); + } + + /* The port might still be VLAN filtering even if it's no longer + * under a bridge, either due to ds->vlan_filtering_is_global or + * ds->needs_standalone_vlan_filtering. In turn this means VLANs + * on the CPU port. + */ + vlan_filtering = dsa_port_is_vlan_filtering(dp); + if (vlan_filtering) { + err = dsa_slave_manage_vlan_filtering(dev, false); + if (err) { + dev_err(ds->dev, + "port %d failed to remove standalone VLANs: %pe\n", + port, ERR_PTR(err)); + goto rewind_old_bridge; + } + } + + /* Standalone addresses, and addresses of upper interfaces like + * VLAN, LAG, HSR need to be migrated. + */ + dsa_slave_unsync_ha(dev); + + err = dsa_port_assign_master(dp, master, extack, true); + if (err) + goto rewind_old_addrs; + + dsa_slave_sync_ha(dev); + + if (vlan_filtering) { + err = dsa_slave_manage_vlan_filtering(dev, true); + if (err) { + dev_err(ds->dev, + "port %d failed to restore standalone VLANs: %pe\n", + port, ERR_PTR(err)); + goto rewind_new_addrs; + } + } + + if (bridge_dev) { + err = dsa_port_bridge_join(dp, bridge_dev, extack); + if (err && err == -EOPNOTSUPP) { + dev_err(ds->dev, + "port %d failed to reoffload bridge %s: %pe\n", + port, bridge_dev->name, ERR_PTR(err)); + goto rewind_new_vlan; + } + } + + return 0; + +rewind_new_vlan: + if (vlan_filtering) + dsa_slave_manage_vlan_filtering(dev, false); + +rewind_new_addrs: + dsa_slave_unsync_ha(dev); + + dsa_port_assign_master(dp, old_master, NULL, false); + +/* Restore the objects on the old CPU port */ +rewind_old_addrs: + dsa_slave_sync_ha(dev); + + if (vlan_filtering) { + tmp = dsa_slave_manage_vlan_filtering(dev, true); + if (tmp) { + dev_err(ds->dev, "port %d failed to restore standalone VLANs: %pe\n", + dp->index, ERR_PTR(tmp)); + } + } + +rewind_old_bridge: + if (bridge_dev) { + tmp = dsa_port_bridge_join(dp, bridge_dev, extack); + if (tmp) { + dev_err(ds->dev, + "port %d failed to rejoin bridge %s: %pe\n", + dp->index, bridge_dev->name, ERR_PTR(tmp)); + } + } + + return err; +} + void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp, const struct dsa_device_ops *tag_ops) { diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 0d0deca99eba..95bfce49d57d 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -164,6 +164,48 @@ static int dsa_slave_unsync_mc(struct net_device *dev, return dsa_slave_schedule_standalone_work(dev, DSA_MC_DEL, addr, 0); } +void dsa_slave_sync_ha(struct net_device *dev) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + struct netdev_hw_addr *ha; + + netif_addr_lock_bh(dev); + + netdev_for_each_synced_mc_addr(ha, dev) + dsa_slave_sync_mc(dev, ha->addr); + + netdev_for_each_synced_uc_addr(ha, dev) + dsa_slave_sync_uc(dev, ha->addr); + + netif_addr_unlock_bh(dev); + + if (dsa_switch_supports_uc_filtering(ds) || + dsa_switch_supports_mc_filtering(ds)) + dsa_flush_workqueue(); +} + +void dsa_slave_unsync_ha(struct net_device *dev) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + struct netdev_hw_addr *ha; + + netif_addr_lock_bh(dev); + + netdev_for_each_synced_uc_addr(ha, dev) + dsa_slave_unsync_uc(dev, ha->addr); + + netdev_for_each_synced_mc_addr(ha, dev) + dsa_slave_unsync_mc(dev, ha->addr); + + netif_addr_unlock_bh(dev); + + if (dsa_switch_supports_uc_filtering(ds) || + dsa_switch_supports_mc_filtering(ds)) + dsa_flush_workqueue(); +} + /* slave mii_bus handling ***************************************************/ static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg) { @@ -2322,6 +2364,7 @@ int dsa_slave_create(struct dsa_port *port) if (slave_dev == NULL) return -ENOMEM; + slave_dev->rtnl_link_ops = &dsa_link_ops; slave_dev->ethtool_ops = &dsa_slave_ethtool_ops; #if IS_ENABLED(CONFIG_DCB) slave_dev->dcbnl_ops = &dsa_slave_dcbnl_ops; @@ -2438,6 +2481,80 @@ void dsa_slave_destroy(struct net_device *slave_dev) free_netdev(slave_dev); } +int dsa_slave_change_master(struct net_device *dev, struct net_device *master, + struct netlink_ext_ack *extack) +{ + struct net_device *old_master = dsa_slave_to_master(dev); + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + struct net_device *upper; + struct list_head *iter; + int err; + + if (master == old_master) + return 0; + + if (!ds->ops->port_change_master) + return -EOPNOTSUPP; + + if (!netdev_uses_dsa(master)) { + NL_SET_ERR_MSG_MOD(extack, + "Interface not eligible as DSA master"); + return -EOPNOTSUPP; + } + + netdev_for_each_upper_dev_rcu(master, upper, iter) { + if (dsa_slave_dev_check(upper)) + continue; + if (netif_is_bridge_master(upper)) + continue; + NL_SET_ERR_MSG_MOD(extack, "Cannot join master with unknown uppers"); + return -EOPNOTSUPP; + } + + /* Since we allow live-changing the DSA master, plus we auto-open the + * DSA master when the user port opens => we need to ensure that the + * new DSA master is open too. + */ + if (dev->flags & IFF_UP) { + err = dev_open(master, extack); + if (err) + return err; + } + + netdev_upper_dev_unlink(old_master, dev); + + err = netdev_upper_dev_link(master, dev, extack); + if (err) + goto out_revert_old_master_unlink; + + err = dsa_port_change_master(dp, master, extack); + if (err) + goto out_revert_master_link; + + /* Update the MTU of the new CPU port through cross-chip notifiers */ + err = dsa_slave_change_mtu(dev, dev->mtu); + if (err && err != -EOPNOTSUPP) { + netdev_warn(dev, + "nonfatal error updating MTU with new master: %pe\n", + ERR_PTR(err)); + } + + /* If the port doesn't have its own MAC address and relies on the DSA + * master's one, inherit it again from the new DSA master. + */ + if (is_zero_ether_addr(dp->mac)) + eth_hw_addr_inherit(dev, master); + + return 0; + +out_revert_master_link: + netdev_upper_dev_unlink(master, dev); +out_revert_old_master_unlink: + netdev_upper_dev_link(old_master, dev, NULL); + return err; +} + bool dsa_slave_dev_check(const struct net_device *dev) { return dev->netdev_ops == &dsa_slave_netdev_ops; From patchwork Mon May 23 10:42:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858789 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9576FC433FE for ; Mon, 23 May 2022 10:43:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234225AbiEWKnw (ORCPT ); Mon, 23 May 2022 06:43:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54350 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234194AbiEWKn2 (ORCPT ); Mon, 23 May 2022 06:43:28 -0400 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7450EFC7 for ; Mon, 23 May 2022 03:43:25 -0700 (PDT) Received: by mail-ed1-x534.google.com with SMTP id j28so18493736eda.13 for ; Mon, 23 May 2022 03:43:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0jjXvtFnIPMsxjxWeaswnMn6d7926FBVTg55lXT6y/g=; b=aBugpW7Hy6GBO5GDSknc3cBRs41W4h2UMXwaQYlArsKYzffRj5llZ+sp7l8YyuBw8F 0WF8J2nfQOlQkUPVBMB0rHxAYwSOuvpcRQoyEhKh/9HW4sCyqlXIH7hJHp2hPDX53xzA j/8JDUBFgbqXgYPl/vpJDAqvR9wHvDoMtcq/D1qXGCxIg5BT2ZZ++/1KSzP9q46+v4yh x05GsLI3Afj9PoHRYtSHVrtzYfJus4Ccm7y+zFJH1CQGt1R5MXoAla1HflVpcOuLjHrM 2paDjvfY2Dsl6GW6ego/EkiGNuIY8qBcAFOtO+WBnrnleKUHT/EzGVty/0dq+OtIviW2 pFtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0jjXvtFnIPMsxjxWeaswnMn6d7926FBVTg55lXT6y/g=; b=USfWVfFGAEkRxJg0JM4ePGTgJAYqqhHEcIJPtm+QlPWaTZpEjJjijMNT12fqshhvc/ YqRckr+pGWpxWcJ7FnXph8j//7Ew/wiAEaz67H7Wy2DMN1seINNIVkxN0IQBiCmTs/xP WReIdGA317bIh6YvYqZGkZ93DIADGhPdOR++8+ev7ekqMSauomkKPOWbLUQE4sDLL2/M Ljk1YFfmOk21QlLQdmIClVlQmENmmixHlQUy9DiC7a8JWBZ6jfsKrC87o+hKATm1OcYk EZJQJVKgrXG1OydXAe5DwUOe3LhqxvFUjpr4XOiyezvq2xGeb+78LZXe0PUhrDASci6B XiPA== X-Gm-Message-State: AOAM531GwK+SSxx+PBpbhA9uqwy1mqwWNnv/A8nb5TyZZgofYKupnMzl ode404iWwTttgxaAhEOQvtRLMk01rII= X-Google-Smtp-Source: ABdhPJzeqIVMRR2keN65m0UiqIefdZTAEz75Fq1qEiYd3sg3n3k+4YIge8sdasxEFko/GaQZLXwiIg== X-Received: by 2002:a05:6402:3289:b0:42b:4d05:ac85 with SMTP id f9-20020a056402328900b0042b4d05ac85mr9257705eda.106.1653302603437; Mon, 23 May 2022 03:43:23 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:22 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 11/12] net: dsa: allow masters to join a LAG Date: Mon, 23 May 2022 13:42:55 +0300 Message-Id: <20220523104256.3556016-12-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean There are 2 ways in which a DSA user port may become handled by 2 CPU ports in a LAG: (1) its current DSA master joins a LAG ip link del bond0 && ip link add bond0 type bond mode 802.3ad ip link set eno2 master bond0 When this happens, all user ports with "eno2" as DSA master get automatically migrated to "bond0" as DSA master. (2) it is explicitly configured as such by the user # Before, the DSA master was eno3 ip link set swp0 type dsa master bond0 The design of this configuration is that the LAG device dynamically becomes a DSA master through dsa_master_setup() when the first physical DSA master becomes a LAG slave, and stops being so through dsa_master_teardown() when the last physical DSA master leaves. A LAG interface is considered as a valid DSA master only if it contains existing DSA masters, and no other lower interfaces. Therefore, we mainly rely on method (1) to enter this configuration. Each physical DSA master (LAG slave) retains its dev->dsa_ptr for when it becomes a standalone DSA master again. But the LAG master also has a dev->dsa_ptr, and this is actually duplicated from one of the physical LAG slaves, and therefore needs to be balanced when LAG slaves come and go. To the switch driver, putting DSA masters in a LAG is seen as putting their associated CPU ports in a LAG. We need to prepare cross-chip host FDB notifiers for CPU ports in a LAG, by calling the driver's ->lag_fdb_add method rather than ->port_fdb_add. Signed-off-by: Vladimir Oltean --- include/net/dsa.h | 6 ++ net/dsa/dsa_priv.h | 5 ++ net/dsa/master.c | 59 +++++++++++++++++ net/dsa/port.c | 1 + net/dsa/slave.c | 157 +++++++++++++++++++++++++++++++++++++++++++-- net/dsa/switch.c | 22 +++++-- 6 files changed, 242 insertions(+), 8 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 0958ad3289c9..158efd3e2ab3 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -296,6 +296,9 @@ struct dsa_port { u8 master_admin_up:1; u8 master_oper_up:1; + /* Valid only on user ports */ + u8 cpu_port_in_lag:1; + u8 setup:1; struct device_node *dn; @@ -720,6 +723,9 @@ static inline bool dsa_port_offloads_lag(struct dsa_port *dp, static inline struct net_device *dsa_port_to_master(const struct dsa_port *dp) { + if (dp->cpu_port_in_lag) + return dsa_port_lag_dev_get(dp->cpu_dp); + return dp->cpu_dp->master; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1ce0e48d5a92..236fb1fb7b6c 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -184,6 +184,11 @@ static inline int dsa_tag_protocol_overhead(const struct dsa_device_ops *ops) /* master.c */ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp); void dsa_master_teardown(struct net_device *dev); +int dsa_master_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp, + struct netdev_lag_upper_info *uinfo, + struct netlink_ext_ack *extack); +void dsa_master_lag_teardown(struct net_device *lag_dev, + struct dsa_port *cpu_dp); static inline struct net_device *dsa_master_find_slave(struct net_device *dev, int device, int port) diff --git a/net/dsa/master.c b/net/dsa/master.c index a7420bad0a0a..66fb972da2dd 100644 --- a/net/dsa/master.c +++ b/net/dsa/master.c @@ -418,3 +418,62 @@ void dsa_master_teardown(struct net_device *dev) */ wmb(); } + +int dsa_master_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp, + struct netdev_lag_upper_info *uinfo, + struct netlink_ext_ack *extack) +{ + bool master_setup = false; + struct net_device *lower; + struct list_head *iter; + int err; + + /* To be eligible as a DSA master, a LAG must have all lower + * interfaces be eligible DSA masters. + */ + netdev_for_each_lower_dev(lag_dev, lower, iter) { + if (!netdev_uses_dsa(lower)) { + NL_SET_ERR_MSG_MOD(extack, + "All LAG ports must be eligible as DSA masters"); + return -EINVAL; + } + } + + if (!netdev_uses_dsa(lag_dev)) { + err = dsa_master_setup(lag_dev, cpu_dp); + if (err) + return err; + } + + err = dsa_port_lag_join(cpu_dp, lag_dev, uinfo, extack); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "CPU port failed to join LAG"); + goto out_master_teardown; + } + + return 0; + +out_master_teardown: + if (master_setup) + dsa_master_teardown(lag_dev); + return err; +} + +/* Tear down a master if there isn't any other user port on it, + * optionally also destroying LAG information. + */ +void dsa_master_lag_teardown(struct net_device *lag_dev, + struct dsa_port *cpu_dp) +{ + struct net_device *upper; + struct list_head *iter; + + dsa_port_lag_leave(cpu_dp, lag_dev); + + netdev_for_each_upper_dev_rcu(lag_dev, upper, iter) + if (dsa_slave_dev_check(upper)) + return; + + dsa_master_teardown(lag_dev); +} diff --git a/net/dsa/port.c b/net/dsa/port.c index ced7f8d8ec62..a90c03d15061 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -1388,6 +1388,7 @@ static int dsa_port_assign_master(struct dsa_port *dp, return err; dp->cpu_dp = master->dsa_ptr; + dp->cpu_port_in_lag = netif_is_lag_master(master); return 0; } diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 95bfce49d57d..f21524c0fbd5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2812,6 +2812,10 @@ dsa_master_prechangeupper_sanity_check(struct net_device *master, if (netif_is_bridge_master(info->upper_dev)) return NOTIFY_DONE; + /* Allow LAG uppers */ + if (netif_is_lag_master(info->upper_dev)) + return NOTIFY_DONE; + extack = netdev_notifier_info_to_extack(&info->info); NL_SET_ERR_MSG_MOD(extack, @@ -2859,6 +2863,138 @@ dsa_bridge_prechangelower_sanity_check(struct net_device *new_lower, return NOTIFY_DONE; } +static void dsa_tree_migrate_ports_from_lag_master(struct dsa_switch_tree *dst, + struct net_device *lag_dev) +{ + struct net_device *new_master; + struct dsa_port *dp; + int err; + + new_master = dsa_tree_find_first_master(dst); + + dsa_tree_for_each_user_port(dp, dst) { + if (dsa_port_to_master(dp) != lag_dev) + continue; + + err = dsa_port_change_master(dp, new_master, NULL); + if (err) { + netdev_err(dp->slave, + "failed to restore master to %s: %pe\n", + new_master->name, ERR_PTR(err)); + } + } +} + +static int dsa_master_lag_join(struct net_device *master, + struct net_device *lag_dev, + struct netdev_lag_upper_info *uinfo, + struct netlink_ext_ack *extack) +{ + struct dsa_port *cpu_dp = master->dsa_ptr; + struct dsa_switch_tree *dst = cpu_dp->dst; + struct dsa_port *dp; + int err; + + err = dsa_master_lag_setup(lag_dev, cpu_dp, uinfo, extack); + if (err) + return err; + + dsa_tree_for_each_user_port(dp, dst) { + if (dsa_port_to_master(dp) != master) + continue; + + err = dsa_port_change_master(dp, lag_dev, extack); + if (err) + goto restore; + } + + return 0; + +restore: + dsa_tree_for_each_user_port_continue_reverse(dp, dst) { + if (dsa_port_to_master(dp) != lag_dev) + continue; + + err = dsa_port_change_master(dp, master, NULL); + if (err) { + netdev_err(dp->slave, + "failed to restore master to %s: %pe\n", + master->name, ERR_PTR(err)); + } + } + + dsa_master_lag_teardown(lag_dev, master->dsa_ptr); + + return err; +} + +static void dsa_master_lag_leave(struct net_device *master, + struct net_device *lag_dev) +{ + struct dsa_port *dp, *cpu_dp = lag_dev->dsa_ptr; + struct dsa_switch_tree *dst = cpu_dp->dst; + struct dsa_port *new_cpu_dp = NULL; + struct net_device *lower; + struct list_head *iter; + + netdev_for_each_lower_dev(lag_dev, lower, iter) { + if (netdev_uses_dsa(lower)) { + new_cpu_dp = lower->dsa_ptr; + break; + } + } + + if (new_cpu_dp) { + /* Update the CPU port of the user ports still under the LAG + * so that dsa_port_to_master() continues to work properly + */ + dsa_tree_for_each_user_port(dp, dst) + if (dsa_port_to_master(dp) == lag_dev) + dp->cpu_dp = new_cpu_dp; + + /* Update the index of the virtual CPU port to match the lowest + * physical CPU port + */ + lag_dev->dsa_ptr = new_cpu_dp; + wmb(); + } else { + /* If the LAG DSA master has no ports left, migrate back all + * user ports to the first physical CPU port + */ + dsa_tree_migrate_ports_from_lag_master(dst, lag_dev); + } + + /* This DSA master has left its LAG in any case, so let + * the CPU port leave the hardware LAG as well + */ + dsa_master_lag_teardown(lag_dev, master->dsa_ptr); +} + +static int dsa_master_changeupper(struct net_device *dev, + struct netdev_notifier_changeupper_info *info) +{ + struct netlink_ext_ack *extack; + int err = NOTIFY_DONE; + + if (!netdev_uses_dsa(dev)) + return err; + + extack = netdev_notifier_info_to_extack(&info->info); + + if (netif_is_lag_master(info->upper_dev)) { + if (info->linking) { + err = dsa_master_lag_join(dev, info->upper_dev, + info->upper_info, extack); + err = notifier_from_errno(err); + } else { + dsa_master_lag_leave(dev, info->upper_dev); + err = NOTIFY_OK; + } + } + + return err; +} + static int dsa_slave_netdevice_event(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -2902,6 +3038,10 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, if (notifier_to_errno(err)) return err; + err = dsa_master_changeupper(dev, ptr); + if (notifier_to_errno(err)) + return err; + break; } case NETDEV_CHANGELOWERSTATE: { @@ -2909,12 +3049,21 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, struct dsa_port *dp; int err; - if (!dsa_slave_dev_check(dev)) - break; + if (dsa_slave_dev_check(dev)) { + dp = dsa_slave_to_port(dev); + + err = dsa_port_lag_change(dp, info->lower_state_info); + } - dp = dsa_slave_to_port(dev); + /* Mirror LAG port events on DSA masters that are in + * a LAG towards their respective switch CPU ports + */ + if (netdev_uses_dsa(dev)) { + dp = dev->dsa_ptr; + + err = dsa_port_lag_change(dp, info->lower_state_info); + } - err = dsa_port_lag_change(dp, info->lower_state_info); return notifier_from_errno(err); } case NETDEV_CHANGE: diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 2b56218fc57c..f443916d2571 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -397,8 +397,15 @@ static int dsa_switch_host_fdb_add(struct dsa_switch *ds, dsa_switch_for_each_port(dp, ds) { if (dsa_port_host_address_match(dp, info->dp)) { - err = dsa_port_do_fdb_add(dp, info->addr, info->vid, - info->db); + if (dsa_port_is_cpu(dp) && info->dp->cpu_port_in_lag) { + err = dsa_switch_do_lag_fdb_add(ds, dp->lag, + info->addr, + info->vid, + info->db); + } else { + err = dsa_port_do_fdb_add(dp, info->addr, + info->vid, info->db); + } if (err) break; } @@ -418,8 +425,15 @@ static int dsa_switch_host_fdb_del(struct dsa_switch *ds, dsa_switch_for_each_port(dp, ds) { if (dsa_port_host_address_match(dp, info->dp)) { - err = dsa_port_do_fdb_del(dp, info->addr, info->vid, - info->db); + if (dsa_port_is_cpu(dp) && info->dp->cpu_port_in_lag) { + err = dsa_switch_do_lag_fdb_del(ds, dp->lag, + info->addr, + info->vid, + info->db); + } else { + err = dsa_port_do_fdb_del(dp, info->addr, + info->vid, info->db); + } if (err) break; } From patchwork Mon May 23 10:42:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 12858790 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 764FAC433F5 for ; Mon, 23 May 2022 10:43:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234231AbiEWKny (ORCPT ); Mon, 23 May 2022 06:43:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54360 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234205AbiEWKn3 (ORCPT ); Mon, 23 May 2022 06:43:29 -0400 Received: from mail-ed1-x530.google.com (mail-ed1-x530.google.com [IPv6:2a00:1450:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 676EB120BD for ; Mon, 23 May 2022 03:43:27 -0700 (PDT) Received: by mail-ed1-x530.google.com with SMTP id j4so14120870edq.6 for ; Mon, 23 May 2022 03:43:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IuAqXISDjSHkJt8CP9xEtdbMYAiNqKEvcEBC+IER7fc=; b=jjIuJTiMB7qbobNu1JLpIhoEfn0PRp2NW3dqzfNSPdGWwUVZKg4M211jrIMrtvtdSE G5jhhqgtwINdOVwNnItI9WDqxnKmR2Wwf2kvQGxuLnj8GWT05cN/ahAdsuUUo4QonhiK +YL+OCtVxhmnuIciZtZiDcCI3WYrvszRsoZZjMq88LucBInXr3KsWRefNxWzazSOgkYt SrqC0TeaDkPFoOgzxhGopsQoU8rg03EIH6MhH6Q5Mymj+OutKoGYCicFO7rvrAzhQk+g 6rrfeUVflUUuS1oeW0QjuteKZ9Xsv0fOKTmmJ3nnrkiYoQoP3TZzloGUcmFG+oORwikL PXCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IuAqXISDjSHkJt8CP9xEtdbMYAiNqKEvcEBC+IER7fc=; b=fcbNjn6umV12Xv3AuZpQNDjrEqMHndVeTyxa69ZEvS8knPiR9YcslgDTR2xaJExkP/ pCcmNqBi7LM1JZU7GG1qudT1bQLsZJUc+b4dUQEDGrsBfUoyt3tKG//W/gVkRS6I9FUI qiUqkei/3Y3D8Wh2i7Nqdlg2pQDMHrnliucRMxNp9AOC+nJ2R/Bbp5dh+X9iDOPrzi9A EfOAP3iHZvxphdHctV9nxKMQbxir4ocm303sIPo/giiQ8BsYOcWYVwbIcjH+PS0eQ+XS Y7GrEWdehSSZray3mKB9GHzN+CcNGSEpHanxO0pGV2ZbypSdwMHCBSQIU5MepIQvzUlP EbMA== X-Gm-Message-State: AOAM531ldDgp6gTCTZhNH/xBQ2Zh8CQXTUD7IyO0dC1bDOQAu/aJBrY2 4JQ/k88I7mrnH2wKXS+Ci+Qp5bvzN0Q= X-Google-Smtp-Source: ABdhPJyRSh/zsGoAA+Pa7roPayyQzVA4+yv/ZkpG3UdMne+2so0x3E55sSGG6QerfCWh9TVBkUTY4A== X-Received: by 2002:a05:6402:1453:b0:42a:ae31:310c with SMTP id d19-20020a056402145300b0042aae31310cmr22611666edx.382.1653302605427; Mon, 23 May 2022 03:43:25 -0700 (PDT) Received: from localhost.localdomain ([188.25.255.186]) by smtp.gmail.com with ESMTPSA id j18-20020a1709066dd200b006feb875503fsm2584822ejt.78.2022.05.23.03.43.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 May 2022 03:43:24 -0700 (PDT) From: Vladimir Oltean To: netdev@vger.kernel.org Cc: Jakub Kicinski , Florian Fainelli , Vivien Didelot , Andrew Lunn , Vladimir Oltean , Tobias Waldekranz , =?utf-8?q?Marek_Beh=C3=BAn?= , Ansuel Smith , DENG Qingfang , =?utf-8?q?Alvin_=C5=A0ipraga?= , Claudiu Manoil , Alexandre Belloni , UNGLinuxDriver@microchip.com, Colin Foster , Linus Walleij , Luiz Angelo Daros de Luca , Roopa Prabhu , Nikolay Aleksandrov , Frank Wunderlich , Vladimir Oltean Subject: [RFC PATCH net-next 12/12] net: dsa: felix: add support for changing DSA master Date: Mon, 23 May 2022 13:42:56 +0300 Message-Id: <20220523104256.3556016-13-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523104256.3556016-1-olteanv@gmail.com> References: <20220523104256.3556016-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vladimir Oltean Changing the DSA master means different things depending on the tagging protocol in use. For NPI mode ("ocelot" and "seville"), there is a single port which can be configured as NPI, but DSA only permits changing the CPU port affinity of user ports one by one. So changing a user port to a different NPI port globally changes what the NPI port is, and breaks the user ports still using the old one. To address this while still permitting the change of the NPI port, require that the user ports which are still affine to the old NPI port are down, and cannot be brought up until they are all affine to the same NPI port. The tag_8021q mode ("ocelot-8021q") is more flexible, in that each user port can be freely assigned to one CPU port or to the other. This works by filtering host addresses towards both tag_8021q CPU ports, and then restricting the forwarding from a certain user port only to one of the two tag_8021q CPU ports. Additionally, the 2 tag_8021q CPU ports can be placed in a LAG. This works by enabling forwarding via PGID_SRC from a certain user port towards the logical port ID containing both tag_8021q CPU ports, but then restricting forwarding per packet, via the LAG hash codes in PGID_AGGR, to either one or the other. When we change the DSA master to a LAG device, DSA guarantees us that the LAG has at least one lower interface as a physical DSA master. But DSA masters can come and go as lowers of that LAG, and ds->ops->port_change_master() will not get called, because the DSA master is still the same (the LAG). So we need to hook into the ds->ops->port_lag_{join,leave} calls on the CPU ports and update the logical port ID of the LAG that user ports are assigned to. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/ocelot/felix.c | 117 ++++++++++++++++++++++++++++- drivers/net/dsa/ocelot/felix.h | 3 + drivers/net/ethernet/mscc/ocelot.c | 3 +- include/soc/mscc/ocelot.h | 1 + 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 3e07dc39007a..4e648382c05d 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -42,6 +42,25 @@ static struct net_device *felix_classify_db(struct dsa_db db) } } +static int felix_cpu_port_for_master(struct dsa_switch *ds, + struct net_device *master) +{ + struct ocelot *ocelot = ds->priv; + struct dsa_port *cpu_dp; + int lag; + + if (netif_is_lag_master(master)) { + mutex_lock(&ocelot->fwd_domain_lock); + lag = ocelot_bond_get_id(ocelot, master); + mutex_unlock(&ocelot->fwd_domain_lock); + + return lag; + } + + cpu_dp = master->dsa_ptr; + return cpu_dp->index; +} + /* Set up VCAP ES0 rules for pushing a tag_8021q VLAN towards the CPU such that * the tagger can perform RX source port identification. */ @@ -422,6 +441,39 @@ static unsigned long felix_tag_npi_get_host_fwd_mask(struct dsa_switch *ds) return BIT(ocelot->num_phys_ports); } +static int felix_tag_npi_change_master(struct dsa_switch *ds, int port, + struct net_device *master, + struct netlink_ext_ack *extack) +{ + struct dsa_port *dp = dsa_to_port(ds, port), *other_dp; + struct ocelot *ocelot = ds->priv; + + if (netif_is_lag_master(master)) { + NL_SET_ERR_MSG_MOD(extack, "LAG DSA master only supported using ocelot-8021q"); + return -EOPNOTSUPP; + } + + /* Changing the NPI port breaks user ports still assigned to the old + * one, so only allow it while they're down, and don't allow them to + * come back up until they're all changed to the new one. + */ + dsa_switch_for_each_user_port(other_dp, ds) { + struct net_device *slave = other_dp->slave; + + if (other_dp != dp && (slave->flags & IFF_UP) && + dsa_port_to_master(other_dp) != master) { + NL_SET_ERR_MSG_MOD(extack, + "Cannot change while old master still has users"); + return -EOPNOTSUPP; + } + } + + felix_npi_port_deinit(ocelot, ocelot->npi); + felix_npi_port_init(ocelot, felix_cpu_port_for_master(ds, master)); + + return 0; +} + /* Alternatively to using the NPI functionality, that same hardware MAC * connected internally to the enetc or fman DSA master can be configured to * use the software-defined tag_8021q frame format. As far as the hardware is @@ -433,6 +485,7 @@ static const struct felix_tag_proto_ops felix_tag_npi_proto_ops = { .setup = felix_tag_npi_setup, .teardown = felix_tag_npi_teardown, .get_host_fwd_mask = felix_tag_npi_get_host_fwd_mask, + .change_master = felix_tag_npi_change_master, }; static int felix_tag_8021q_setup(struct dsa_switch *ds) @@ -501,10 +554,24 @@ static unsigned long felix_tag_8021q_get_host_fwd_mask(struct dsa_switch *ds) return dsa_cpu_ports(ds); } +static int felix_tag_8021q_change_master(struct dsa_switch *ds, int port, + struct net_device *master, + struct netlink_ext_ack *extack) +{ + int cpu = felix_cpu_port_for_master(ds, master); + struct ocelot *ocelot = ds->priv; + + ocelot_port_unassign_dsa_8021q_cpu(ocelot, port); + ocelot_port_assign_dsa_8021q_cpu(ocelot, port, cpu); + + return felix_update_trapping_destinations(ds, true); +} + static const struct felix_tag_proto_ops felix_tag_8021q_proto_ops = { .setup = felix_tag_8021q_setup, .teardown = felix_tag_8021q_teardown, .get_host_fwd_mask = felix_tag_8021q_get_host_fwd_mask, + .change_master = felix_tag_8021q_change_master, }; static void felix_set_host_flood(struct dsa_switch *ds, unsigned long mask, @@ -664,6 +731,16 @@ static void felix_port_set_host_flood(struct dsa_switch *ds, int port, !!felix->host_flood_mc_mask, true); } +static int felix_port_change_master(struct dsa_switch *ds, int port, + struct net_device *master, + struct netlink_ext_ack *extack) +{ + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + + return felix->tag_proto_ops->change_master(ds, port, master, extack); +} + static int felix_set_ageing_time(struct dsa_switch *ds, unsigned int ageing_time) { @@ -855,8 +932,17 @@ static int felix_lag_join(struct dsa_switch *ds, int port, struct netdev_lag_upper_info *info) { struct ocelot *ocelot = ds->priv; + int err; - return ocelot_port_lag_join(ocelot, port, lag.dev, info); + err = ocelot_port_lag_join(ocelot, port, lag.dev, info); + if (err) + return err; + + /* Update the logical LAG port that serves as tag_8021q CPU port */ + if (!dsa_is_cpu_port(ds, port)) + return 0; + + return felix_port_change_master(ds, port, lag.dev, NULL); } static int felix_lag_leave(struct dsa_switch *ds, int port, @@ -866,7 +952,11 @@ static int felix_lag_leave(struct dsa_switch *ds, int port, ocelot_port_lag_leave(ocelot, port, lag.dev); - return 0; + /* Update the logical LAG port that serves as tag_8021q CPU port */ + if (!dsa_is_cpu_port(ds, port)) + return 0; + + return felix_port_change_master(ds, port, lag.dev, NULL); } static int felix_lag_change(struct dsa_switch *ds, int port) @@ -1004,6 +1094,27 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, felix->info->port_sched_speed_set(ocelot, port, speed); } +static int felix_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phydev) +{ + struct dsa_port *dp = dsa_to_port(ds, port); + struct ocelot *ocelot = ds->priv; + + if (!dsa_port_is_user(dp)) + return 0; + + if (ocelot->npi >= 0) { + struct net_device *master = dsa_port_to_master(dp); + + if (felix_cpu_port_for_master(ds, master) != ocelot->npi) { + dev_err(ds->dev, "Multiple masters are not allowed\n"); + return -EINVAL; + } + } + + return 0; +} + static void felix_port_qos_map_init(struct ocelot *ocelot, int port) { int i; @@ -1839,6 +1950,7 @@ const struct dsa_switch_ops felix_switch_ops = { .phylink_mac_select_pcs = felix_phylink_mac_select_pcs, .phylink_mac_link_down = felix_phylink_mac_link_down, .phylink_mac_link_up = felix_phylink_mac_link_up, + .port_enable = felix_port_enable, .port_fast_age = felix_port_fast_age, .port_fdb_dump = felix_fdb_dump, .port_fdb_add = felix_fdb_add, @@ -1894,6 +2006,7 @@ const struct dsa_switch_ops felix_switch_ops = { .port_add_dscp_prio = felix_port_add_dscp_prio, .port_del_dscp_prio = felix_port_del_dscp_prio, .port_set_host_flood = felix_port_set_host_flood, + .port_change_master = felix_port_change_master, }; struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port) diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 9e07eb7ee28d..a1350342d47c 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -70,6 +70,9 @@ struct felix_tag_proto_ops { int (*setup)(struct dsa_switch *ds); void (*teardown)(struct dsa_switch *ds); unsigned long (*get_host_fwd_mask)(struct dsa_switch *ds); + int (*change_master)(struct dsa_switch *ds, int port, + struct net_device *master, + struct netlink_ext_ack *extack); }; extern const struct dsa_switch_ops felix_switch_ops; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 8da7e25a47c9..3a73bf31f3eb 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -2036,7 +2036,7 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond) /* The logical port number of a LAG is equal to the lowest numbered physical * port ID present in that LAG. It may change if that port ever leaves the LAG. */ -static int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond) +int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond) { int bond_mask = ocelot_get_bond_mask(ocelot, bond); @@ -2045,6 +2045,7 @@ static int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond) return __ffs(bond_mask); } +EXPORT_SYMBOL_GPL(ocelot_bond_get_id); static u32 ocelot_dsa_8021q_cpu_assigned_ports(struct ocelot *ocelot, struct ocelot_port *cpu) diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 5f88385a7748..9b777e4fa98e 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -948,6 +948,7 @@ int ocelot_port_lag_join(struct ocelot *ocelot, int port, void ocelot_port_lag_leave(struct ocelot *ocelot, int port, struct net_device *bond); void ocelot_port_lag_change(struct ocelot *ocelot, int port, bool lag_tx_active); +int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond); int ocelot_devlink_sb_register(struct ocelot *ocelot); void ocelot_devlink_sb_unregister(struct ocelot *ocelot);