From patchwork Sun Nov 8 13:19:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 11889549 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21682C4741F for ; Sun, 8 Nov 2020 13:22:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D9780206F4 for ; Sun, 8 Nov 2020 13:22:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dmRgZbV1" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728599AbgKHNWs (ORCPT ); Sun, 8 Nov 2020 08:22:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727949AbgKHNUO (ORCPT ); Sun, 8 Nov 2020 08:20:14 -0500 Received: from mail-ed1-x541.google.com (mail-ed1-x541.google.com [IPv6:2a00:1450:4864:20::541]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C191AC0613D2; Sun, 8 Nov 2020 05:20:13 -0800 (PST) Received: by mail-ed1-x541.google.com with SMTP id ay21so5906235edb.2; Sun, 08 Nov 2020 05:20:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=yc3fdvdMZXoIQBbOfrk5g2mtoncNy7PSx02ksEjgVdU=; b=dmRgZbV1OhD87z6CiSifwoSR7s9GWPgGd6HzevP4l6OqJTc3yN+UQD6W8/rP9w+/tP DgOyYjsIMdFL5ZtQzVB/RFclLeGlD0bAPedM8NuEk7BPG/X3g++E+IkCwVxSsEO3NR/T HjLNuVfh7kJfrdzUvPNRif9k5lK/JhV7bQU5XIL9BZIzYNsPjU9qxCmuEwCLnl6OvVct 9u+J+Ve0ORZUuWi53jqFD7bo4/HebmE8xlndGM5nLjL73EicxCSgyE7NTD5G2fQM1ckr Eqis+um8up/T9mgSzjpj1aLVVvlbJdz/vUcippaElpBY+Pp5TNCov8Df9dM1dljGXqgH EA6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=yc3fdvdMZXoIQBbOfrk5g2mtoncNy7PSx02ksEjgVdU=; b=rOl5tPZTZLquuNibZ0c8XJKQ+nSvx3PQprSxmOW9OVm3ZAqMMOVNLied+M6f1jXQrj 3N6XKvRzPQdVGCQkbqSjkh9LinkDvOTQkxkxsKqTn1cfq0d6wRf6yh1l63SW6l/hB0Aj u8x6baOrUxfHL9XQAvIy7yZrnzHXAi639Zxh/B0gt7pL/P8YlaR0FSO8DezTniuypkc3 31LYypM088GunPSOimcy4XBKuZ3j+uQi081b8DkXLXH4wzJ2i4rit39taGmYQK1rMcl7 UpR5S9aSooCeVJtT5akO68i+ptTu9ed0xsWBj2kk2jpRU4lq1KVuYVMMZnjbIXamPn7D TeXg== X-Gm-Message-State: AOAM532Mqrb4cNFsDuqvfP7QSWoEb1ozTt2lioZ9MtTRFJSIRFuFOLFm bSpgz642PjP642XRwHIGE/I= X-Google-Smtp-Source: ABdhPJzAN2rJKsy409i1Pukz6IpTay5+eISlUAJdlHmhNMu8QMcUB2oDLFKK0OgQw4talgDAaoV9mw== X-Received: by 2002:a05:6402:1245:: with SMTP id l5mr10762274edw.68.1604841612472; Sun, 08 Nov 2020 05:20:12 -0800 (PST) Received: from localhost.localdomain ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id og19sm5967094ejb.7.2020.11.08.05.20.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Nov 2020 05:20:11 -0800 (PST) From: Vladimir Oltean To: Andrew Lunn , Vivien Didelot , Florian Fainelli , Jakub Kicinski , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: DENG Qingfang , Tobias Waldekranz , Marek Behun , Russell King - ARM Linux admin Subject: [RFC PATCH net-next 1/3] net: dsa: don't use switchdev_notifier_fdb_info in dsa_switchdev_event_work Date: Sun, 8 Nov 2020 15:19:51 +0200 Message-Id: <20201108131953.2462644-2-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201108131953.2462644-1-olteanv@gmail.com> References: <20201108131953.2462644-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 Currently DSA doesn't add FDB entries on the CPU port, because it only does so through switchdev events added_by_user and associated with a DSA net_device, and there are none of those for the CPU port. But actually FDB entries towards the CPU port make sense for some use cases where certain addresses need to be processed in software, and in that case we need to call dsa_switchdev_event_work. There is just one problem with the existing code: it passes a structure in dsa_switchdev_event_work which was retrieved directly from switchdev, so it contains a net_device. We need to generalize the contents to something that covers the CPU port as well: the "ds, port" tuple is fine for that. Note that the new procedure for notifying the successful FDB offload is inspired from the rocker model. Also, nothing was being done if added_by_user was false. Let's check for that a lot earlier, and don't actually bother to schedule the whole workqueue for nothing. Signed-off-by: Vladimir Oltean --- net/dsa/dsa_priv.h | 12 ++++++ net/dsa/slave.c | 100 ++++++++++++++++++++++----------------------- 2 files changed, 62 insertions(+), 50 deletions(-) diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 12998bf04e55..03671ed984a1 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -73,6 +73,18 @@ struct dsa_notifier_mtu_info { int mtu; }; +struct dsa_switchdev_event_work { + struct dsa_switch *ds; + int port; + struct work_struct work; + unsigned long event; + /* Specific for SWITCHDEV_FDB_ADD_TO_DEVICE and + * SWITCHDEV_FDB_DEL_TO_DEVICE + */ + unsigned char addr[ETH_ALEN]; + u16 vid; +}; + struct dsa_slave_priv { /* Copy of CPU port xmit for faster access in slave transmit hot path */ struct sk_buff * (*xmit)(struct sk_buff *skb, diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 59c80052e950..30db8230e30b 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2062,72 +2062,62 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, return NOTIFY_DONE; } -struct dsa_switchdev_event_work { - struct work_struct work; - struct switchdev_notifier_fdb_info fdb_info; - struct net_device *dev; - unsigned long event; -}; +static void +dsa_fdb_offload_notify(struct dsa_switchdev_event_work *switchdev_work) +{ + struct dsa_switch *ds = switchdev_work->ds; + struct dsa_port *dp = dsa_to_port(ds, switchdev_work->port); + struct switchdev_notifier_fdb_info info; + + if (!dsa_is_user_port(ds, dp->index)) + return; + + info.addr = switchdev_work->addr; + info.vid = switchdev_work->vid; + info.offloaded = true; + call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, + dp->slave, &info.info, NULL); +} static void dsa_slave_switchdev_event_work(struct work_struct *work) { struct dsa_switchdev_event_work *switchdev_work = container_of(work, struct dsa_switchdev_event_work, work); - struct net_device *dev = switchdev_work->dev; - struct switchdev_notifier_fdb_info *fdb_info; - struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = switchdev_work->ds; + struct dsa_port *dp; int err; + dp = dsa_to_port(ds, switchdev_work->port); + rtnl_lock(); switch (switchdev_work->event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: - fdb_info = &switchdev_work->fdb_info; - if (!fdb_info->added_by_user) - break; - - err = dsa_port_fdb_add(dp, fdb_info->addr, fdb_info->vid); + err = dsa_port_fdb_add(dp, switchdev_work->addr, + switchdev_work->vid); if (err) { - netdev_dbg(dev, "fdb add failed err=%d\n", err); + dev_dbg(ds->dev, "port %d fdb add failed err=%d\n", + dp->index, err); break; } - fdb_info->offloaded = true; - call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED, dev, - &fdb_info->info, NULL); + dsa_fdb_offload_notify(switchdev_work); break; case SWITCHDEV_FDB_DEL_TO_DEVICE: - fdb_info = &switchdev_work->fdb_info; - if (!fdb_info->added_by_user) - break; - - err = dsa_port_fdb_del(dp, fdb_info->addr, fdb_info->vid); + err = dsa_port_fdb_del(dp, switchdev_work->addr, + switchdev_work->vid); if (err) { - netdev_dbg(dev, "fdb del failed err=%d\n", err); - dev_close(dev); + dev_dbg(ds->dev, "port %d fdb del failed err=%d\n", + dp->index, err); + if (dsa_is_user_port(ds, dp->index)) + dev_close(dp->slave); } break; } rtnl_unlock(); - kfree(switchdev_work->fdb_info.addr); kfree(switchdev_work); - dev_put(dev); -} - -static int -dsa_slave_switchdev_fdb_work_init(struct dsa_switchdev_event_work * - switchdev_work, - const struct switchdev_notifier_fdb_info * - fdb_info) -{ - memcpy(&switchdev_work->fdb_info, fdb_info, - sizeof(switchdev_work->fdb_info)); - switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC); - if (!switchdev_work->fdb_info.addr) - return -ENOMEM; - ether_addr_copy((u8 *)switchdev_work->fdb_info.addr, - fdb_info->addr); - return 0; + if (dsa_is_user_port(ds, dp->index)) + dev_put(dp->slave); } /* Called under rcu_read_lock() */ @@ -2135,7 +2125,9 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = switchdev_notifier_info_to_dev(ptr); + const struct switchdev_notifier_fdb_info *fdb_info; struct dsa_switchdev_event_work *switchdev_work; + struct dsa_port *dp; int err; if (event == SWITCHDEV_PORT_ATTR_SET) { @@ -2148,20 +2140,32 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, if (!dsa_slave_dev_check(dev)) return NOTIFY_DONE; + dp = dsa_slave_to_port(dev); + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); if (!switchdev_work) return NOTIFY_BAD; INIT_WORK(&switchdev_work->work, dsa_slave_switchdev_event_work); - switchdev_work->dev = dev; + switchdev_work->ds = dp->ds; + switchdev_work->port = dp->index; switchdev_work->event = event; switch (event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: - if (dsa_slave_switchdev_fdb_work_init(switchdev_work, ptr)) - goto err_fdb_work_init; + fdb_info = ptr; + + if (!fdb_info->added_by_user) { + kfree(switchdev_work); + return NOTIFY_OK; + } + + ether_addr_copy(switchdev_work->addr, + fdb_info->addr); + switchdev_work->vid = fdb_info->vid; + dev_hold(dev); break; default: @@ -2171,10 +2175,6 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, dsa_schedule_work(&switchdev_work->work); return NOTIFY_OK; - -err_fdb_work_init: - kfree(switchdev_work); - return NOTIFY_BAD; } static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused, From patchwork Sun Nov 8 13:19:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 11889545 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80431C4741F for ; Sun, 8 Nov 2020 13:22:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 50FB1206E3 for ; Sun, 8 Nov 2020 13:22:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rsSQheMV" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728650AbgKHNWu (ORCPT ); Sun, 8 Nov 2020 08:22:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727958AbgKHNUP (ORCPT ); Sun, 8 Nov 2020 08:20:15 -0500 Received: from mail-ed1-x542.google.com (mail-ed1-x542.google.com [IPv6:2a00:1450:4864:20::542]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 01CFFC0613D3; Sun, 8 Nov 2020 05:20:15 -0800 (PST) Received: by mail-ed1-x542.google.com with SMTP id cq7so5695143edb.4; Sun, 08 Nov 2020 05:20:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lpdz9hde6szrI40H2myatWiWZrz5F2eNJ3GGC/UNQXw=; b=rsSQheMVpiselxS+tPVy9yVz6qk9fLpF4I0AYg/Qp/54XXzvNT9Bse33Sgr/2oqIIg Wqtgbxwy7aZy1THr16HdBue5F7sTaHevsYljyDj0IkeH4vKSqDIn4YlazwvpliO0y71q j08GF0lPVujpjsj/Zfsb1pDh3vYKKBgCmmrwnQr67uX9XhPwoeLrTIY2ME8rA7iPDmL7 cI9UhQP4UqbuuoBsph4wtB7ClOMJFvh8nDCzyAkj55rmNgkwyVKyyi8ENlCBQ3ZWO5oQ FVXOwlJpd4I46fqz2op5w+lBFQGyHERzn9cIudlY6cGtoq//bkYo66GfHHRLFJ/6pzz2 D9XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lpdz9hde6szrI40H2myatWiWZrz5F2eNJ3GGC/UNQXw=; b=OeJqON30LmdoK0zspysZYVBC4vewfIDxOLnBtXsKz+g/A1Geik0Td0BmcZcOGXEAoi FrpINFsIoNfrUaPAjCpUM2NRqQWnUIJ0WIqGXX8aRz05fyvtk3l15IrAgvSE8jacHAIm q8b2O3Z0IUuuZl/67rMvMZKYzytr6/MhwKw+1Kh3PL44st7PO8uQtG/pYzR2ZWKK+AXQ gCuq6u74x4xOZE4kOGCWlqC/ntI4s3627knE/jNmoMDLGW90F2t0kbC5WAxnX+cYmYzE phD5BCHJqoOlKBzoa08h0g3bDH3XxRI1Z818x8F9KCiP6rs80JhGJ8V0vDC1qpp366ah pUyg== X-Gm-Message-State: AOAM532cyLPP52ALSIvYzktjlCRjoh8/lCC8mt4NWoYgUWrkPPIFTOYy vCbfDEei9Y3hDwrt33OvS3Q= X-Google-Smtp-Source: ABdhPJwM6EIsIRQemRI40yBUHDmanbtFBDwTFzjfFWw5eVpWWLfQ40JLfPVzPK62XwIljf+8CTKB8A== X-Received: by 2002:aa7:d408:: with SMTP id z8mr10505109edq.166.1604841613697; Sun, 08 Nov 2020 05:20:13 -0800 (PST) Received: from localhost.localdomain ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id og19sm5967094ejb.7.2020.11.08.05.20.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Nov 2020 05:20:13 -0800 (PST) From: Vladimir Oltean To: Andrew Lunn , Vivien Didelot , Florian Fainelli , Jakub Kicinski , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: DENG Qingfang , Tobias Waldekranz , Marek Behun , Russell King - ARM Linux admin Subject: [RFC PATCH net-next 2/3] net: dsa: move switchdev event implementation under the same switch/case statement Date: Sun, 8 Nov 2020 15:19:52 +0200 Message-Id: <20201108131953.2462644-3-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201108131953.2462644-1-olteanv@gmail.com> References: <20201108131953.2462644-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 We'll need to start listening to SWITCHDEV_FDB_{ADD,DEL}_TO_DEVICE events even for interfaces where dsa_slave_dev_check returns false, so we need that check inside the switch-case statement for SWITCHDEV_FDB_*. This movement also avoids two useless allocation / free paths for switchdev_work, which were difficult to avoid before, due to the code's structure: - on the untreated "default event" case. - on the case where fdb_info->added_by_user is false. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- net/dsa/slave.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 30db8230e30b..b34da39722c7 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2130,50 +2130,45 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, struct dsa_port *dp; int err; - if (event == SWITCHDEV_PORT_ATTR_SET) { + switch (event) { + case SWITCHDEV_PORT_ATTR_SET: err = switchdev_handle_port_attr_set(dev, ptr, dsa_slave_dev_check, dsa_slave_port_attr_set); return notifier_from_errno(err); - } - - if (!dsa_slave_dev_check(dev)) - return NOTIFY_DONE; - - dp = dsa_slave_to_port(dev); - - switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); - if (!switchdev_work) - return NOTIFY_BAD; - - INIT_WORK(&switchdev_work->work, - dsa_slave_switchdev_event_work); - switchdev_work->ds = dp->ds; - switchdev_work->port = dp->index; - switchdev_work->event = event; - - switch (event) { case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: fdb_info = ptr; - if (!fdb_info->added_by_user) { - kfree(switchdev_work); + if (!dsa_slave_dev_check(dev)) + return NOTIFY_DONE; + + if (!fdb_info->added_by_user) return NOTIFY_OK; - } + + dp = dsa_slave_to_port(dev); + + switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); + if (!switchdev_work) + return NOTIFY_BAD; + + INIT_WORK(&switchdev_work->work, + dsa_slave_switchdev_event_work); + switchdev_work->ds = dp->ds; + switchdev_work->port = dp->index; + switchdev_work->event = event; ether_addr_copy(switchdev_work->addr, fdb_info->addr); switchdev_work->vid = fdb_info->vid; dev_hold(dev); + dsa_schedule_work(&switchdev_work->work); break; default: - kfree(switchdev_work); return NOTIFY_DONE; } - dsa_schedule_work(&switchdev_work->work); return NOTIFY_OK; } From patchwork Sun Nov 8 13:19:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 11889547 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 748E3C388F9 for ; Sun, 8 Nov 2020 13:22:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2691820719 for ; Sun, 8 Nov 2020 13:22:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tMUonkDY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728511AbgKHNWW (ORCPT ); Sun, 8 Nov 2020 08:22:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55286 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728104AbgKHNUR (ORCPT ); Sun, 8 Nov 2020 08:20:17 -0500 Received: from mail-ed1-x544.google.com (mail-ed1-x544.google.com [IPv6:2a00:1450:4864:20::544]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3CF2FC0613D4; Sun, 8 Nov 2020 05:20:16 -0800 (PST) Received: by mail-ed1-x544.google.com with SMTP id v4so5904352edi.0; Sun, 08 Nov 2020 05:20:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=btNm+7NkM4nMOz6PjQpFgxw9zsVPe2xepBIf2Pk6auk=; b=tMUonkDYyTtsjJwMx0G3T6uiNiuiZRCPRTfqETb73mDtjFm3zum/LlA7RBNAkET/Hd jhRttKpXEcK8zw14siGcJNGgv4af5N/ZzGShAViZSZ6ckkIQfh1SBcTiFhQuoC9VzKdn gCikL+Hh9XAZP2PwkEA8vElspIfCuXQaW1oDZs6QUUSM7xtXFjSUCp0lVDE+3wBbIxKu J+kuG2cLSrMvaw59XF8AeoADNYFBUB/A+/1Mcysmf1VA70Tyrf00AJAQPnjecnVfHxS2 XKR9mFXdCAk8FFCMv1GGWKvLIrUOZ+DmGqmU86Ak4aCpkDNNawgCAYgwgK2oqwRc55UT Uyag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=btNm+7NkM4nMOz6PjQpFgxw9zsVPe2xepBIf2Pk6auk=; b=TDC0pQXCFVrtP9uBij8ga9r/5bWfwSwQyOyV9MwLSrpC4ReHDhODosRewrpwHVF1WO caqxzDppDPuLfc8Aw4PzG8/1COoDmdwTzLeVUSoDoIfSmxkSaJN91JFODr2lVh8WL3Vj o6Ja47mr5mTZbFmNl3RnTL1dpuxNtzxIUdQ0TedqRd1/HVmAtpWeJ+0GWidSi0uLuwHu ck3MzqbCmMyJE8BJ6jYTRrMCl3iNmqPsZy1qC/9vhYMHb1KphnGNt5SY0Nv700WF0Cnt 1RJJcdeEXSeEudTvCf2ZmwS0niTYyIWMdGTNizxa51GQgf6OR5Wvy7vBZ6xy3kbp50aq EFtQ== X-Gm-Message-State: AOAM533pYqINi10LbVt/MHpK0wsqnz6GZQkkhJGzRkiI30AX0hQZrRMT mEsnwuRWONX0Vpc4tgIr/Co= X-Google-Smtp-Source: ABdhPJxyaK3MyN2t+U67VNfNOYbEuVnSx0SIr7c/n5lr+JpKUGnceoUaMIIKKvbeogzAqqz1QAFvBg== X-Received: by 2002:a50:950e:: with SMTP id u14mr10614033eda.260.1604841614912; Sun, 08 Nov 2020 05:20:14 -0800 (PST) Received: from localhost.localdomain ([188.25.2.177]) by smtp.gmail.com with ESMTPSA id og19sm5967094ejb.7.2020.11.08.05.20.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Nov 2020 05:20:14 -0800 (PST) From: Vladimir Oltean To: Andrew Lunn , Vivien Didelot , Florian Fainelli , Jakub Kicinski , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: DENG Qingfang , Tobias Waldekranz , Marek Behun , Russell King - ARM Linux admin Subject: [RFC PATCH net-next 3/3] net: dsa: listen for SWITCHDEV_{FDB,DEL}_ADD_TO_DEVICE on foreign bridge neighbors Date: Sun, 8 Nov 2020 15:19:53 +0200 Message-Id: <20201108131953.2462644-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201108131953.2462644-1-olteanv@gmail.com> References: <20201108131953.2462644-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 Some DSA switches (and not only) cannot learn source MAC addresses from packets injected from the CPU. They only perform hardware address learning from inbound traffic. This can be problematic when we have a bridge spanning some DSA switch ports and some non-DSA ports (which we'll call "foreign interfaces" from DSA's perspective). There are 2 classes of problems created by the lack of learning on CPU-injected traffic: - excessive flooding, due to the fact that DSA treats those addresses as unknown - the risk of stale routes, which can lead to temporary packet loss To illustrate the second class, consider the following situation, which is common in production equipment (wireless access points, where there is a WLAN interface and an Ethernet switch, and these form a single bridging domain). AP 1: +------------------------------------------------------------------------+ | br0 | +------------------------------------------------------------------------+ +------------+ +------------+ +------------+ +------------+ +------------+ | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | +------------+ +------------+ +------------+ +------------+ +------------+ | ^ ^ | | | | | | | Client A Client B | | | +------------+ +------------+ +------------+ +------------+ +------------+ | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | +------------+ +------------+ +------------+ +------------+ +------------+ +------------------------------------------------------------------------+ | br0 | +------------------------------------------------------------------------+ AP 2 - br0 of AP 1 will know that Clients A and B are reachable via wlan0 - the hardware fdb of a DSA switch driver today is not kept in sync with the software entries on other bridge ports, so it will not know that clients A and B are reachable via the CPU port UNLESS the hardware switch itself performs SA learning from traffic injected from the CPU. Nonetheless, a substantial number of switches don't. - the hardware fdb of the DSA switch on AP 2 may autonomously learn that Client A and B are reachable through swp0. Therefore, the software br0 of AP 2 also may or may not learn this. In the example we're illustrating, some Ethernet traffic has been going on, and br0 from AP 2 has indeed learnt that it can reach Client B through swp0. One of the wireless clients, say Client B, disconnects from AP 1 and roams to AP 2. The topology now looks like this: AP 1: +------------------------------------------------------------------------+ | br0 | +------------------------------------------------------------------------+ +------------+ +------------+ +------------+ +------------+ +------------+ | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | +------------+ +------------+ +------------+ +------------+ +------------+ | ^ | | | Client A | | | Client B | | | v +------------+ +------------+ +------------+ +------------+ +------------+ | swp0 | | swp1 | | swp2 | | swp3 | | wlan0 | +------------+ +------------+ +------------+ +------------+ +------------+ +------------------------------------------------------------------------+ | br0 | +------------------------------------------------------------------------+ AP 2 - br0 of AP 1 still knows that Client A is reachable via wlan0 (no change) - br0 of AP 1 will (possibly) know that Client B has left wlan0. There are cases where it might never find out though. Either way, DSA today does not process that notification in any way. - the hardware FDB of the DSA switch on AP 1 may learn autonomously that Client B can be reached via swp0, if it receives any packet with Client 1's source MAC address over Ethernet. - the hardware FDB of the DSA switch on AP 2 still thinks that Client B can be reached via swp0. It does not know that it has roamed to wlan0, because it doesn't perform SA learning from the CPU port. Now Client A contacts Client B. AP 1 routes the packet fine towards swp0 and delivers it on the Ethernet segment. AP 2 sees a frame on swp0 and its fdb says that the destination is swp0. Hairpinning is disabled => drop. This problem comes from the fact that these switches have a 'blind spot' for addresses coming from software bridging. The generic solution is not to assume that hardware learning can be enabled somehow, but to listen to more bridge learning events. It turns out that the bridge driver does learn in software from all inbound frames, in __br_handle_local_finish. A proper SWITCHDEV_FDB_ADD_TO_DEVICE notification is emitted for the addresses serviced by the bridge on 'foreign' interfaces. The problem is that DSA currently only cares about SWITCHDEV_FDB_ADD_TO_DEVICE events received on its own interfaces, such as static FDB entries. Luckily we can change that, and DSA can listen to all switchdev FDB add/del events in the system and figure out if those events were emitted by a bridge that spans at least one of DSA's own ports. In case that is true, DSA will also offload that address towards its own CPU port, in the eventuality that there might be bridge clients attached to the DSA switch who want to talk to the station connected to the foreign interface. Reported-by: DENG Qingfang Signed-off-by: Vladimir Oltean --- net/dsa/slave.c | 51 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index b34da39722c7..5b3b07a39105 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2120,6 +2120,28 @@ static void dsa_slave_switchdev_event_work(struct work_struct *work) dev_put(dp->slave); } +static int dsa_lower_dev_walk(struct net_device *lower_dev, + struct netdev_nested_priv *priv) +{ + if (dsa_slave_dev_check(lower_dev)) { + priv->data = netdev_priv(lower_dev); + return 1; + } + + return 0; +} + +struct dsa_slave_priv *dsa_slave_dev_lower_find(struct net_device *dev) +{ + struct netdev_nested_priv priv = { + .data = NULL, + }; + + netdev_walk_all_lower_dev_rcu(dev, dsa_lower_dev_walk, &priv); + + return priv.data; +} + /* Called under rcu_read_lock() */ static int dsa_slave_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) @@ -2140,13 +2162,32 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, case SWITCHDEV_FDB_DEL_TO_DEVICE: fdb_info = ptr; - if (!dsa_slave_dev_check(dev)) - return NOTIFY_DONE; + if (dsa_slave_dev_check(dev)) { + if (!fdb_info->added_by_user) + return NOTIFY_OK; + + dp = dsa_slave_to_port(dev); + } else { + /* Snoop addresses learnt on foreign interfaces + * bridged with us, for switches that don't + * automatically learn SA from CPU-injected traffic + */ + struct net_device *br_dev; + struct dsa_slave_priv *p; - if (!fdb_info->added_by_user) - return NOTIFY_OK; + br_dev = netdev_master_upper_dev_get_rcu(dev); + if (!br_dev) + return NOTIFY_DONE; - dp = dsa_slave_to_port(dev); + if (!netif_is_bridge_master(br_dev)) + return NOTIFY_DONE; + + p = dsa_slave_dev_lower_find(br_dev); + if (!p) + return NOTIFY_DONE; + + dp = p->dp->cpu_dp; + } switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); if (!switchdev_work)