[RFC PATCH v2 1/2] linux: introduce multi-cpu dsa patch

Ansuel Smith ansuelsmth at gmail.com
Sat Jan 22 16:35:25 PST 2022


Add support for multi-cpu dsa. This is a reworked version of the RFC patch
proposed some time ago.
By default every dsa port is connected to the first cpu port and the command
'ip link set PORT cpu CPU_PORT' can be used to change the used cpu port at
runtime.
A specific function port_change_cpu_port is required to correctly setup the
port on cpu change request.

Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
---
 ...net-dsa-allow_for_multiple_CPU_ports.patch | 151 ++++++++++++++++++
 ...add_ndo_for_setting_the_cpu_property.patch | 113 +++++++++++++
 ..._set_cpu_for_changing_ports_CPU_port.patch |  89 +++++++++++
 ...clude-net-add-dsa_cpu_ports-function.patch |  34 ++++
 4 files changed, 387 insertions(+)
 create mode 100644 target/linux/generic/hack-5.10/780-1-net-dsa-allow_for_multiple_CPU_ports.patch
 create mode 100644 target/linux/generic/hack-5.10/780-2-net-add_ndo_for_setting_the_cpu_property.patch
 create mode 100644 target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_cpu_for_changing_ports_CPU_port.patch
 create mode 100644 target/linux/generic/hack-5.10/780-4-include-net-add-dsa_cpu_ports-function.patch

diff --git a/target/linux/generic/hack-5.10/780-1-net-dsa-allow_for_multiple_CPU_ports.patch b/target/linux/generic/hack-5.10/780-1-net-dsa-allow_for_multiple_CPU_ports.patch
new file mode 100644
index 00000000..7f2f349a
--- /dev/null
+++ b/target/linux/generic/hack-5.10/780-1-net-dsa-allow_for_multiple_CPU_ports.patch
@@ -0,0 +1,151 @@
+From mboxrd at z Thu Jan  1 00:00:00 1970
+Return-Path: <SRS0=lHAO=WU=vger.kernel.org=netdev-owner at kernel.org>
+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=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID,
+	DKIM_VALID_AU,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 98EBDC3A5A2
+	for <netdev at archiver.kernel.org>; Sat, 24 Aug 2019 02:43:07 +0000 (UTC)
+Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
+	by mail.kernel.org (Postfix) with ESMTP id 6168A2173B
+	for <netdev at archiver.kernel.org>; Sat, 24 Aug 2019 02:43:07 +0000 (UTC)
+Authentication-Results: mail.kernel.org;
+	dkim=pass (1024-bit key) header.d=nic.cz header.i=@nic.cz header.b="Kl8qU9Mx"
+Received: (majordomo at vger.kernel.org) by vger.kernel.org via listexpand
+        id S1726888AbfHXCnF (ORCPT <rfc822;netdev at archiver.kernel.org>);
+        Fri, 23 Aug 2019 22:43:05 -0400
+Received: from mail.nic.cz ([217.31.204.67]:37268 "EHLO mail.nic.cz"
+        rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP
+        id S1725807AbfHXCnD (ORCPT <rfc822;netdev at vger.kernel.org>);
+        Fri, 23 Aug 2019 22:43:03 -0400
+Received: from dellmb.labs.office.nic.cz (unknown [IPv6:2001:1488:fffe:6:cac7:3539:7f1f:463])
+        by mail.nic.cz (Postfix) with ESMTP id 94D1E140D1E;
+        Sat, 24 Aug 2019 04:42:59 +0200 (CEST)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=nic.cz; s=default;
+        t=1566614579; bh=jPa21EsnWy9WksW68HSx/O+la2qm4ImIACY+K2cEnLY=;
+        h=From:To:Date;
+        b=Kl8qU9MxZdC3EQnTetDA7VbGXYIuwCO2zS6HinOo7XykIKQDlvB7jIUcH0FQLgG6T
+         BNf/aIsDASIL1PBSAlNynoTMSDf8m6I2Xo8auxQr4L6sslF683w8hY9PN7f+pYyL2R
+         FQs93FIJYSp5I2NCSktTxGFNumTvYPxA8lEqBaZo=
+From:   =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.behun at nic.cz>
+To:     netdev at vger.kernel.org
+Cc:     Andrew Lunn <andrew at lunn.ch>,
+        Vivien Didelot <vivien.didelot at gmail.com>,
+        Florian Fainelli <f.fainelli at gmail.com>,
+        David Ahern <dsahern at gmail.com>,
+        Stephen Hemminger <stephen at networkplumber.org>,
+        =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.behun at nic.cz>
+Subject: [PATCH RFC net-next 1/3] net: dsa: allow for multiple CPU ports
+Date:   Sat, 24 Aug 2019 04:42:48 +0200
+Message-Id: <20190824024251.4542-2-marek.behun at nic.cz>
+X-Mailer: git-send-email 2.21.0
+In-Reply-To: <20190824024251.4542-1-marek.behun at nic.cz>
+References: <20190824024251.4542-1-marek.behun at nic.cz>
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+X-Virus-Scanned: clamav-milter 0.100.3 at mail.nic.cz
+X-Virus-Status: Clean
+Sender: netdev-owner at vger.kernel.org
+Precedence: bulk
+List-ID: <netdev.vger.kernel.org>
+X-Mailing-List: netdev at vger.kernel.org
+Archived-At: <https://lore.kernel.org/netdev/20190824024251.4542-2-marek.behun@nic.cz/>
+List-Archive: <https://lore.kernel.org/netdev/>
+List-Post: <mailto:netdev at vger.kernel.org>
+
+Allow for multiple CPU ports in a DSA switch tree. By default assign the
+CPU ports to user ports in a round robin way, ie. if there are two CPU
+ports connected to eth0 and eth1, and five user ports (lan1..lan5),
+assign them as:
+  lan1 <-> eth0
+  lan2 <-> eth1
+  lan3 <-> eth0
+  lan4 <-> eth1
+  lan5 <-> eth0
+
+Signed-off-by: Marek Behún <marek.behun at nic.cz>
+---
+ include/net/dsa.h |  5 +--
+ net/dsa/dsa2.c    | 84 +++++++++++++++++++++++++++++++----------------
+ 2 files changed, 58 insertions(+), 31 deletions(-)
+
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -211,7 +211,7 @@ static bool dsa_tree_setup_routing_table
+ 	return 0;
+ }
+ 
+-static void dsa_tree_teardown_default_cpu(struct dsa_switch_tree *dst)
++static void dsa_tree_teardown_default_cpus(struct dsa_switch_tree *dst)
+ {
+ 	struct dsa_port *dp;
+ 
+@@ -572,7 +582,7 @@ static void dsa_tree_teardown_switches(s
+ 		dsa_switch_teardown(dp->ds);
+ }
+ 
+-static int dsa_tree_setup_master(struct dsa_switch_tree *dst)
++static int dsa_tree_setup_masters(struct dsa_switch_tree *dst)
+ {
+ 	struct dsa_port *dp;
+ 	int err;
+@@ -581,14 +591,20 @@ static int dsa_tree_setup_master(struct
+ 		if (dsa_port_is_cpu(dp)) {
+ 			err = dsa_master_setup(dp->master, dp);
+ 			if (err)
+-				return err;
++				goto teardown;
+ 		}
+ 	}
+ 
+ 	return 0;
++teardown:
++	list_for_each_entry(dp, &dst->ports, list)
++		if (dsa_port_is_cpu(dp))
++			dsa_master_teardown(dp->master);
++
++	return err;
+ }
+ 
+-static void dsa_tree_teardown_master(struct dsa_switch_tree *dst)
++static void dsa_tree_teardown_masters(struct dsa_switch_tree *dst)
+ {
+ 	struct dsa_port *dp;
+ 
+@@ -620,7 +636,7 @@ static int dsa_tree_setup(struct dsa_swi
+ 	if (err)
+ 		goto teardown_default_cpu;
+ 
+-	err = dsa_tree_setup_master(dst);
++	err = dsa_tree_setup_masters(dst);
+ 	if (err)
+ 		goto teardown_switches;
+ 
+@@ -633,7 +649,7 @@ static int dsa_tree_setup(struct dsa_swi
+ teardown_switches:
+ 	dsa_tree_teardown_switches(dst);
+ teardown_default_cpu:
+-	dsa_tree_teardown_default_cpu(dst);
++	dsa_tree_teardown_default_cpus(dst);
+ 
+ 	return err;
+ }
+@@ -645,11 +661,11 @@ static void dsa_tree_teardown(struct dsa
+ 	if (!dst->setup)
+ 		return;
+ 
+-	dsa_tree_teardown_master(dst);
++	dsa_tree_teardown_masters(dst);
+ 
+ 	dsa_tree_teardown_switches(dst);
+ 
+-	dsa_tree_teardown_default_cpu(dst);
++	dsa_tree_teardown_default_cpus(dst);
+ 
+ 	list_for_each_entry_safe(dl, next, &dst->rtable, list) {
+ 		list_del(&dl->list);
diff --git a/target/linux/generic/hack-5.10/780-2-net-add_ndo_for_setting_the_cpu_property.patch b/target/linux/generic/hack-5.10/780-2-net-add_ndo_for_setting_the_cpu_property.patch
new file mode 100644
index 00000000..aeee31cd
--- /dev/null
+++ b/target/linux/generic/hack-5.10/780-2-net-add_ndo_for_setting_the_cpu_property.patch
@@ -0,0 +1,113 @@
+From 9439d87a81e3ea67f53b4e6db1e8858fdad27b48 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Sun, 23 Jan 2022 00:49:10 +0100
+Subject: [PATCH] net: add ndo for setting the cpu proprety
+
+In DSA the cpu value is used to report to which CPU port a given switch
+port is connected to. Since we want to support multi-CPU DSA, we want
+the user to be able to change this value.
+
+Add ndo_set_cpu method into the ndo structure and also create
+dev_set_cpu and call this from the netlink code, so that userspace can
+change the cpu value.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+---
+ include/linux/netdevice.h    |  5 +++++
+ include/uapi/linux/if_link.h |  1 +
+ net/core/dev.c               | 18 ++++++++++++++++++
+ net/core/rtnetlink.c         |  7 +++++++
+ 4 files changed, 31 insertions(+)
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 235d5d082f1a..b1524b92efdf 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -1301,6 +1301,8 @@ struct netdev_net_notifier {
+  *	TX queue.
+  * int (*ndo_get_iflink)(const struct net_device *dev);
+  *	Called to get the iflink value of this device.
++ * int (*ndo_set_cpu)(struct net_device *dev, int cpu);
++ *	Called to set the cpu value of this device.
+  * void (*ndo_change_proto_down)(struct net_device *dev,
+  *				 bool proto_down);
+  *	This function is used to pass protocol port error state information
+@@ -1541,6 +1543,8 @@ struct net_device_ops {
+ 						      int queue_index,
+ 						      u32 maxrate);
+ 	int			(*ndo_get_iflink)(const struct net_device *dev);
++	int			(*ndo_set_cpu)(struct net_device *dev,
++					       int cpu);
+ 	int			(*ndo_change_proto_down)(struct net_device *dev,
+ 							 bool proto_down);
+ 	int			(*ndo_fill_metadata_dst)(struct net_device *dev,
+@@ -2853,6 +2857,7 @@ void dev_add_offload(struct packet_offload *po);
+ void dev_remove_offload(struct packet_offload *po);
+ 
+ int dev_get_iflink(const struct net_device *dev);
++int dev_set_cpu(struct net_device *dev, int cpu);
+ int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
+ 			  struct net_device_path_stack *stack);
+diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
+index 4ac53b30b6dc..6a6de696854b 100644
+--- a/include/uapi/linux/if_link.h
++++ b/include/uapi/linux/if_link.h
+@@ -279,6 +279,7 @@ enum {
+ 	IFLA_BROADCAST,
+ 	IFLA_IFNAME,
+ 	IFLA_MTU,
++	IFLA_CPU,
+ 	IFLA_LINK,
+ 	IFLA_QDISC,
+ 	IFLA_STATS,
+diff --git a/net/core/dev.c b/net/core/dev.c
+index a855e41bbe39..3335e629850d 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -621,6 +621,24 @@ int dev_get_iflink(const struct net_device *dev)
+ }
+ EXPORT_SYMBOL(dev_get_iflink);
+ 
++/**
++ *	dev_set_cpu - set 'cpu' value of a dsa interface
++ *	@dev: target interface
++ *	@cpu: new value
++ *
++ *	Change the cpu port to which this dsa interface is linked to.
++ */
++int dev_set_cpu(struct net_device *dev, int cpu)
++{
++	if (!dev->dsa_ptr)
++		return -EOPNOTSUPP;
++
++	if (dev->netdev_ops && dev->netdev_ops->ndo_set_cpu)
++		return dev->netdev_ops->ndo_set_cpu(dev, cpu);
++
++	return -EOPNOTSUPP;
++}
++
+ /**
+  *	dev_fill_metadata_dst - Retrieve tunnel egress information.
+  *	@dev: targeted interface
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index d6eba554b137..199bbdad685e 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -2728,6 +2728,13 @@ static int do_setlink(const struct sk_buff *skb,
+ 		status |= DO_SETLINK_MODIFIED;
+ 	}
+ 
++	if (tb[IFLA_CPU]) {
++		err = dev_set_cpu(dev, nla_get_u32(tb[IFLA_CPU]));
++		if (err)
++			goto errout;
++		status |= DO_SETLINK_MODIFIED;
++	}
++
+ 	if (tb[IFLA_CARRIER]) {
+ 		err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER]));
+ 		if (err)
+-- 
+2.33.1
+
diff --git a/target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_cpu_for_changing_ports_CPU_port.patch b/target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_cpu_for_changing_ports_CPU_port.patch
new file mode 100644
index 00000000..62be001a
--- /dev/null
+++ b/target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_cpu_for_changing_ports_CPU_port.patch
@@ -0,0 +1,89 @@
+From:   Marek Behún <marek.behun at nic.cz>
+Subject: [PATCH RFC net-next 3/3] net: dsa: implement ndo_set_cpu for changing port's CPU port
+Date:   Sat, 24 Aug 2019 04:42:50 +0200
+
+Implement ndo_set_cpu for DSA slave device. In multi-CPU port setup
+this should be used to change to which CPU destination port a given port
+should be connected.
+
+This adds a new operation into the DSA switch operations structure,
+port_change_cpu_port. A driver implementing this function has the
+ability to change CPU destination port of a given port.
+
+Signed-off-by: Marek Behún <marek.behun at nic.cz>
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+---
+ include/net/dsa.h |  6 ++++++
+ net/dsa/slave.c   | 35 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 41 insertions(+)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -654,6 +654,12 @@ struct dsa_switch_ops {
+ 	int	(*port_change_mtu)(struct dsa_switch *ds, int port,
+ 				   int new_mtu);
+ 	int	(*port_max_mtu)(struct dsa_switch *ds, int port);
++
++	/*
++	 * Multi-CPU port support
++	 */
++	int	(*port_change_cpu_port)(struct dsa_switch *ds, int port,
++					struct dsa_port *new_cpu_dp);
+ };
+ 
+ #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes)		\
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -62,6 +62,44 @@ static int dsa_slave_get_iflink(const st
+ 	return dsa_slave_to_master(dev)->ifindex;
+ }
+ 
++static int dsa_slave_set_cpu(struct net_device *dev, int cpu)
++{
++	struct net_device *master = dsa_slave_to_master(dev);
++	struct dsa_port *dp = dsa_slave_to_port(dev);
++	struct dsa_slave_priv *p = netdev_priv(dev);
++	struct net_device *new_cpu_dev;
++	struct dsa_port *new_cpu_dp;
++	int err;
++
++	if (!dp->ds->ops->port_change_cpu_port)
++		return -EOPNOTSUPP;
++
++	new_cpu_dev = dev_get_by_index(dev_net(dev), cpu);
++	if (!new_cpu_dev)
++		return -ENODEV;
++
++	new_cpu_dp = new_cpu_dev->dsa_ptr;
++	if (!new_cpu_dp)
++		return -EINVAL;
++
++	/* new CPU port has to be on the same switch tree */
++	if (new_cpu_dp->dst != dp->cpu_dp->dst)
++		return -EINVAL;
++
++	err = dp->ds->ops->port_change_cpu_port(dp->ds, dp->index, new_cpu_dp);
++	if (err)
++		return err;
++
++	if (ether_addr_equal(dev->dev_addr, master->dev_addr))
++	 	eth_hw_addr_inherit(dev, new_cpu_dev);
++
++	/* should this be done atomically? */
++	dp->cpu_dp = new_cpu_dp;
++	p->xmit = new_cpu_dp->tag_ops->xmit;
++
++	return 0;
++}
++
+ static int dsa_slave_open(struct net_device *dev)
+ {
+ 	struct net_device *master = dsa_slave_to_master(dev);
+@@ -1667,6 +1705,7 @@ static const struct net_device_ops dsa_s
+ 	.ndo_fdb_dump		= dsa_slave_fdb_dump,
+ 	.ndo_do_ioctl		= dsa_slave_ioctl,
+ 	.ndo_get_iflink		= dsa_slave_get_iflink,
++	.ndo_set_cpu		= dsa_slave_set_cpu,
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ 	.ndo_netpoll_setup	= dsa_slave_netpoll_setup,
+ 	.ndo_netpoll_cleanup	= dsa_slave_netpoll_cleanup,
diff --git a/target/linux/generic/hack-5.10/780-4-include-net-add-dsa_cpu_ports-function.patch b/target/linux/generic/hack-5.10/780-4-include-net-add-dsa_cpu_ports-function.patch
new file mode 100644
index 00000000..d03b8e62
--- /dev/null
+++ b/target/linux/generic/hack-5.10/780-4-include-net-add-dsa_cpu_ports-function.patch
@@ -0,0 +1,34 @@
+From 2bf13a906ce96f67eb292c8e519c6d2215501d82 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth at gmail.com>
+Date: Sun, 4 Apr 2021 12:58:50 +0200
+Subject: [PATCH 1/2] include: net: add dsa_cpu_ports function
+
+dsa_cpu_ports can be useful for switch that has multiple cpu port to
+retrieve the cpu mask for ACL and bridge table.
+
+Signed-off-by: Ansuel Smith <ansuelsmth at gmail.com>
+---
+ include/net/dsa.h | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -387,6 +387,18 @@ static inline u32 dsa_user_ports(struct
+ 	return mask;
+ }
+ 
++static inline u32 dsa_cpu_ports(struct dsa_switch *ds)
++{
++	u32 mask = 0;
++	int p;
++
++	for (p = 0; p < ds->num_ports; p++)
++		if (dsa_is_cpu_port(ds, p))
++			mask |= BIT(p);
++
++	return mask;
++}
++
+ /* Return the local port used to reach an arbitrary switch device */
+ static inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device)
+ {
-- 
2.33.1




More information about the openwrt-devel mailing list