mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 10:41:49 +02:00
Merge branch 'net-bridge-mcast-fix-mdb_n_entries-counting-warning'
Nikolay Aleksandrov says: ==================== net: bridge: mcast: fix mdb_n_entries counting warning The first patch fixes a warning in the mdb_n_entries code which was reported by syzbot, the second patch adds tests for different ways which used to trigger said warning. For more information please check the individual commit messages. ==================== Link: https://patch.msgid.link/20260213070031.1400003-1-nikolay@nvidia.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
9874b1ba46
|
|
@ -244,14 +244,11 @@ br_multicast_port_vid_to_port_ctx(struct net_bridge_port *port, u16 vid)
|
|||
|
||||
lockdep_assert_held_once(&port->br->multicast_lock);
|
||||
|
||||
if (!br_opt_get(port->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))
|
||||
return NULL;
|
||||
|
||||
/* Take RCU to access the vlan. */
|
||||
rcu_read_lock();
|
||||
|
||||
vlan = br_vlan_find(nbp_vlan_group_rcu(port), vid);
|
||||
if (vlan && !br_multicast_port_ctx_vlan_disabled(&vlan->port_mcast_ctx))
|
||||
if (vlan)
|
||||
pmctx = &vlan->port_mcast_ctx;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
@ -701,7 +698,10 @@ br_multicast_port_ngroups_inc_one(struct net_bridge_mcast_port *pmctx,
|
|||
u32 max = READ_ONCE(pmctx->mdb_max_entries);
|
||||
u32 n = READ_ONCE(pmctx->mdb_n_entries);
|
||||
|
||||
if (max && n >= max) {
|
||||
/* enforce the max limit when it's a port pmctx or a port-vlan pmctx
|
||||
* with snooping enabled
|
||||
*/
|
||||
if (!br_multicast_port_ctx_vlan_disabled(pmctx) && max && n >= max) {
|
||||
NL_SET_ERR_MSG_FMT_MOD(extack, "%s is already in %u groups, and mcast_max_groups=%u",
|
||||
what, n, max);
|
||||
return -E2BIG;
|
||||
|
|
@ -736,9 +736,7 @@ static int br_multicast_port_ngroups_inc(struct net_bridge_port *port,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Only count on the VLAN context if VID is given, and if snooping on
|
||||
* that VLAN is enabled.
|
||||
*/
|
||||
/* Only count on the VLAN context if VID is given */
|
||||
if (!group->vid)
|
||||
return 0;
|
||||
|
||||
|
|
@ -2011,6 +2009,18 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
|
|||
timer_setup(&pmctx->ip6_own_query.timer,
|
||||
br_ip6_multicast_port_query_expired, 0);
|
||||
#endif
|
||||
/* initialize mdb_n_entries if a new port vlan is being created */
|
||||
if (vlan) {
|
||||
struct net_bridge_port_group *pg;
|
||||
u32 n = 0;
|
||||
|
||||
spin_lock_bh(&port->br->multicast_lock);
|
||||
hlist_for_each_entry(pg, &port->mglist, mglist)
|
||||
if (pg->key.addr.vid == vlan->vid)
|
||||
n++;
|
||||
WRITE_ONCE(pmctx->mdb_n_entries, n);
|
||||
spin_unlock_bh(&port->br->multicast_lock);
|
||||
}
|
||||
}
|
||||
|
||||
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx)
|
||||
|
|
@ -2094,25 +2104,6 @@ static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
|
|||
br_ip4_multicast_add_router(brmctx, pmctx);
|
||||
br_ip6_multicast_add_router(brmctx, pmctx);
|
||||
}
|
||||
|
||||
if (br_multicast_port_ctx_is_vlan(pmctx)) {
|
||||
struct net_bridge_port_group *pg;
|
||||
u32 n = 0;
|
||||
|
||||
/* The mcast_n_groups counter might be wrong. First,
|
||||
* BR_VLFLAG_MCAST_ENABLED is toggled before temporary entries
|
||||
* are flushed, thus mcast_n_groups after the toggle does not
|
||||
* reflect the true values. And second, permanent entries added
|
||||
* while BR_VLFLAG_MCAST_ENABLED was disabled, are not reflected
|
||||
* either. Thus we have to refresh the counter.
|
||||
*/
|
||||
|
||||
hlist_for_each_entry(pg, &pmctx->port->mglist, mglist) {
|
||||
if (pg->key.addr.vid == pmctx->vlan->vid)
|
||||
n++;
|
||||
}
|
||||
WRITE_ONCE(pmctx->mdb_n_entries, n);
|
||||
}
|
||||
}
|
||||
|
||||
static void br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ ALL_TESTS="
|
|||
test_8021d
|
||||
test_8021q
|
||||
test_8021qvs
|
||||
test_mdb_count_warning
|
||||
"
|
||||
|
||||
NUM_NETIFS=4
|
||||
|
|
@ -83,8 +84,6 @@ switch_create_8021q()
|
|||
{
|
||||
local br_flags=$1; shift
|
||||
|
||||
log_info "802.1q $br_flags${br_flags:+ }tests"
|
||||
|
||||
ip link add name br0 type bridge vlan_filtering 1 vlan_default_pvid 0 \
|
||||
mcast_snooping 1 $br_flags \
|
||||
mcast_igmp_version 3 mcast_mld_version 2
|
||||
|
|
@ -106,6 +105,7 @@ switch_create_8021q()
|
|||
|
||||
switch_create_8021qvs()
|
||||
{
|
||||
log_info "802.1q mcast_vlan_snooping 1 tests"
|
||||
switch_create_8021q "mcast_vlan_snooping 1"
|
||||
bridge vlan global set dev br0 vid 10 mcast_igmp_version 3
|
||||
bridge vlan global set dev br0 vid 10 mcast_mld_version 2
|
||||
|
|
@ -1272,6 +1272,76 @@ test_8021qvs_toggle_vlan_snooping()
|
|||
test_toggle_vlan_snooping_permanent
|
||||
}
|
||||
|
||||
mdb_count_check_warn()
|
||||
{
|
||||
local msg=$1; shift
|
||||
|
||||
dmesg | grep -q "WARNING:.*br_multicast_port_ngroups_dec.*"
|
||||
check_fail $? "$msg"
|
||||
}
|
||||
|
||||
test_mdb_count_mcast_vlan_snooping_flush()
|
||||
{
|
||||
RET=0
|
||||
|
||||
# check if we already have a warning
|
||||
mdb_count_check_warn "Check MDB entries count warning before test"
|
||||
|
||||
bridge mdb add dev br0 port "$swp1" grp 239.0.0.1 permanent vid 10
|
||||
ip link set dev br0 down
|
||||
ip link set dev br0 type bridge mcast_vlan_snooping 1
|
||||
bridge mdb flush dev br0
|
||||
|
||||
mdb_count_check_warn "Check MDB entries count warning after test"
|
||||
|
||||
ip link set dev br0 type bridge mcast_vlan_snooping 0
|
||||
ip link set dev br0 up
|
||||
|
||||
log_test "MDB count warning: mcast_vlan_snooping and MDB flush"
|
||||
}
|
||||
|
||||
test_mdb_count_mcast_snooping_flush()
|
||||
{
|
||||
RET=0
|
||||
|
||||
# check if we already have a warning
|
||||
mdb_count_check_warn "Check MDB entries count warning before test"
|
||||
|
||||
bridge mdb add dev br0 port "$swp1" grp 239.0.0.1 permanent vid 10
|
||||
ip link set dev br0 type bridge mcast_snooping 0
|
||||
ip link set dev br0 type bridge mcast_vlan_snooping 1
|
||||
bridge mdb flush dev br0
|
||||
|
||||
mdb_count_check_warn "Check MDB entries count warning after test"
|
||||
|
||||
ip link set dev br0 type bridge mcast_vlan_snooping 0
|
||||
ip link set dev br0 type bridge mcast_snooping 1
|
||||
|
||||
log_test "MDB count warning: mcast_snooping and MDB flush"
|
||||
}
|
||||
|
||||
test_mdb_count_vlan_state_flush()
|
||||
{
|
||||
RET=0
|
||||
|
||||
# check if we already have a warning
|
||||
mdb_count_check_warn "Check MDB entries count warning before test"
|
||||
|
||||
bridge mdb add dev br0 port "$swp1" grp 239.0.0.1 permanent vid 10
|
||||
ip link set dev br0 down
|
||||
bridge vlan set vid 10 dev "$swp1" state blocking
|
||||
ip link set dev br0 type bridge mcast_vlan_snooping 1
|
||||
ip link set dev br0 up
|
||||
bridge mdb flush dev br0
|
||||
|
||||
mdb_count_check_warn "Check MDB entries count warning after test"
|
||||
|
||||
bridge vlan set vid 10 dev "$swp1" state forwarding
|
||||
ip link set dev br0 type bridge mcast_vlan_snooping 0
|
||||
|
||||
log_test "MDB count warning: disabled vlan state and MDB flush"
|
||||
}
|
||||
|
||||
# test groups
|
||||
|
||||
test_8021d()
|
||||
|
|
@ -1297,6 +1367,7 @@ test_8021q()
|
|||
{
|
||||
# Tests for vlan_filtering 1 mcast_vlan_snooping 0.
|
||||
|
||||
log_info "802.1q tests"
|
||||
switch_create_8021q
|
||||
setup_wait
|
||||
|
||||
|
|
@ -1334,6 +1405,21 @@ test_8021qvs()
|
|||
switch_destroy
|
||||
}
|
||||
|
||||
test_mdb_count_warning()
|
||||
{
|
||||
# Tests for mdb_n_entries warning
|
||||
|
||||
log_info "MDB count warning tests"
|
||||
switch_create_8021q
|
||||
setup_wait
|
||||
|
||||
test_mdb_count_mcast_vlan_snooping_flush
|
||||
test_mdb_count_mcast_snooping_flush
|
||||
test_mdb_count_vlan_state_flush
|
||||
|
||||
switch_destroy
|
||||
}
|
||||
|
||||
if ! bridge link help 2>&1 | grep -q "mcast_max_groups"; then
|
||||
echo "SKIP: iproute2 too old, missing bridge \"mcast_max_groups\" support"
|
||||
exit $ksft_skip
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user