mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
bridge: mcast: Delete empty MDB entry when port group creation fails
When a port group cannot be created for a new group, the MDB entry that was created for it is left with no ports and is not joined by the host. Its timer is never armed, so the entry is never deleted, but it is counted towards mcast_hash_max. When this maximum is reached, the bridge disables multicast snooping. Since commitb57e8d870d("net: bridge: Maintain number of MDB entries in net_bridge_mcast_port"), port group creation also fails when the port reached its mcast_max_groups limit. A host behind such a port can therefore disable snooping by sending reports for new groups, which is what the limit is meant to prevent. The RTM_NEWMDB path has the same problem. Fix by deleting the entry after a failure if it is unused. Delete it immediately rather than arming its timer, so that it stops counting towards the maximum right away. Fixes:b57e8d870d("net: bridge: Maintain number of MDB entries in net_bridge_mcast_port") Reported-by: Yunlong Ma <yunlong_ma@buaa.edu.cn> Closes: https://lore.kernel.org/netdev/2f5b61e2.1e71a.1a11fcb3809.Coremail.yunlong_ma@buaa.edu.cn/ Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Tested-by: Gabriel Goller <g.goller@proxmox.com> Reviewed-by: Gabriel Goller <g.goller@proxmox.com> Link: https://patch.msgid.link/20261016101407.2030133-2-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
38dda0ecd4
commit
1d0590f96f
|
|
@ -819,6 +819,7 @@ static int br_mdb_add_group_src_fwd(const struct br_mdb_config *cfg,
|
|||
struct br_mdb_config sg_cfg;
|
||||
struct br_ip sg_ip;
|
||||
u8 flags = 0;
|
||||
int err;
|
||||
|
||||
sg_ip = cfg->group;
|
||||
sg_ip.src = src_ip->src;
|
||||
|
|
@ -842,7 +843,11 @@ static int br_mdb_add_group_src_fwd(const struct br_mdb_config *cfg,
|
|||
sg_cfg.filter_mode = MCAST_INCLUDE;
|
||||
sg_cfg.rt_protocol = cfg->rt_protocol;
|
||||
sg_cfg.nlflags = cfg->nlflags;
|
||||
return br_mdb_add_group_sg(&sg_cfg, sgmp, brmctx, flags, extack);
|
||||
err = br_mdb_add_group_sg(&sg_cfg, sgmp, brmctx, flags, extack);
|
||||
if (err)
|
||||
br_multicast_del_group(sgmp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int br_mdb_add_group_src(const struct br_mdb_config *cfg,
|
||||
|
|
@ -1047,6 +1052,7 @@ static int br_mdb_add_group(const struct br_mdb_config *cfg,
|
|||
struct net_bridge_mcast *brmctx;
|
||||
struct br_ip group = cfg->group;
|
||||
unsigned char flags = 0;
|
||||
int err;
|
||||
|
||||
brmctx = __br_mdb_choose_context(br, entry, extack);
|
||||
if (!brmctx)
|
||||
|
|
@ -1073,9 +1079,13 @@ static int br_mdb_add_group(const struct br_mdb_config *cfg,
|
|||
flags |= MDB_PG_FLAGS_PERMANENT;
|
||||
|
||||
if (br_multicast_is_star_g(&group))
|
||||
return br_mdb_add_group_star_g(cfg, mp, brmctx, flags, extack);
|
||||
err = br_mdb_add_group_star_g(cfg, mp, brmctx, flags, extack);
|
||||
else
|
||||
return br_mdb_add_group_sg(cfg, mp, brmctx, flags, extack);
|
||||
err = br_mdb_add_group_sg(cfg, mp, brmctx, flags, extack);
|
||||
if (err)
|
||||
br_multicast_del_group(mp);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __br_mdb_add(const struct br_mdb_config *cfg,
|
||||
|
|
|
|||
|
|
@ -647,6 +647,14 @@ static void br_multicast_del_mdb_entry(struct net_bridge_mdb_entry *mp)
|
|||
queue_work(system_long_wq, &br->mcast_gc_work);
|
||||
}
|
||||
|
||||
void br_multicast_del_group(struct net_bridge_mdb_entry *mp)
|
||||
{
|
||||
if (mp->ports || mp->host_joined)
|
||||
return;
|
||||
|
||||
br_multicast_del_mdb_entry(mp);
|
||||
}
|
||||
|
||||
static void br_multicast_group_expired(struct timer_list *t)
|
||||
{
|
||||
struct net_bridge_mdb_entry *mp = timer_container_of(mp, t, timer);
|
||||
|
|
@ -1554,6 +1562,7 @@ __br_multicast_add_group(struct net_bridge_mcast *brmctx,
|
|||
p = br_multicast_new_port_group(pmctx->port, group, *pp, 0, src,
|
||||
filter_mode, RTPROT_KERNEL, NULL);
|
||||
if (unlikely(!p)) {
|
||||
br_multicast_del_group(mp);
|
||||
p = ERR_PTR(-ENOMEM);
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -998,6 +998,7 @@ struct net_bridge_mdb_entry *
|
|||
br_mdb_ip_get(struct net_bridge *br, struct br_ip *dst);
|
||||
struct net_bridge_mdb_entry *
|
||||
br_multicast_new_group(struct net_bridge *br, struct br_ip *group);
|
||||
void br_multicast_del_group(struct net_bridge_mdb_entry *mp);
|
||||
struct net_bridge_port_group *
|
||||
br_multicast_new_port_group(struct net_bridge_port *port,
|
||||
const struct br_ip *group,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user