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

Daniel Golle daniel at makrotopia.org
Sat Jan 22 17:29:38 PST 2022


Please see two comments inline below

On Sun, Jan 23, 2022 at 01:35:25AM +0100, Ansuel Smith wrote:
> 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

This commit message is no longer up-to-date with the code.

> +
> +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,

The newly added attribute in the enum should be the last and not change
the order of the existing enums, so ABI compatiblity is retained as
much as possible.


> + 	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
> 
> 
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list