On Thu, Feb 03, 2022 at 01:44:11AM +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.

The current behavior with this patch applied is quite the opposite:
All user ports get assigned to the *last* CPU port.

Apart from that this looks good so far.

> A specific function port_change_cpu_port is required 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 |  97 +++++++++++++++
>  ...add-ndo-for-setting-the-cpu-proprety.patch | 113 ++++++++++++++++++
>  ...t-ndo_set_cpu-for-changing-DSA-port-.patch | 100 ++++++++++++++++
>  ...clude-net-add-dsa_cpu_ports-function.patch |  39 ++++++
>  4 files changed, 349 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-proprety.patch
>  create mode 100644 
> target/linux/generic/hack-5.10/780-3-net-dsa-implement-ndo_set_cpu-for-changing-DSA-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..9b4a57c6
> --- /dev/null
> +++ 
> b/target/linux/generic/hack-5.10/780-1-net-dsa-allow-for-multiple-CPU-ports.patch
> @@ -0,0 +1,97 @@
> +From 48d1e9543273c7670ebef15a4d27b13023895a28 Mon Sep 17 00:00:00 2001
> +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.be...@nic.cz>
> +Date: Sat, 24 Aug 2019 04:42:48 +0200
> +Subject: [PATCH 1/4] net: dsa: allow for multiple CPU ports
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +Allow for multiple CPU ports in a DSA switch tree. The default assing
> +logic is still used where the first defined CPU port is selected for all
> +the user ports. The CPU port has to be changed at runtime.
> +
> +Signed-off-by: Marek Behún <marek.be...@nic.cz>
> +---
> + net/dsa/dsa2.c | 22 ++++++++++++++--------
> + 1 file changed, 14 insertions(+), 8 deletions(-)
> +
> +diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
> +index 183003e45762..4a8de5e2f0f5 100644
> +--- a/net/dsa/dsa2.c
> ++++ b/net/dsa/dsa2.c
> +@@ -240,7 +240,7 @@ static int dsa_tree_setup_default_cpu(struct 
> dsa_switch_tree *dst)
> +     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;
> + 
> +@@ -553,7 +553,7 @@ static void dsa_tree_teardown_switches(struct 
> dsa_switch_tree *dst)
> +             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;
> +@@ -562,14 +562,20 @@ static int dsa_tree_setup_master(struct 
> dsa_switch_tree *dst)
> +             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;
> + 
> +@@ -601,7 +607,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
> +     if (err)
> +             goto teardown_default_cpu;
> + 
> +-    err = dsa_tree_setup_master(dst);
> ++    err = dsa_tree_setup_masters(dst);
> +     if (err)
> +             goto teardown_switches;
> + 
> +@@ -614,7 +620,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
> + teardown_switches:
> +     dsa_tree_teardown_switches(dst);
> + teardown_default_cpu:
> +-    dsa_tree_teardown_default_cpu(dst);
> ++    dsa_tree_teardown_default_cpus(dst);
> + 
> +     return err;
> + }
> +@@ -626,11 +632,11 @@ static void dsa_tree_teardown(struct dsa_switch_tree 
> *dst)
> +     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);
> +-- 
> +2.34.1
> +
> diff --git 
> a/target/linux/generic/hack-5.10/780-2-net-add-ndo-for-setting-the-cpu-proprety.patch
>  
> b/target/linux/generic/hack-5.10/780-2-net-add-ndo-for-setting-the-cpu-proprety.patch
> new file mode 100644
> index 00000000..d9441feb
> --- /dev/null
> +++ 
> b/target/linux/generic/hack-5.10/780-2-net-add-ndo-for-setting-the-cpu-proprety.patch
> @@ -0,0 +1,113 @@
> +From 07ad275393f991d29aff1e9951e01e0a1f1582b4 Mon Sep 17 00:00:00 2001
> +From: Ansuel Smith <ansuels...@gmail.com>
> +Date: Sun, 23 Jan 2022 00:49:10 +0100
> +Subject: [PATCH 2/4] 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 <ansuels...@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 7c3da0e1ea9d..c59181a116fd 100644
> +--- a/include/linux/netdevice.h
> ++++ b/include/linux/netdevice.h
> +@@ -1237,6 +1237,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
> +@@ -1470,6 +1472,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,
> +@@ -2797,6 +2801,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);
> + struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
> +                                   unsigned short mask);
> +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
> +index c4b23f06f69e..b035c911eadc 100644
> +--- a/include/uapi/linux/if_link.h
> ++++ b/include/uapi/linux/if_link.h
> +@@ -340,6 +340,7 @@ enum {
> +     IFLA_ALT_IFNAME, /* Alternative ifname */
> +     IFLA_PERM_ADDRESS,
> +     IFLA_PROTO_DOWN_REASON,
> ++    IFLA_CPU,
> +     __IFLA_MAX
> + };
> + 
> +diff --git a/net/core/dev.c b/net/core/dev.c
> +index 38412e70f761..a213719a11ed 100644
> +--- a/net/core/dev.c
> ++++ b/net/core/dev.c
> +@@ -820,6 +820,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 7d7223691783..767ac3bf6358 100644
> +--- a/net/core/rtnetlink.c
> ++++ b/net/core/rtnetlink.c
> +@@ -2716,6 +2716,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.34.1
> +
> diff --git 
> a/target/linux/generic/hack-5.10/780-3-net-dsa-implement-ndo_set_cpu-for-changing-DSA-port-.patch
>  
> b/target/linux/generic/hack-5.10/780-3-net-dsa-implement-ndo_set_cpu-for-changing-DSA-port-.patch
> new file mode 100644
> index 00000000..b6f454bf
> --- /dev/null
> +++ 
> b/target/linux/generic/hack-5.10/780-3-net-dsa-implement-ndo_set_cpu-for-changing-DSA-port-.patch
> @@ -0,0 +1,100 @@
> +From 96d426097d16234a5c0f7bf30a87a381fb7821e8 Mon Sep 17 00:00:00 2001
> +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.be...@nic.cz>
> +Date: Sat, 24 Aug 2019 04:42:50 +0200
> +Subject: [PATCH 3/4] net: dsa: implement ndo_set_cpu for changing DSA port's
> + CPU port
> +MIME-Version: 1.0
> +Content-Type: text/plain; charset=UTF-8
> +Content-Transfer-Encoding: 8bit
> +
> +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.be...@nic.cz>
> +---
> + include/net/dsa.h |  6 ++++++
> + net/dsa/slave.c   | 39 +++++++++++++++++++++++++++++++++++++++
> + 2 files changed, 45 insertions(+)
> +
> +diff --git a/include/net/dsa.h b/include/net/dsa.h
> +index 35429a140dfa..70bd07c4ea15 100644
> +--- a/include/net/dsa.h
> ++++ b/include/net/dsa.h
> +@@ -647,6 +647,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)                
> \
> +diff --git a/net/dsa/slave.c b/net/dsa/slave.c
> +index 3bc5ca40c9fb..8f871d2699c2 100644
> +--- a/net/dsa/slave.c
> ++++ b/net/dsa/slave.c
> +@@ -62,6 +62,44 @@ static int dsa_slave_get_iflink(const struct net_device 
> *dev)
> +     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);
> +@@ -1594,6 +1632,7 @@ static const struct net_device_ops 
> dsa_slave_netdev_ops = {
> +     .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,
> +-- 
> +2.34.1
> +
> 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..22f85bca
> --- /dev/null
> +++ 
> b/target/linux/generic/hack-5.10/780-4-include-net-add-dsa_cpu_ports-function.patch
> @@ -0,0 +1,39 @@
> +From 7085cfadfc26f4483c544790c80b3fc6acf1bdb3 Mon Sep 17 00:00:00 2001
> +From: Ansuel Smith <ansuels...@gmail.com>
> +Date: Sun, 4 Apr 2021 12:58:50 +0200
> +Subject: [PATCH 4/4] 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(+)
> +
> +diff --git a/include/net/dsa.h b/include/net/dsa.h
> +index 70bd07c4ea15..06aa0d9912ee 100644
> +--- a/include/net/dsa.h
> ++++ b/include/net/dsa.h
> +@@ -380,6 +380,18 @@ static inline u32 dsa_user_ports(struct dsa_switch *ds)
> +     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.34.1
> +
> -- 
> 2.34.1
> 
> 
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to