* [PATCH RFC] net: bridge: mcast: don't clear L2 host_joined on port group deletion
@ 2026-06-10 8:31 Cedric Jehasse via B4 Relay
2026-06-14 10:54 ` Ido Schimmel
0 siblings, 1 reply; 2+ messages in thread
From: Cedric Jehasse via B4 Relay @ 2026-06-10 8:31 UTC (permalink / raw)
To: Nikolay Aleksandrov, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman
Cc: bridge, netdev, linux-kernel, Cedric Jehasse, Cedric Jehasse
From: Cedric Jehasse <cedric.jehasse@luminex.be>
For a static L2 multicast group that has both a host entry and a port
entry, deleting the port entry also removes the host entry, and the
whole group then disappears from "bridge mdb show".
To reproduce:
bridge mdb add dev br0 port br0 grp 01:02:03:04:05:06 permanent
bridge mdb add dev br0 port swp1 grp 01:02:03:04:05:06 permanent
bridge mdb del dev br0 port swp1 grp 01:02:03:04:05:06 permanent
bridge mdb show # the "port br0" host entry is gone, too
br_multicast_del_pg() processes every non-(*,G) entry through the S,G
path, which removes the port group from br->sg_port_tbl and then calls
br_multicast_sg_del_exclude_ports(). L2 entries are stored in
sg_port_tbl as well, so they take this path too.
When the last port is removed in br_multicast_sg_del_exclude_ports it
sets "sgmp->host_joined = false", clearing the host membership directly
and bypassing br_multicast_host_leave(). With host_joined now false and
no ports left, br_multicast_del_pg() arms the group timer and
br_multicast_group_expired() tears down the whole mdb entry -- even
though the host membership was explicitly and permanently configured
from user space.
Keep removing L2 port groups from sg_port_tbl, but skip the S,G
EXCLUDE-mode handling for them. The host membership of an L2 group is
managed solely via br_multicast_host_join() / br_multicast_host_leave().
Signed-off-by: Cedric Jehasse <cedric.jehasse@luminex.be>
---
For a static L2 multicast group that has both a host entry and a port
entry, deleting the port entry also removes the host entry, and the
whole group then disappears from "bridge mdb show".
To reproduce:
bridge mdb add dev br0 port br0 grp 01:02:03:04:05:06 permanent
bridge mdb add dev br0 port swp1 grp 01:02:03:04:05:06 permanent
bridge mdb del dev br0 port swp1 grp 01:02:03:04:05:06 permanent
bridge mdb show # the "port br0" host entry is gone, too
br_multicast_del_pg() processes every non-(*,G) entry through the S,G
path, which removes the port group from br->sg_port_tbl and then calls
br_multicast_sg_del_exclude_ports(). L2 entries are stored in
sg_port_tbl as well, so they take this path too.
When the last port is removed in br_multicast_sg_del_exclude_ports it
sets "sgmp->host_joined = false", clearing the host membership directly
and bypassing br_multicast_host_leave(). With host_joined now false and
no ports left, br_multicast_del_pg() arms the group timer and
br_multicast_group_expired() tears down the whole mdb entry -- even
though the host membership was explicitly and permanently configured
from user space.
Keep removing L2 port groups from sg_port_tbl, but skip the S,G
EXCLUDE-mode handling for them. The host membership of an L2 group is
managed solely via br_multicast_host_join() / br_multicast_host_leave().
This fixes the issue, but i'd like a second opinion on if this is the
correct way to fix it.
---
net/bridge/br_multicast.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 881d866d687a..d718a6d1ddb1 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -816,7 +816,13 @@ void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
if (!br_multicast_is_star_g(&mp->addr)) {
rhashtable_remove_fast(&br->sg_port_tbl, &pg->rhnode,
br_sg_port_rht_params);
- br_multicast_sg_del_exclude_ports(mp);
+ /* L2 entries share sg_port_tbl with S,G entries but have no
+ * *,G/S,G EXCLUDE-mode semantics; their host membership is
+ * managed explicitly via br_multicast_host_join()/leave() and
+ * must not be cleared here when the last port group is removed.
+ */
+ if (!br_group_is_l2(&mp->addr))
+ br_multicast_sg_del_exclude_ports(mp);
} else {
br_multicast_star_g_handle_mode(pg, MCAST_INCLUDE);
}
---
base-commit: 022bdd9c0d036863c4bacd1688b73c6be3001cee
change-id: 20260609-mdb_l2_host_joined_fix-fb2de21580c7
Best regards,
--
Cedric Jehasse <cedric.jehasse@luminex.be>
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH RFC] net: bridge: mcast: don't clear L2 host_joined on port group deletion
2026-06-10 8:31 [PATCH RFC] net: bridge: mcast: don't clear L2 host_joined on port group deletion Cedric Jehasse via B4 Relay
@ 2026-06-14 10:54 ` Ido Schimmel
0 siblings, 0 replies; 2+ messages in thread
From: Ido Schimmel @ 2026-06-14 10:54 UTC (permalink / raw)
To: cedric.jehasse
Cc: Nikolay Aleksandrov, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, bridge, netdev,
linux-kernel, Cedric Jehasse
On Wed, Jun 10, 2026 at 10:31:23AM +0200, Cedric Jehasse via B4 Relay wrote:
> From: Cedric Jehasse <cedric.jehasse@luminex.be>
>
> For a static L2 multicast group that has both a host entry and a port
> entry, deleting the port entry also removes the host entry, and the
> whole group then disappears from "bridge mdb show".
>
> To reproduce:
> bridge mdb add dev br0 port br0 grp 01:02:03:04:05:06 permanent
> bridge mdb add dev br0 port swp1 grp 01:02:03:04:05:06 permanent
> bridge mdb del dev br0 port swp1 grp 01:02:03:04:05:06 permanent
> bridge mdb show # the "port br0" host entry is gone, too
Please show the output in the commit message and also show that this
differs from regular (*, G) entries where the host entry is not removed
following the deletion of the port entry.
>
> br_multicast_del_pg() processes every non-(*,G) entry through the S,G
> path, which removes the port group from br->sg_port_tbl and then calls
> br_multicast_sg_del_exclude_ports(). L2 entries are stored in
> sg_port_tbl as well, so they take this path too.
>
> When the last port is removed in br_multicast_sg_del_exclude_ports it
> sets "sgmp->host_joined = false", clearing the host membership directly
> and bypassing br_multicast_host_leave(). With host_joined now false and
> no ports left, br_multicast_del_pg() arms the group timer and
> br_multicast_group_expired() tears down the whole mdb entry -- even
> though the host membership was explicitly and permanently configured
> from user space.
>
> Keep removing L2 port groups from sg_port_tbl, but skip the S,G
> EXCLUDE-mode handling for them. The host membership of an L2 group is
> managed solely via br_multicast_host_join() / br_multicast_host_leave().
>
> Signed-off-by: Cedric Jehasse <cedric.jehasse@luminex.be>
The patch seems OK to me, but please add a test case in bridge_mdb.sh.
I checked the code and AFAICT this never worked, so target at net-next
without a fixes tag: Support for L2 multicast groups was added in
955062b03fa62, but at this point the mode handling already existed in
br_multicast_del_pg().
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-14 10:54 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-10 8:31 [PATCH RFC] net: bridge: mcast: don't clear L2 host_joined on port group deletion Cedric Jehasse via B4 Relay
2026-06-14 10:54 ` Ido Schimmel
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox