Commit 2e359b00 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Paolo Abeni
Browse files

net: dsa: propagate extack to port_lag_join



Drivers could refuse to offload a LAG configuration for a variety of
reasons, mainly having to do with its TX type. Additionally, since DSA
masters may now also be LAG interfaces, and this will translate into a
call to port_lag_join on the CPU ports, there may be extra restrictions
there. Propagate the netlink extack to this DSA method in order for
drivers to give a meaningful error message back to the user.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 13eccc1b
Loading
Loading
Loading
Loading
+19 −8
Original line number Diff line number Diff line
@@ -6593,14 +6593,17 @@ static int mv88e6xxx_port_bridge_flags(struct dsa_switch *ds, int port,

static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds,
				      struct dsa_lag lag,
				      struct netdev_lag_upper_info *info)
				      struct netdev_lag_upper_info *info,
				      struct netlink_ext_ack *extack)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	struct dsa_port *dp;
	int members = 0;

	if (!mv88e6xxx_has_lag(chip))
	if (!mv88e6xxx_has_lag(chip)) {
		NL_SET_ERR_MSG_MOD(extack, "Chip does not support LAG offload");
		return false;
	}

	if (!lag.id)
		return false;
@@ -6609,14 +6612,20 @@ static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds,
		/* Includes the port joining the LAG */
		members++;

	if (members > 8)
	if (members > 8) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot offload more than 8 LAG ports");
		return false;
	}

	/* We could potentially relax this to include active
	 * backup in the future.
	 */
	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Can only offload LAG using hash TX type");
		return false;
	}

	/* Ideally we would also validate that the hash type matches
	 * the hardware. Alas, this is always set to unknown on team
@@ -6769,12 +6778,13 @@ static int mv88e6xxx_port_lag_change(struct dsa_switch *ds, int port)

static int mv88e6xxx_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)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err, id;

	if (!mv88e6xxx_lag_can_offload(ds, lag, info))
	if (!mv88e6xxx_lag_can_offload(ds, lag, info, extack))
		return -EOPNOTSUPP;

	/* DSA LAG IDs are one-based */
@@ -6827,12 +6837,13 @@ static int mv88e6xxx_crosschip_lag_change(struct dsa_switch *ds, int sw_index,

static int mv88e6xxx_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)
{
	struct mv88e6xxx_chip *chip = ds->priv;
	int err;

	if (!mv88e6xxx_lag_can_offload(ds, lag, info))
	if (!mv88e6xxx_lag_can_offload(ds, lag, info, extack))
		return -EOPNOTSUPP;

	mv88e6xxx_reg_lock(chip);
+3 −2
Original line number Diff line number Diff line
@@ -861,11 +861,12 @@ static void felix_bridge_leave(struct dsa_switch *ds, int port,

static int felix_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)
{
	struct ocelot *ocelot = ds->priv;

	return ocelot_port_lag_join(ocelot, port, lag.dev, info);
	return ocelot_port_lag_join(ocelot, port, lag.dev, info, extack);
}

static int felix_lag_leave(struct dsa_switch *ds, int port,
+17 −6
Original line number Diff line number Diff line
@@ -1017,7 +1017,8 @@ int qca8k_port_vlan_del(struct dsa_switch *ds, int port,

static bool qca8k_lag_can_offload(struct dsa_switch *ds,
				  struct dsa_lag lag,
				  struct netdev_lag_upper_info *info)
				  struct netdev_lag_upper_info *info,
				  struct netlink_ext_ack *extack)
{
	struct dsa_port *dp;
	int members = 0;
@@ -1029,15 +1030,24 @@ static bool qca8k_lag_can_offload(struct dsa_switch *ds,
		/* Includes the port joining the LAG */
		members++;

	if (members > QCA8K_NUM_PORTS_FOR_LAG)
	if (members > QCA8K_NUM_PORTS_FOR_LAG) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot offload more than 4 LAG ports");
		return false;
	}

	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Can only offload LAG using hash TX type");
		return false;
	}

	if (info->hash_type != NETDEV_LAG_HASH_L2 &&
	    info->hash_type != NETDEV_LAG_HASH_L23)
	    info->hash_type != NETDEV_LAG_HASH_L23) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Can only offload L2 or L2+L3 TX hash");
		return false;
	}

	return true;
}
@@ -1160,11 +1170,12 @@ static int qca8k_lag_refresh_portmap(struct dsa_switch *ds, int port,
}

int qca8k_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 ret;

	if (!qca8k_lag_can_offload(ds, lag, info))
	if (!qca8k_lag_can_offload(ds, lag, info, extack))
		return -EOPNOTSUPP;

	ret = qca8k_lag_setup_hash(ds, lag, info);
+2 −1
Original line number Diff line number Diff line
@@ -512,7 +512,8 @@ int qca8k_port_vlan_del(struct dsa_switch *ds, int port,

/* Common port LAG function */
int qca8k_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 qca8k_port_lag_leave(struct dsa_switch *ds, int port,
			 struct dsa_lag lag);

+6 −2
Original line number Diff line number Diff line
@@ -2132,10 +2132,14 @@ static void ocelot_migrate_lag_fdbs(struct ocelot *ocelot,

int ocelot_port_lag_join(struct ocelot *ocelot, int port,
			 struct net_device *bond,
			 struct netdev_lag_upper_info *info)
			 struct netdev_lag_upper_info *info,
			 struct netlink_ext_ack *extack)
{
	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
	if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
		NL_SET_ERR_MSG_MOD(extack,
				   "Can only offload LAG using hash TX type");
		return -EOPNOTSUPP;
	}

	mutex_lock(&ocelot->fwd_domain_lock);

Loading