From patchwork Thu May 2 12:29:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Beh=C3=BAn?= X-Patchwork-Id: 13651684 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 87C591CD39 for ; Thu, 2 May 2024 12:29:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714652968; cv=none; b=JyGLS5eDHXyROYLeK6Y1RlEC8RizkIiqxH+r9rVXBewWMW/W83DNoYyIXs5FyPK1sInJVfGrdonxoA5hEJXnlVEWoAaRMLNxH3aIVogEvDK/Oa81gVZC29o5dZdK36HOG4bRLdXJ58pFnDCsqcphx7Pn47gFe0hBNnE72U1RYC8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714652968; c=relaxed/simple; bh=9azVaDYx8Hf2BII3OMntXoB0smdteY8jXBXkGincjrg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=QcnqbvhwPK4V7R8LiG79RqvA7q0Ae8R5CGarwRfZBxEm86jkYW2ShAHuyOABXMHYfTxfI7ffBf+11CXxXB8PKAQts6u54M/YZ0Pxv/YxWmMWuxm+c23NeURusQKFRSi8G4MaqBkoYLFny+mbPAV547g+b0Gy0k+SpasCJsdKJ90= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bbA4Nz5K; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bbA4Nz5K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D6FABC4AF18; Thu, 2 May 2024 12:29:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714652968; bh=9azVaDYx8Hf2BII3OMntXoB0smdteY8jXBXkGincjrg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bbA4Nz5Kxsa3FVBXg1eyurCEBn74SIrfWK2nmbwt7n6JWA9ZLq5MggrUx7HviU66q gyG3x27Jvrft9b7oJzhxiDdyq/LAqJsJDPjTtJgtwu/SvGT77W/8B0MmyOWnl/VSwr fr9zeD9HOfeURFdLJGmY5p94f+ry7UtZwrzDzwIptTDeqy9sUfZjy9xUL95Ccel5Ql 4dABs4gedsLsr4cISNdMfSAV6GnHA/tk8SipVfhj7pG9KGgDXtE5O1h+/8iL1fLdzl rniiQOW/0jZ9yV/pfGqJfmF4ws+MLXmYvuWJn4omEf6mnjwuoJQ9Eu1feKs+I0kn5j JOuR3v+LoqsZg== From: =?utf-8?q?Marek_Beh=C3=BAn?= To: netdev@vger.kernel.org, Andrew Lunn , Florian Fainelli , Vladimir Oltean Cc: =?utf-8?q?Marek_Beh=C3=BAn?= Subject: [PATCH net-next v2 1/2] net: dsa: deduplicate code adding / deleting the port address to fdb Date: Thu, 2 May 2024 14:29:21 +0200 Message-ID: <20240502122922.28139-2-kabel@kernel.org> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240502122922.28139-1-kabel@kernel.org> References: <20240502122922.28139-1-kabel@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org The sequence if (dsa_switch_supports_uc_filtering(ds)) dsa_port_standalone_host_fdb_add(dp, addr, 0); if (!ether_addr_equal(addr, conduit->dev_addr)) dev_uc_add(conduit, addr); is executed both in dsa_user_open() and dsa_user_set_mac_addr(). Its reverse is executed both in dsa_user_close() and dsa_user_set_mac_addr(). Refactor these sequences into new functions dsa_user_host_uc_install() and dsa_user_host_uc_uninstall(). Signed-off-by: Marek BehĂșn --- net/dsa/user.c | 91 ++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/net/dsa/user.c b/net/dsa/user.c index c94b868855aa..b1d8d1827f91 100644 --- a/net/dsa/user.c +++ b/net/dsa/user.c @@ -355,60 +355,82 @@ static int dsa_user_get_iflink(const struct net_device *dev) return READ_ONCE(dsa_user_to_conduit(dev)->ifindex); } -static int dsa_user_open(struct net_device *dev) +static int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr) { struct net_device *conduit = dsa_user_to_conduit(dev); struct dsa_port *dp = dsa_user_to_port(dev); struct dsa_switch *ds = dp->ds; int err; - err = dev_open(conduit, NULL); - if (err < 0) { - netdev_err(dev, "failed to open conduit %s\n", conduit->name); - goto out; - } - if (dsa_switch_supports_uc_filtering(ds)) { - err = dsa_port_standalone_host_fdb_add(dp, dev->dev_addr, 0); + err = dsa_port_standalone_host_fdb_add(dp, addr, 0); if (err) goto out; } - if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr)) { - err = dev_uc_add(conduit, dev->dev_addr); + if (!ether_addr_equal(addr, conduit->dev_addr)) { + err = dev_uc_add(conduit, addr); if (err < 0) goto del_host_addr; } - err = dsa_port_enable_rt(dp, dev->phydev); - if (err) - goto del_unicast; - return 0; -del_unicast: - if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr)) - dev_uc_del(conduit, dev->dev_addr); del_host_addr: if (dsa_switch_supports_uc_filtering(ds)) - dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0); + dsa_port_standalone_host_fdb_del(dp, addr, 0); out: return err; } -static int dsa_user_close(struct net_device *dev) +static void dsa_user_host_uc_uninstall(struct net_device *dev) { struct net_device *conduit = dsa_user_to_conduit(dev); struct dsa_port *dp = dsa_user_to_port(dev); struct dsa_switch *ds = dp->ds; - dsa_port_disable_rt(dp); - if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr)) dev_uc_del(conduit, dev->dev_addr); if (dsa_switch_supports_uc_filtering(ds)) dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0); +} + +static int dsa_user_open(struct net_device *dev) +{ + struct net_device *conduit = dsa_user_to_conduit(dev); + struct dsa_port *dp = dsa_user_to_port(dev); + int err; + + err = dev_open(conduit, NULL); + if (err < 0) { + netdev_err(dev, "failed to open conduit %s\n", conduit->name); + goto out; + } + + err = dsa_user_host_uc_install(dev, dev->dev_addr); + if (err) + goto out; + + err = dsa_port_enable_rt(dp, dev->phydev); + if (err) + goto out_del_host_uc; + + return 0; + +out_del_host_uc: + dsa_user_host_uc_uninstall(dev); +out: + return err; +} + +static int dsa_user_close(struct net_device *dev) +{ + struct dsa_port *dp = dsa_user_to_port(dev); + + dsa_port_disable_rt(dp); + + dsa_user_host_uc_uninstall(dev); return 0; } @@ -448,7 +470,6 @@ static void dsa_user_set_rx_mode(struct net_device *dev) static int dsa_user_set_mac_address(struct net_device *dev, void *a) { - struct net_device *conduit = dsa_user_to_conduit(dev); struct dsa_port *dp = dsa_user_to_port(dev); struct dsa_switch *ds = dp->ds; struct sockaddr *addr = a; @@ -470,34 +491,16 @@ static int dsa_user_set_mac_address(struct net_device *dev, void *a) if (!(dev->flags & IFF_UP)) goto out_change_dev_addr; - if (dsa_switch_supports_uc_filtering(ds)) { - err = dsa_port_standalone_host_fdb_add(dp, addr->sa_data, 0); - if (err) - return err; - } - - if (!ether_addr_equal(addr->sa_data, conduit->dev_addr)) { - err = dev_uc_add(conduit, addr->sa_data); - if (err < 0) - goto del_unicast; - } - - if (!ether_addr_equal(dev->dev_addr, conduit->dev_addr)) - dev_uc_del(conduit, dev->dev_addr); + err = dsa_user_host_uc_install(dev, addr->sa_data); + if (err) + return err; - if (dsa_switch_supports_uc_filtering(ds)) - dsa_port_standalone_host_fdb_del(dp, dev->dev_addr, 0); + dsa_user_host_uc_uninstall(dev); out_change_dev_addr: eth_hw_addr_set(dev, addr->sa_data); return 0; - -del_unicast: - if (dsa_switch_supports_uc_filtering(ds)) - dsa_port_standalone_host_fdb_del(dp, addr->sa_data, 0); - - return err; } struct dsa_user_dump_ctx { From patchwork Thu May 2 12:29:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Beh=C3=BAn?= X-Patchwork-Id: 13651685 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6C6F80028 for ; Thu, 2 May 2024 12:29:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714652969; cv=none; b=VPk1wpON59Vytyqk/EATFtImxR+Fw/lJCw9/8rcQq3yEg8M4QFb30zUqJoz0oNPbdd2YiCj3lkzQp/6Qcg3Ia+75zkJdyyN9UQCe76rWhWXJWcqt/ngBrYuEYl8xXiJa5YfLaUn/VS0bLVdz3OPaQSIYKHCQIOC4Vr2Xdl4NR/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714652969; c=relaxed/simple; bh=uSpwPlMaWkCNTNLi9NPx1KH8LbWug9nQARrsTq8Rzm8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HK62F36dbI7Gt8VDuiFKBimcCcQWdp3nLZz4TwKYBiV2G0Dm4AdDvZcvsdymt23bzSKfvDmPQ9ejfiU5YLKhp7BL9r14itVXzcQV8gGXqXOJLqYK1nXjXmrhWY+HD57atzMrQuZ9HFbvFgUpBnGlGH14FOGepXmtSegcQETchsI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IN5hyfCy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IN5hyfCy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 74140C4AF48; Thu, 2 May 2024 12:29:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1714652969; bh=uSpwPlMaWkCNTNLi9NPx1KH8LbWug9nQARrsTq8Rzm8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IN5hyfCy2NPwWsx5VVTUu5AP4Y8PDO92zGyNfGCtOl70Oj9+JMmnUuo4bHv7hxv+o OHXUuxe9oh9BFUcv0Z3YeL4qrVmXM3B5U9dMmQPsLkAWfA6UltkWPtt/Z+ISWZ8QXx 9vXKnslioJKX8Y1pW5bYXIcYDPYyPDLkHmGT0pbfDP9uQKuaImGnohEPJTqTtRqJvX hPb4Lzyv0f6CGGm5UAWiDhRKRHCJZeBKlNxBr1muykAnQvjvyoN8jbi9l1LhHQ7Nyw KBImcB+y04att91SfGowqdgyd4T76hLrAArOYwnBxH5cUgm/PhqoXQlLF/WcdQHv9/ 5CbMzb043009g== From: =?utf-8?q?Marek_Beh=C3=BAn?= To: netdev@vger.kernel.org, Andrew Lunn , Florian Fainelli , Vladimir Oltean Cc: =?utf-8?q?Marek_Beh=C3=BAn?= Subject: [PATCH net-next v2 2/2] net: dsa: update the unicast MAC address when changing conduit Date: Thu, 2 May 2024 14:29:22 +0200 Message-ID: <20240502122922.28139-3-kabel@kernel.org> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240502122922.28139-1-kabel@kernel.org> References: <20240502122922.28139-1-kabel@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org When changing DSA user interface conduit while the user interface is up, DSA exhibits different behavior in comparison to when the interface is down. This different behavior concers the primary unicast MAC address stored in the port standalone FDB and in the conduit device UC database. If we put a switch port down while changing the conduit with ip link set sw0p0 down ip link set sw0p0 type dsa conduit conduit1 ip link set sw0p0 up we delete the address in dsa_user_close() and install the (possibly different) address in dsa_user_open(). But when changing the conduit on the fly, the old address is not deleted and the new one is not installed. Since we explicitly want to support live-changing the conduit, uninstall the old address before calling dsa_port_assign_conduit() and install the (possibly different) new address after the call. Because conduit change might also trigger address change (the user interface is supposed to inherit the conudit interface MAC address if no address is defined in hardware (dp->mac is a zero address)), move the eth_hw_addr_inherit() call from dsa_user_change_conduit() to dsa_port_change_conduit(), just before installing the new address. Fixes: 95f510d0b792 ("net: dsa: allow the DSA master to be seen and changed through rtnetlink") Signed-off-by: Marek BehĂșn Reviewed-by: Vladimir Oltean Tested-by: Vladimir Oltean --- net/dsa/port.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/dsa/user.c | 10 ++-------- net/dsa/user.h | 2 ++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/net/dsa/port.c b/net/dsa/port.c index 9a249d4ac3a5..961b2dc84512 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -1467,10 +1467,34 @@ int dsa_port_change_conduit(struct dsa_port *dp, struct net_device *conduit, */ dsa_user_unsync_ha(dev); + /* If live-changing, we also need to uninstall the user device address + * from the port FDB and the conduit interface. + */ + if (dev->flags & IFF_UP) + dsa_user_host_uc_uninstall(dev); + err = dsa_port_assign_conduit(dp, conduit, extack, true); if (err) goto rewind_old_addrs; + /* If the port doesn't have its own MAC address and relies on the DSA + * conduit's one, inherit it again from the new DSA conduit. + */ + if (is_zero_ether_addr(dp->mac)) + eth_hw_addr_inherit(dev, conduit); + + /* If live-changing, we need to install the user device address to the + * port FDB and the conduit interface. + */ + if (dev->flags & IFF_UP) { + err = dsa_user_host_uc_install(dev, dev->dev_addr); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Failed to install host UC address"); + goto rewind_addr_inherit; + } + } + dsa_user_sync_ha(dev); if (vlan_filtering) { @@ -1500,10 +1524,26 @@ int dsa_port_change_conduit(struct dsa_port *dp, struct net_device *conduit, rewind_new_addrs: dsa_user_unsync_ha(dev); + if (dev->flags & IFF_UP) + dsa_user_host_uc_uninstall(dev); + +rewind_addr_inherit: + if (is_zero_ether_addr(dp->mac)) + eth_hw_addr_inherit(dev, old_conduit); + dsa_port_assign_conduit(dp, old_conduit, NULL, false); /* Restore the objects on the old CPU port */ rewind_old_addrs: + if (dev->flags & IFF_UP) { + tmp = dsa_user_host_uc_install(dev, dev->dev_addr); + if (tmp) { + dev_err(ds->dev, + "port %d failed to restore host UC address: %pe\n", + dp->index, ERR_PTR(tmp)); + } + } + dsa_user_sync_ha(dev); if (vlan_filtering) { diff --git a/net/dsa/user.c b/net/dsa/user.c index b1d8d1827f91..b599f0e9459c 100644 --- a/net/dsa/user.c +++ b/net/dsa/user.c @@ -355,7 +355,7 @@ static int dsa_user_get_iflink(const struct net_device *dev) return READ_ONCE(dsa_user_to_conduit(dev)->ifindex); } -static int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr) +int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr) { struct net_device *conduit = dsa_user_to_conduit(dev); struct dsa_port *dp = dsa_user_to_port(dev); @@ -383,7 +383,7 @@ static int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr) return err; } -static void dsa_user_host_uc_uninstall(struct net_device *dev) +void dsa_user_host_uc_uninstall(struct net_device *dev) { struct net_device *conduit = dsa_user_to_conduit(dev); struct dsa_port *dp = dsa_user_to_port(dev); @@ -2779,12 +2779,6 @@ int dsa_user_change_conduit(struct net_device *dev, struct net_device *conduit, ERR_PTR(err)); } - /* If the port doesn't have its own MAC address and relies on the DSA - * conduit's one, inherit it again from the new DSA conduit. - */ - if (is_zero_ether_addr(dp->mac)) - eth_hw_addr_inherit(dev, conduit); - return 0; out_revert_conduit_link: diff --git a/net/dsa/user.h b/net/dsa/user.h index 996069130bea..016884bead3c 100644 --- a/net/dsa/user.h +++ b/net/dsa/user.h @@ -42,6 +42,8 @@ int dsa_user_suspend(struct net_device *user_dev); int dsa_user_resume(struct net_device *user_dev); int dsa_user_register_notifier(void); void dsa_user_unregister_notifier(void); +int dsa_user_host_uc_install(struct net_device *dev, const u8 *addr); +void dsa_user_host_uc_uninstall(struct net_device *dev); void dsa_user_sync_ha(struct net_device *dev); void dsa_user_unsync_ha(struct net_device *dev); void dsa_user_setup_tagger(struct net_device *user);