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);
next prev parent 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