diff options
author | Paolo Abeni <pabeni@redhat.com> | 2022-09-20 10:32:38 +0200 |
---|---|---|
committer | Paolo Abeni <pabeni@redhat.com> | 2022-09-20 10:32:39 +0200 |
commit | e8b9f0da92f3560d6596d8306f08cd28e50eba85 (patch) | |
tree | b336f1bea0b194d98a6aa8c09922ce37174b4d81 /include/net/dsa.h | |
parent | 42e53b447cf890b10b4872c967e9f81fd2b06067 (diff) | |
parent | eca70102cfb19d783d30d3e9b13713d58581eb67 (diff) |
Merge branch 'dsa-changes-for-multiple-cpu-ports-part-4'
Vladimir Oltean says:
====================
DSA changes for multiple CPU ports (part 4)
Those who have been following part 1:
https://patchwork.kernel.org/project/netdevbpf/cover/20220511095020.562461-1-vladimir.oltean@nxp.com/
part 2:
https://patchwork.kernel.org/project/netdevbpf/cover/20220521213743.2735445-1-vladimir.oltean@nxp.com/
and part 3:
https://patchwork.kernel.org/project/netdevbpf/cover/20220819174820.3585002-1-vladimir.oltean@nxp.com/
will know that I am trying to enable the second internal port pair from
the NXP LS1028A Felix switch for DSA-tagged traffic via "ocelot-8021q".
This series represents the final part of that effort. We have:
- the introduction of new UAPI in the form of IFLA_DSA_MASTER, the
iproute2 patch for which is here:
https://patchwork.kernel.org/project/netdevbpf/patch/20220904190025.813574-1-vladimir.oltean@nxp.com/
- preparation for LAG DSA masters in terms of suppressing some
operations for masters in the DSA core that simply don't make sense
when those masters are a bonding/team interface
- handling all the net device events that occur between DSA and a
LAG DSA master, including migration to a different DSA master when the
current master joins a LAG, or the LAG gets destroyed
- updating documentation
- adding an implementation for NXP LS1028A, where things are insanely
complicated due to hardware limitations. We have 2 tagging protocols:
* the native "ocelot" protocol (NPI port mode). This does not support
CPU ports in a LAG, and supports a single DSA master. The DSA master
can be changed between eno2 (2.5G) and eno3 (1G), but all ports must
be down during the changing process, and user ports assigned to the
old DSA master will refuse to come up if the user requests that
during a "transient" state.
* the "ocelot-8021q" software-defined protocol, where the Ethernet
ports connected to the CPU are not actually "god mode" ports as far
as the hardware is concerned. So here, static assignment between
user and CPU ports is possible by editing the PGID_SRC masks for
the port-based forwarding matrix, and "CPU ports in a LAG" simply
means "a LAG like any other".
The series was regression-tested on LS1028A using the local_termination.sh
kselftest, in most of the possible operating modes and tagging protocols.
I have not done a detailed performance evaluation yet, but using LAG, is
possible to exceed the termination bandwidth of a single CPU port in an
iperf3 test with multiple senders and multiple receivers.
v1 at:
https://patchwork.kernel.org/project/netdevbpf/cover/20220830195932.683432-1-vladimir.oltean@nxp.com/
Previous (older) RFC at:
https://lore.kernel.org/netdev/20220523104256.3556016-1-olteanv@gmail.com/
====================
Link: https://lore.kernel.org/r/20220911010706.2137967-1-vladimir.oltean@nxp.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Diffstat (limited to 'include/net/dsa.h')
-rw-r--r-- | include/net/dsa.h | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h index f2ce12860546e..d777eac5694f8 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -300,6 +300,9 @@ struct dsa_port { u8 master_admin_up:1; u8 master_oper_up:1; + /* Valid only on user ports */ + u8 cpu_port_in_lag:1; + u8 setup:1; struct device_node *dn; @@ -559,6 +562,10 @@ static inline bool dsa_is_user_port(struct dsa_switch *ds, int p) list_for_each_entry((_dp), &(_dst)->ports, list) \ if (dsa_port_is_user((_dp))) +#define dsa_tree_for_each_user_port_continue_reverse(_dp, _dst) \ + list_for_each_entry_continue_reverse((_dp), &(_dst)->ports, list) \ + if (dsa_port_is_user((_dp))) + #define dsa_tree_for_each_cpu_port(_dp, _dst) \ list_for_each_entry((_dp), &(_dst)->ports, list) \ if (dsa_port_is_cpu((_dp))) @@ -718,6 +725,14 @@ static inline bool dsa_port_offloads_lag(struct dsa_port *dp, return dsa_port_lag_dev_get(dp) == lag->dev; } +static inline struct net_device *dsa_port_to_master(const struct dsa_port *dp) +{ + if (dp->cpu_port_in_lag) + return dsa_port_lag_dev_get(dp->cpu_dp); + + return dp->cpu_dp->master; +} + static inline struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp) { @@ -802,6 +817,12 @@ dsa_tree_offloads_bridge_dev(struct dsa_switch_tree *dst, return false; } +static inline bool dsa_port_tree_same(const struct dsa_port *a, + const struct dsa_port *b) +{ + return a->ds->dst == b->ds->dst; +} + typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid, bool is_static, void *data); struct dsa_switch_ops { @@ -825,6 +846,10 @@ struct dsa_switch_ops { int (*connect_tag_protocol)(struct dsa_switch *ds, enum dsa_tag_protocol proto); + int (*port_change_master)(struct dsa_switch *ds, int port, + struct net_device *master, + struct netlink_ext_ack *extack); + /* Optional switch-wide initialization and destruction methods */ int (*setup)(struct dsa_switch *ds); void (*teardown)(struct dsa_switch *ds); @@ -1081,7 +1106,8 @@ struct dsa_switch_ops { int port); int (*crosschip_lag_join)(struct dsa_switch *ds, int sw_index, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info); + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack); int (*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index, int port, struct dsa_lag lag); @@ -1156,7 +1182,8 @@ struct dsa_switch_ops { int (*port_lag_change)(struct dsa_switch *ds, int port); int (*port_lag_join)(struct dsa_switch *ds, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info); + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack); int (*port_lag_leave)(struct dsa_switch *ds, int port, struct dsa_lag lag); |