Netdev List
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: ioana.ciornei@nxp.com
Cc: Jakub Kicinski <kuba@kernel.org>,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	pabeni@redhat.com, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH net-next v3 02/12] dpaa2-switch: add support for LAG offload
Date: Fri,  5 Jun 2026 19:10:47 -0700	[thread overview]
Message-ID: <20260606021047.4124576-1-kuba@kernel.org> (raw)
In-Reply-To: <20260603143623.3712024-3-ioana.ciornei@nxp.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
dpaa2-switch: add support for LAG offload

This patch adds the bulk of the changes needed in order to support
offloading of an upper bond device.

> diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
> index a0bf5b50aae5f..d082ecf9b1252 100644
> --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
> +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c

[ ... ]

> @@ -2210,19 +2300,275 @@ dpaa2_switch_prechangeupper_sanity_checks(struct net_device *netdev,
> +static int dpaa2_switch_port_bond_join(struct net_device *netdev,
> +				       struct net_device *bond_dev,
> +				       struct netdev_lag_upper_info *info,
> +				       struct netlink_ext_ack *extack)
> +{

[ ... ]

> +	/* If the bond device is a switch port, join the bridge as well */
> +	bridge_dev = netdev_master_upper_dev_get(bond_dev);
> +	if (!bridge_dev || !netif_is_bridge_master(bridge_dev))
> +		return 0;
> +
> +	err = dpaa2_switch_port_bridge_join(netdev, bridge_dev, extack);

[Severity: High]
Should switchdev_bridge_port_offload() inside dpaa2_switch_port_bridge_join()
receive the actual bridge port (the bond device) rather than the lower
physical port?

For ports enslaved to a LAG, passing the lower physical port might cause
switchdev to immediately abort the offload with -EINVAL, since the netdev
is not directly enslaved to the bridge. I see this was addressed in a later
commit adding a dpaa2_switch_port_to_bridge_port() helper.

[Severity: High]
When a port joins a LAG that is already enslaved to a bridge, is there a risk
of dpaa2_switch_port_set_fdb() corrupting the in_use flag of active FDBs?

Since the port first acquires the bond's shared FDB, and then
dpaa2_switch_port_bridge_join() finds a port already using that same FDB,
the code in dpaa2_switch_port_set_fdb() seems to lack a self-assignment
check. This could mark the shared FDB as unused before reassigning it,
allowing another standalone port to reallocate it. I note this was fixed in
a later commit covering bond scenarios.

[Severity: High]
Will dpaa2_switch_port_set_fdb() skip bonds when iterating through lower
devices, breaking cross-LAG forwarding?

When a port joins a bridge, dpaa2_switch_port_set_fdb() uses a non-recursive
iterator (netdev_for_each_lower_dev). If the other lower device is a bond,
dpaa2_switch_port_dev_check() will return false, skipping nested ports and
failing to share the hardware FDB. I note this was also fixed in a later
commit.

> +	if (err)
> +		goto err_bridge_join;
> +
> +	return err;
> +
> +err_bridge_join:
> +	dpaa2_switch_port_del_vlan(port_priv, DEFAULT_VLAN_ID);
> +err_vlan_add:
> +err_lag_cfg:
> +	rcu_assign_pointer(port_priv->lag, NULL);
> +	dpaa2_switch_set_lag_cfg(bond_dev, lag_id, ethsw);
> +err_egress_flood:
> +	if (port_priv->fdb != old_fdb) {
> +		new_fdb = port_priv->fdb;
> +
> +		/* Explicitly move the port back into the old private FDB */
> +		old_fdb->in_use = true;
> +		old_fdb->bridge_dev = NULL;
> +		port_priv->fdb = old_fdb;
> +
> +		/* Reprogram the bond FDB to no longer include this port */
> +		dpaa2_switch_fdb_set_egress_flood(ethsw, new_fdb->fdb_id);

[Severity: High]
Are we permanently leaking a hardware FDB resource in this error path?

If dpaa2_switch_port_bridge_join() fails, it will have allocated a new
intermediate FDB and marked it in_use. The cleanup block here restores
the original old_fdb, but does not appear to set new_fdb->in_use back to
false. Repeated failures might exhaust the fixed number of FDBs.

> +	} else {
> +		/* Same FDB means that this was the first port joining the
> +		 * bond. Keep using the same FDB.
> +		 */
> +		old_fdb->bridge_dev = NULL;
> +	}

[ ... ]

> +static int dpaa2_switch_port_bond_leave(struct net_device *netdev,
> +					struct net_device *bond_dev)
> +{

[ ... ]

> +lag_cleanup:
> +	/* Recreate the LAG configuration for the LAG group that we left. In
> +	 * case any step failed, at least we free up a LAG resource.
> +	 */
> +	rcu_assign_pointer(port_priv->lag, NULL);
> +	dpaa2_switch_set_lag_cfg(bond_dev, lag->id, ethsw);

[Severity: Critical]
Could this trigger a kernel panic if lag is NULL on the rollback path?

If dpaa2_switch_port_bond_join() fails and sets port_priv->lag to NULL, a
subsequent NETDEV_CHANGEUPPER rollback calls this function. The lag variable
is initialized via rtnl_dereference(port_priv->lag), which would be NULL,
leading to a dereference when accessing lag->id here.

> +
> +	return err;
> +}
> +
>  static int dpaa2_switch_port_prechangeupper(struct net_device *netdev,
>  					    struct netdev_notifier_changeupper_info *info)
>  {
> +	struct net_device *upper_dev, *br;
>  	struct netlink_ext_ack *extack;
> -	struct net_device *upper_dev;
>  	int err;
>  
>  	if (!dpaa2_switch_port_dev_check(netdev))
> @@ -2239,6 +2585,24 @@ static int dpaa2_switch_port_prechangeupper(struct net_device *netdev,
>  
>  		if (!info->linking)
>  			dpaa2_switch_port_pre_bridge_leave(netdev);
> +	} else if (netif_is_lag_master(upper_dev)) {
> +		if (!info->linking) {
> +			if (netif_is_bridge_port(upper_dev))
> +				dpaa2_switch_port_pre_bridge_leave(netdev);
> +			return 0;
> +		}
> +
> +		if (netif_is_bridge_port(upper_dev)) {
> +			br = netdev_master_upper_dev_get(upper_dev);
> +			err = dpaa2_switch_prechangeupper_sanity_checks(netdev,
> +									br,
> +									extack);
> +			if (err)
> +				return err;
> +		}
> +
> +		return dpaa2_switch_pre_lag_join(netdev, upper_dev,
> +						 info->upper_info, extack);
>  	}
>  
>  	return 0;

[Severity: High]
Might this bypass topological checks and allow VLAN uppers on offloaded LAGs?

If a port joins a LAG first, and then a VLAN is added to the LAG, the
event propagates here with the VLAN device as upper_dev. Since it is
neither a bridge nor a LAG master, this function returns 0 without checking
vlan_uses_dev(), inadvertently allowing an unsupported hardware configuration.

> @@ -2263,6 +2627,80 @@ static int dpaa2_switch_port_changeupper(struct net_device *netdev,
>  							     extack);
>  		else
>  			return dpaa2_switch_port_bridge_leave(netdev);

[Severity: High]
Does calling dpaa2_switch_port_bridge_leave() wrongly split LAG member ports
into isolated private FDBs?

When a LAG leaves a bridge, this is invoked for each member port. It will
unconditionally call dpaa2_switch_port_set_fdb(port_priv, NULL), which forces
the port to drop the shared FDB and isolates it from the other LAG members.
I note this was also fixed in a later commit covering bond scenarios.

> +	} else if (netif_is_lag_master(upper_dev)) {
> +		if (info->linking)
> +			return dpaa2_switch_port_bond_join(netdev, upper_dev,
> +							   info->upper_info,
> +							   extack);

  reply	other threads:[~2026-06-06  2:10 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-03 14:36 [PATCH net-next v3 00/12] dpaa2-switch: add support for LAG offload Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 01/12] dpaa2-switch: add LAG configuration API Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 02/12] dpaa2-switch: add support for LAG offload Ioana Ciornei
2026-06-06  2:10   ` Jakub Kicinski [this message]
2026-06-03 14:36 ` [PATCH net-next v3 03/12] dpaa2-switch: change dpaa2_switch_port_set_fdb() function prototype Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 04/12] dpaa2-switch: extend dpaa2_switch_port_set_fdb() to cover bond scenarios Ioana Ciornei
2026-06-06  2:10   ` Jakub Kicinski
2026-06-03 14:36 ` [PATCH net-next v3 05/12] dpaa2-switch: add dpaa2_switch_port_to_bridge_port() helper Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 06/12] dpaa2-switch: create a separate dpaa2_switch_port_fdb_event() function Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 07/12] dpaa2-switch: check early if an FDB entry should be added Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 08/12] dpaa2-switch: consolidate unicast and multicast management Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 09/12] dpaa2-switch: offload FDBs added on an upper bond device Ioana Ciornei
2026-06-06  2:10   ` Jakub Kicinski
2026-06-03 14:36 ` [PATCH net-next v3 10/12] dpaa2-switch: offload port objects " Ioana Ciornei
2026-06-06  2:10   ` Jakub Kicinski
2026-06-03 14:36 ` [PATCH net-next v3 11/12] dpaa2-switch: trap all link local reserved addresses to the CPU Ioana Ciornei
2026-06-03 14:36 ` [PATCH net-next v3 12/12] dpaa2-switch: add support for imprecise source port Ioana Ciornei
2026-06-06  2:11   ` Jakub Kicinski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260606021047.4124576-1-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=ioana.ciornei@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox