summaryrefslogtreecommitdiff
path: root/include/net/dsa.h
diff options
context:
space:
mode:
authorTobias Waldekranz <tobias@waldekranz.com>2021-01-13 09:42:53 +0100
committerJakub Kicinski <kuba@kernel.org>2021-01-14 17:11:56 -0800
commit058102a6e9eb1905a7da41b7a5a7a1f278a3828a (patch)
treee0c811249cf6e95f595c100b67d0aa5583582dc1 /include/net/dsa.h
parent5696c8aedfccbc5ec644d00fc91f71595b495660 (diff)
net: dsa: Link aggregation support
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). 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 device 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. Drivers can optionally request that DSA maintain a linear mapping from a LAG ID to the corresponding netdev by setting ds->num_lag_ids to the desired size. In the event that the hardware is not capable of offloading a particular LAG for any reason (the typical case being use of exotic modes like broadcast), DSA will take a hands-off approach, allowing the LAG to be formed as a pure software construct. This is reported back through the extended ACK, but is otherwise transparent to the user. Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Tested-by: Vladimir Oltean <olteanv@gmail.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include/net/dsa.h')
-rw-r--r--include/net/dsa.h60
1 files changed, 60 insertions, 0 deletions
diff --git a/include/net/dsa.h b/include/net/dsa.h
index c3485ba6c3125..06e3784ec55c8 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -149,8 +149,41 @@ struct dsa_switch_tree {
/* List of DSA links composing the routing table */
struct list_head rtable;
+
+ /* Maps offloaded LAG netdevs to a zero-based linear ID for
+ * drivers that need it.
+ */
+ struct net_device **lags;
+ unsigned int lags_len;
};
+#define dsa_lags_foreach_id(_id, _dst) \
+ for ((_id) = 0; (_id) < (_dst)->lags_len; (_id)++) \
+ if ((_dst)->lags[(_id)])
+
+#define dsa_lag_foreach_port(_dp, _dst, _lag) \
+ list_for_each_entry((_dp), &(_dst)->ports, list) \
+ if ((_dp)->lag_dev == (_lag))
+
+static inline struct net_device *dsa_lag_dev(struct dsa_switch_tree *dst,
+ unsigned int id)
+{
+ return dst->lags[id];
+}
+
+static inline int dsa_lag_id(struct dsa_switch_tree *dst,
+ struct net_device *lag)
+{
+ unsigned int id;
+
+ dsa_lags_foreach_id(id, dst) {
+ if (dsa_lag_dev(dst, id) == lag)
+ return id;
+ }
+
+ return -ENODEV;
+}
+
/* TC matchall action types */
enum dsa_port_mall_action_type {
DSA_PORT_MALL_MIRROR,
@@ -220,6 +253,8 @@ struct dsa_port {
bool devlink_port_setup;
struct phylink *pl;
struct phylink_config pl_config;
+ struct net_device *lag_dev;
+ bool lag_tx_enabled;
struct list_head list;
@@ -340,6 +375,14 @@ struct dsa_switch {
*/
bool mtu_enforcement_ingress;
+ /* Drivers that benefit from having an ID associated with each
+ * offloaded LAG should set this to the maximum number of
+ * supported IDs. DSA will then maintain a mapping of _at
+ * least_ these many IDs, accessible to drivers via
+ * dsa_lag_id().
+ */
+ unsigned int num_lag_ids;
+
size_t num_ports;
};
@@ -626,6 +669,13 @@ struct dsa_switch_ops {
void (*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index,
int sw_index, int port,
struct net_device *br);
+ int (*crosschip_lag_change)(struct dsa_switch *ds, int sw_index,
+ int port);
+ int (*crosschip_lag_join)(struct dsa_switch *ds, int sw_index,
+ int port, struct net_device *lag,
+ struct netdev_lag_upper_info *info);
+ int (*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index,
+ int port, struct net_device *lag);
/*
* PTP functionality
@@ -657,6 +707,16 @@ 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);
+
+ /*
+ * LAG integration
+ */
+ int (*port_lag_change)(struct dsa_switch *ds, int port);
+ int (*port_lag_join)(struct dsa_switch *ds, int port,
+ struct net_device *lag,
+ struct netdev_lag_upper_info *info);
+ int (*port_lag_leave)(struct dsa_switch *ds, int port,
+ struct net_device *lag);
};
#define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \