Add support for multi-cpu dsa. This is a reworked version of the RFC patch proposed some time ago. By default the cpus are selected in a round-robin way and the command 'ip link set PORT link CPU_PORT' can be used to change the used cpu port at runtime. A specific function port_change_cpu_port to correctly setup the port on cpu change request.
Signed-off-by: Ansuel Smith <ansuels...@gmail.com> --- ...net-dsa-allow_for_multiple_CPU_ports.patch | 159 ++++++++++++++++++ ..._ndo_for_setting_the_iflink_property.patch | 88 ++++++++++ ..._netlink_for_changing_ports_CPU_port.patch | 89 ++++++++++ ...clude-net-add-dsa_cpu_ports-function.patch | 34 ++++ 4 files changed, 370 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_iflink_property.patch create mode 100644 target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_netlink_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 0000000000..9c3a9e77e2 --- /dev/null +++ b/target/linux/generic/hack-5.10/780-1-net-dsa-allow_for_multiple_CPU_ports.patch @@ -0,0 +1,159 @@ +From: Marek Behún <marek.be...@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 + +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.be...@nic.cz> +Signed-off-by: Ansuel Smith <ansuels...@gmail.com> +--- + 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,36 +211,46 @@ static bool dsa_tree_setup_routing_table + return complete; + } + +-static struct dsa_port *dsa_tree_find_first_cpu(struct dsa_switch_tree *dst) ++static int dsa_tree_setup_default_cpus(struct dsa_switch_tree *dst) + { +- struct dsa_port *dp; +- ++ struct dsa_port *cpu_dp, *dp, *first_cpu_dp = NULL, *last_cpu_dp = NULL; ++ ++ /* Find first and last CPU port */ + list_for_each_entry(dp, &dst->ports, list) +- if (dsa_port_is_cpu(dp)) +- return dp; +- +- return NULL; +-} ++ if (dsa_port_is_cpu(dp)) { ++ if (first_cpu_dp == NULL) ++ first_cpu_dp = dp; + +-static int dsa_tree_setup_default_cpu(struct dsa_switch_tree *dst) +-{ +- struct dsa_port *cpu_dp, *dp; ++ last_cpu_dp = dp; ++ } + +- cpu_dp = dsa_tree_find_first_cpu(dst); +- if (!cpu_dp) { ++ if (first_cpu_dp == NULL) { + pr_err("DSA: tree %d has no CPU port\n", dst->index); + return -EINVAL; + } + +- /* Assign the default CPU port to all ports of the fabric */ ++ cpu_dp = first_cpu_dp; ++ ++ /* Assign the CPU ports in round-robbin way to all ports of the fabric */ + list_for_each_entry(dp, &dst->ports, list) +- if (dsa_port_is_user(dp) || dsa_port_is_dsa(dp)) ++ if (dsa_port_is_user(dp) || dsa_port_is_dsa(dp)) { + dp->cpu_dp = cpu_dp; + ++ if (cpu_dp == last_cpu_dp) ++ cpu_dp = first_cpu_dp; ++ else ++ while((cpu_dp = list_next_entry(cpu_dp, list)) != 0) ++ if (dsa_port_is_cpu(cpu_dp)) ++ break; ++ ++ if (dp->ds->ops->port_change_cpu_port) ++ dp->ds->ops->port_change_cpu_port(dp->ds, dp->index, dp->cpu_dp); ++ } ++ + 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; + +@@ -612,7 +628,7 @@ static int dsa_tree_setup(struct dsa_swi + if (!complete) + return 0; + +- err = dsa_tree_setup_default_cpu(dst); ++ err = dsa_tree_setup_default_cpus(dst); + if (err) + return err; + +@@ -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_iflink_property.patch b/target/linux/generic/hack-5.10/780-2-net-add_ndo_for_setting_the_iflink_property.patch new file mode 100644 index 0000000000..5fab81249e --- /dev/null +++ b/target/linux/generic/hack-5.10/780-2-net-add_ndo_for_setting_the_iflink_property.patch @@ -0,0 +1,88 @@ +From: Marek Behún <marek.be...@nic.cz> +Subject: [PATCH RFC net-next 2/3] net: add ndo for setting the iflink property +Date: Sat, 24 Aug 2019 04:42:49 +0200 + +In DSA the iflink 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_iflink method into the ndo strucutre to be a pair to +ndo_get_iflink. Also create dev_set_iflink and call this from the +netlink code, so that userspace can change the iflink value. + +Signed-off-by: Marek Behún <marek.be...@nic.cz> +Signed-off-by: Ansuel Smith <ansuels...@gmail.com> +--- + include/linux/netdevice.h | 5 +++++ + net/core/dev.c | 15 +++++++++++++++ + net/core/rtnetlink.c | 7 +++++++ + 3 files changed, 27 insertions(+) + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1284,6 +1284,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_iflink)(struct net_device *dev, int iflink); ++ * Called to set the iflink 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 +@@ -1519,6 +1521,8 @@ struct net_device_ops { + int queue_index, + u32 maxrate); + int (*ndo_get_iflink)(const struct net_device *dev); ++ int (*ndo_set_iflink)(struct net_device *dev, ++ int iflink); + int (*ndo_change_proto_down)(struct net_device *dev, + bool proto_down); + int (*ndo_fill_metadata_dst)(struct net_device *dev, +@@ -2896,6 +2900,7 @@ void dev_add_offload(struct packet_offlo + void dev_remove_offload(struct packet_offload *po); + + int dev_get_iflink(const struct net_device *dev); ++int dev_set_iflink(struct net_device *dev, int iflink); + 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); +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -822,6 +822,21 @@ int dev_get_iflink(const struct net_devi + EXPORT_SYMBOL(dev_get_iflink); + + /** ++ * dev_set_iflink - set 'iflink' value of an interface ++ * @dev: target interface ++ * @iflink: new value ++ * ++ * Change the interface to which this interface is linked to. ++ */ ++int dev_set_iflink(struct net_device *dev, int iflink) ++{ ++ if (dev->netdev_ops && dev->netdev_ops->ndo_set_iflink) ++ return dev->netdev_ops->ndo_set_iflink(dev, iflink); ++ ++ return -EOPNOTSUPP; ++} ++ ++/** + * dev_fill_metadata_dst - Retrieve tunnel egress information. + * @dev: targeted interface + * @skb: The packet. +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -2717,6 +2717,13 @@ static int do_setlink(const struct sk_bu + status |= DO_SETLINK_MODIFIED; + } + ++ if (tb[IFLA_LINK]) { ++ err = dev_set_iflink(dev, nla_get_u32(tb[IFLA_LINK])); ++ 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) diff --git a/target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_netlink_for_changing_ports_CPU_port.patch b/target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_netlink_for_changing_ports_CPU_port.patch new file mode 100644 index 0000000000..89d53debf8 --- /dev/null +++ b/target/linux/generic/hack-5.10/780-3-net-dsa-implement_ndo_set_netlink_for_changing_ports_CPU_port.patch @@ -0,0 +1,89 @@ +From: Marek Behún <marek.be...@nic.cz> +Subject: [PATCH RFC net-next 3/3] net: dsa: implement ndo_set_netlink for changing port's CPU port +Date: Sat, 24 Aug 2019 04:42:50 +0200 + +Implement ndo_set_iflink 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.be...@nic.cz> +Signed-off-by: Ansuel Smith <ansuels...@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_iflink(struct net_device *dev, int iflink) ++{ ++ 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), iflink); ++ 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_iflink = dsa_slave_set_iflink, + #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 0000000000..d03b8e62d7 --- /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 <ansuels...@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 <ansuels...@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.30.2.windows.1 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel