Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next] net: dsa: unsync host addresses when destroying user port
@ 2026-07-22  0:12 Daniel Golle
  2026-07-23 22:57 ` Vladimir Oltean
  0 siblings, 1 reply; 3+ messages in thread
From: Daniel Golle @ 2026-07-22  0:12 UTC (permalink / raw)
  To: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King, netdev,
	linux-kernel

When a user port is destroyed while addresses are still synced to it,
e.g. multicast addresses synced by a bridge the port is a member of,
the host FDB/MDB entries these addresses installed on the CPU port are
never removed: the only removal path is dsa_user_unsync_uc()/_mc() via
ndo_set_rx_mode, and __dev_set_rx_mode() does not call the ndo on a
device which is down. By the time the bridge unsyncs its addresses in
del_nbp() during unregistration, the netdev has already been closed,
so the unsync never reaches DSA and the entries linger until
dsa_switch_release_ports() reports them:

  Cleaning up multicast address 33:33:00:00:00:01 vid 0 from port 9

This happens on every unbind of a DSA driver supporting host address
filtering while its ports are up.

Unsync the host addresses in dsa_user_destroy() before unregistering
the netdev, at a point where the driver can still process the
deletion, just like dsa_user_change_conduit() already does when
migrating host addresses to a new conduit.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 net/dsa/user.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/dsa/user.c b/net/dsa/user.c
index 03c7af6abe18..a7dabb645036 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -2885,6 +2885,7 @@ void dsa_user_destroy(struct net_device *user_dev)
 
 	netif_carrier_off(user_dev);
 	rtnl_lock();
+	dsa_user_unsync_ha(user_dev);
 	netdev_upper_dev_unlink(conduit, user_dev);
 	unregister_netdevice(user_dev);
 	phylink_disconnect_phy(dp->pl);
-- 
2.55.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next] net: dsa: unsync host addresses when destroying user port
  2026-07-22  0:12 [PATCH net-next] net: dsa: unsync host addresses when destroying user port Daniel Golle
@ 2026-07-23 22:57 ` Vladimir Oltean
  2026-07-24 12:41   ` Vladimir Oltean
  0 siblings, 1 reply; 3+ messages in thread
From: Vladimir Oltean @ 2026-07-23 22:57 UTC (permalink / raw)
  To: Daniel Golle
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Russell King, netdev, linux-kernel

On Wed, Jul 22, 2026 at 01:12:47AM +0100, Daniel Golle wrote:
> When a user port is destroyed while addresses are still synced to it,
> e.g. multicast addresses synced by a bridge the port is a member of,
> the host FDB/MDB entries these addresses installed on the CPU port are
> never removed: the only removal path is dsa_user_unsync_uc()/_mc() via
> ndo_set_rx_mode, and __dev_set_rx_mode() does not call the ndo on a
> device which is down. By the time the bridge unsyncs its addresses in
> del_nbp() during unregistration, the netdev has already been closed,
> so the unsync never reaches DSA and the entries linger until
> dsa_switch_release_ports() reports them:
> 
>   Cleaning up multicast address 33:33:00:00:00:01 vid 0 from port 9
> 
> This happens on every unbind of a DSA driver supporting host address
> filtering while its ports are up.
> 
> Unsync the host addresses in dsa_user_destroy() before unregistering
> the netdev, at a point where the driver can still process the
> deletion, just like dsa_user_change_conduit() already does when
> migrating host addresses to a new conduit.
> 
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> ---
>  net/dsa/user.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/net/dsa/user.c b/net/dsa/user.c
> index 03c7af6abe18..a7dabb645036 100644
> --- a/net/dsa/user.c
> +++ b/net/dsa/user.c
> @@ -2885,6 +2885,7 @@ void dsa_user_destroy(struct net_device *user_dev)
>  
>  	netif_carrier_off(user_dev);
>  	rtnl_lock();
> +	dsa_user_unsync_ha(user_dev);
>  	netdev_upper_dev_unlink(conduit, user_dev);
>  	unregister_netdevice(user_dev);
>  	phylink_disconnect_phy(dp->pl);
> -- 
> 2.55.0

Sorry, I noticed this patch late. Something doesn't add up - I don't
understand what makes the unregistration path unique, since according to
all you've said, it should be enough to remove the user port from the
bridge while administratively down, and it should lead to the same
effect (no unsync event triggered). In that case, maybe the
dsa_user_unsync_ha() belongs somewhere in dsa_user_close(), near
dsa_user_host_uc_uninstall().

I will return tomorrow with more comments after I do some testing.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH net-next] net: dsa: unsync host addresses when destroying user port
  2026-07-23 22:57 ` Vladimir Oltean
@ 2026-07-24 12:41   ` Vladimir Oltean
  0 siblings, 0 replies; 3+ messages in thread
From: Vladimir Oltean @ 2026-07-24 12:41 UTC (permalink / raw)
  To: Daniel Golle
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Russell King, netdev, linux-kernel

On Fri, Jul 24, 2026 at 01:57:35AM +0300, Vladimir Oltean wrote:
> On Wed, Jul 22, 2026 at 01:12:47AM +0100, Daniel Golle wrote:
> > When a user port is destroyed while addresses are still synced to it,
> > e.g. multicast addresses synced by a bridge the port is a member of,
> > the host FDB/MDB entries these addresses installed on the CPU port are
> > never removed: the only removal path is dsa_user_unsync_uc()/_mc() via
> > ndo_set_rx_mode, and __dev_set_rx_mode() does not call the ndo on a
> > device which is down. By the time the bridge unsyncs its addresses in
> > del_nbp() during unregistration, the netdev has already been closed,
> > so the unsync never reaches DSA and the entries linger until
> > dsa_switch_release_ports() reports them:
> > 
> >   Cleaning up multicast address 33:33:00:00:00:01 vid 0 from port 9
> > 
> > This happens on every unbind of a DSA driver supporting host address
> > filtering while its ports are up.
> > 
> > Unsync the host addresses in dsa_user_destroy() before unregistering
> > the netdev, at a point where the driver can still process the
> > deletion, just like dsa_user_change_conduit() already does when
> > migrating host addresses to a new conduit.
> > 
> > Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> > ---
> >  net/dsa/user.c | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/net/dsa/user.c b/net/dsa/user.c
> > index 03c7af6abe18..a7dabb645036 100644
> > --- a/net/dsa/user.c
> > +++ b/net/dsa/user.c
> > @@ -2885,6 +2885,7 @@ void dsa_user_destroy(struct net_device *user_dev)
> >  
> >  	netif_carrier_off(user_dev);
> >  	rtnl_lock();
> > +	dsa_user_unsync_ha(user_dev);
> >  	netdev_upper_dev_unlink(conduit, user_dev);
> >  	unregister_netdevice(user_dev);
> >  	phylink_disconnect_phy(dp->pl);
> > -- 
> > 2.55.0
> 
> Sorry, I noticed this patch late. Something doesn't add up - I don't
> understand what makes the unregistration path unique, since according to
> all you've said, it should be enough to remove the user port from the
> bridge while administratively down, and it should lead to the same
> effect (no unsync event triggered). In that case, maybe the
> dsa_user_unsync_ha() belongs somewhere in dsa_user_close(), near
> dsa_user_host_uc_uninstall().
> 
> I will return tomorrow with more comments after I do some testing.

Back with some more comments.

Your statement "multicast addresses synced by a bridge the port is a
member of" is not correct. The bridge does not call dev_mc_add().
The multicast addresses come from a different place - likely from
net/ipv6/mcast.c instead.

Therefore, the part of the explanation that ties del_nbp() to the chain
of events truly has no relationship and should be dropped. The
host-joined multicast groups for the bridge are all synced to hardware
through the SWITCHDEV_OBJ_ID_HOST_MDB mechanism.

The minimal reproducer for the problem you observed should be:

$ ip link set swp0 up
$ ip link set swp0 down
$ echo <device-name> > /path/to/driver/unbind

and the correct fix is to put the dsa_user_unsync_ha() call where I
suggested earlier - in dsa_user_close().

pw-bot: cr

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-24 12:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-22  0:12 [PATCH net-next] net: dsa: unsync host addresses when destroying user port Daniel Golle
2026-07-23 22:57 ` Vladimir Oltean
2026-07-24 12:41   ` Vladimir Oltean

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox