Re: [RFC PATCH 2/4] net: dsa: link aggregation support
From: Vladimir Oltean <olteanv@gmail.com>
Date: 2020-10-28 23:16:31
On Tue, Oct 27, 2020 at 11:51:15AM +0100, Tobias Waldekranz wrote:
Monitor the following events and notify the driver when: - A DSA port joins/leaves a LAG. - A LAG, made up of DSA ports, joins/leaves a bridge. - A DSA port in a LAG is enabled/disabled (enabled meaning "distributing" in 802.3ad LACP terms). Each LAG interface to which a DSA port is attached is represented by a `struct dsa_lag` which is globally reachable from the switch tree and
When you use dsa_broadcast, it is reachable from _all_ switch trees, not from "the" switch tree. This was added to support "islands" of inter-compatible DSA switches separated by other DSA switches with incompatible taggers. Not sure if it was a voluntary decision to use that as opposed to plain dsa_port_notify. Not a problem either way.
quoted hunk ↗ jump to hunk
from each associated port. When a LAG joins a bridge, the DSA subsystem will treat that as each individual port joining the bridge. The driver may look at the port's LAG pointer to see if it is associated with any LAG, if that is required. This is analogue to how switchdev events are replicated out to all lower devices when reaching e.g. a LAG. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> --- include/net/dsa.h | 68 +++++++++++++++++++++ net/dsa/dsa2.c | 3 + net/dsa/dsa_priv.h | 16 +++++ net/dsa/port.c | 146 +++++++++++++++++++++++++++++++++++++++++++++ net/dsa/slave.c | 53 ++++++++++++++-- net/dsa/switch.c | 64 ++++++++++++++++++++ 6 files changed, 346 insertions(+), 4 deletions(-)diff --git a/include/net/dsa.h b/include/net/dsa.h index 35429a140dfa..58d73eafe891 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h@@ -145,6 +145,9 @@ struct dsa_switch_tree { /* List of switch ports */ struct list_head ports; + /* List of configured LAGs */ + struct list_head lags; + /* List of DSA links composing the routing table */ struct list_head rtable; };@@ -178,6 +181,48 @@ struct dsa_mall_tc_entry { }; }; +struct dsa_lag { + struct net_device *dev; + int id; + + struct list_head ports; + + /* For multichip systems, we must ensure that each hash bucket + * is only enabled on a single egress port throughout the + * whole tree.
Or else? I don't really understand this statement.
quoted hunk ↗ jump to hunk
--- a/net/dsa/port.c +++ b/net/dsa/port.c@@ -193,6 +193,152 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) dsa_port_set_state_now(dp, BR_STATE_FORWARDING); } +static struct dsa_lag *dsa_lag_get(struct dsa_switch_tree *dst, + struct net_device *dev) +{ + struct dsa_lag *lag; + unsigned long busy = 0;
Reverse Christmas notation please?
quoted hunk ↗ jump to hunk
+ int id; + + list_for_each_entry(lag, &dst->lags, list) { + set_bit(lag->id, &busy); + + if (lag->dev == dev) { + kref_get(&lag->refcount); + return lag; + } + } + + id = find_first_zero_bit(&busy, BITS_PER_LONG); + if (id >= BITS_PER_LONG) + return ERR_PTR(-ENOSPC); + + lag = kzalloc(sizeof(*lag), GFP_KERNEL); + if (!lag) + return ERR_PTR(-ENOMEM); + + kref_init(&lag->refcount); + lag->id = id; + lag->dev = dev; + INIT_LIST_HEAD(&lag->ports); + INIT_LIST_HEAD(&lag->tx_ports); + + INIT_LIST_HEAD(&lag->list); + list_add_tail_rcu(&lag->list, &dst->lags); + return lag; +} +diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 3bc5ca40c9fb..e5e4f3d096c0 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c@@ -334,7 +334,8 @@ static int dsa_slave_vlan_add(struct net_device *dev, struct switchdev_obj_port_vlan vlan; int vid, err; - if (obj->orig_dev != dev) + if (!(obj->orig_dev == dev || + (dp->lag && obj->orig_dev == dp->lag->dev)))
A small comment here maybe?
quoted hunk ↗ jump to hunk
return -EOPNOTSUPP; if (dsa_port_skip_vlan_configuration(dp))@@ -421,7 +422,8 @@ static int dsa_slave_vlan_del(struct net_device *dev, struct switchdev_obj_port_vlan *vlan; int vid, err; - if (obj->orig_dev != dev) + if (!(obj->orig_dev == dev || + (dp->lag && obj->orig_dev == dp->lag->dev))) return -EOPNOTSUPP; if (dsa_port_skip_vlan_configuration(dp))