Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+106 -29
+18 -27
net/bridge/br_multicast.c
··· 244 244 245 245 lockdep_assert_held_once(&port->br->multicast_lock); 246 246 247 - if (!br_opt_get(port->br, BROPT_MCAST_VLAN_SNOOPING_ENABLED)) 248 - return NULL; 249 - 250 247 /* Take RCU to access the vlan. */ 251 248 rcu_read_lock(); 252 249 253 250 vlan = br_vlan_find(nbp_vlan_group_rcu(port), vid); 254 - if (vlan && !br_multicast_port_ctx_vlan_disabled(&vlan->port_mcast_ctx)) 251 + if (vlan) 255 252 pmctx = &vlan->port_mcast_ctx; 256 253 257 254 rcu_read_unlock(); ··· 698 701 u32 max = READ_ONCE(pmctx->mdb_max_entries); 699 702 u32 n = READ_ONCE(pmctx->mdb_n_entries); 700 703 701 - if (max && n >= max) { 704 + /* enforce the max limit when it's a port pmctx or a port-vlan pmctx 705 + * with snooping enabled 706 + */ 707 + if (!br_multicast_port_ctx_vlan_disabled(pmctx) && max && n >= max) { 702 708 NL_SET_ERR_MSG_FMT_MOD(extack, "%s is already in %u groups, and mcast_max_groups=%u", 703 709 what, n, max); 704 710 return -E2BIG; ··· 736 736 return err; 737 737 } 738 738 739 - /* Only count on the VLAN context if VID is given, and if snooping on 740 - * that VLAN is enabled. 741 - */ 739 + /* Only count on the VLAN context if VID is given */ 742 740 if (!group->vid) 743 741 return 0; 744 742 ··· 2009 2011 timer_setup(&pmctx->ip6_own_query.timer, 2010 2012 br_ip6_multicast_port_query_expired, 0); 2011 2013 #endif 2014 + /* initialize mdb_n_entries if a new port vlan is being created */ 2015 + if (vlan) { 2016 + struct net_bridge_port_group *pg; 2017 + u32 n = 0; 2018 + 2019 + spin_lock_bh(&port->br->multicast_lock); 2020 + hlist_for_each_entry(pg, &port->mglist, mglist) 2021 + if (pg->key.addr.vid == vlan->vid) 2022 + n++; 2023 + WRITE_ONCE(pmctx->mdb_n_entries, n); 2024 + spin_unlock_bh(&port->br->multicast_lock); 2025 + } 2012 2026 } 2013 2027 2014 2028 void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx) ··· 2103 2093 if (pmctx->multicast_router == MDB_RTR_TYPE_PERM) { 2104 2094 br_ip4_multicast_add_router(brmctx, pmctx); 2105 2095 br_ip6_multicast_add_router(brmctx, pmctx); 2106 - } 2107 - 2108 - if (br_multicast_port_ctx_is_vlan(pmctx)) { 2109 - struct net_bridge_port_group *pg; 2110 - u32 n = 0; 2111 - 2112 - /* The mcast_n_groups counter might be wrong. First, 2113 - * BR_VLFLAG_MCAST_ENABLED is toggled before temporary entries 2114 - * are flushed, thus mcast_n_groups after the toggle does not 2115 - * reflect the true values. And second, permanent entries added 2116 - * while BR_VLFLAG_MCAST_ENABLED was disabled, are not reflected 2117 - * either. Thus we have to refresh the counter. 2118 - */ 2119 - 2120 - hlist_for_each_entry(pg, &pmctx->port->mglist, mglist) { 2121 - if (pg->key.addr.vid == pmctx->vlan->vid) 2122 - n++; 2123 - } 2124 - WRITE_ONCE(pmctx->mdb_n_entries, n); 2125 2096 } 2126 2097 } 2127 2098
+88 -2
tools/testing/selftests/net/forwarding/bridge_mdb_max.sh
··· 28 28 test_8021d 29 29 test_8021q 30 30 test_8021qvs 31 + test_mdb_count_warning 31 32 " 32 33 33 34 NUM_NETIFS=4 ··· 84 83 { 85 84 local br_flags=$1; shift 86 85 87 - log_info "802.1q $br_flags${br_flags:+ }tests" 88 - 89 86 ip link add name br0 type bridge vlan_filtering 1 vlan_default_pvid 0 \ 90 87 mcast_snooping 1 $br_flags \ 91 88 mcast_igmp_version 3 mcast_mld_version 2 ··· 105 106 106 107 switch_create_8021qvs() 107 108 { 109 + log_info "802.1q mcast_vlan_snooping 1 tests" 108 110 switch_create_8021q "mcast_vlan_snooping 1" 109 111 bridge vlan global set dev br0 vid 10 mcast_igmp_version 3 110 112 bridge vlan global set dev br0 vid 10 mcast_mld_version 2 ··· 1272 1272 test_toggle_vlan_snooping_permanent 1273 1273 } 1274 1274 1275 + mdb_count_check_warn() 1276 + { 1277 + local msg=$1; shift 1278 + 1279 + dmesg | grep -q "WARNING:.*br_multicast_port_ngroups_dec.*" 1280 + check_fail $? "$msg" 1281 + } 1282 + 1283 + test_mdb_count_mcast_vlan_snooping_flush() 1284 + { 1285 + RET=0 1286 + 1287 + # check if we already have a warning 1288 + mdb_count_check_warn "Check MDB entries count warning before test" 1289 + 1290 + bridge mdb add dev br0 port "$swp1" grp 239.0.0.1 permanent vid 10 1291 + ip link set dev br0 down 1292 + ip link set dev br0 type bridge mcast_vlan_snooping 1 1293 + bridge mdb flush dev br0 1294 + 1295 + mdb_count_check_warn "Check MDB entries count warning after test" 1296 + 1297 + ip link set dev br0 type bridge mcast_vlan_snooping 0 1298 + ip link set dev br0 up 1299 + 1300 + log_test "MDB count warning: mcast_vlan_snooping and MDB flush" 1301 + } 1302 + 1303 + test_mdb_count_mcast_snooping_flush() 1304 + { 1305 + RET=0 1306 + 1307 + # check if we already have a warning 1308 + mdb_count_check_warn "Check MDB entries count warning before test" 1309 + 1310 + bridge mdb add dev br0 port "$swp1" grp 239.0.0.1 permanent vid 10 1311 + ip link set dev br0 type bridge mcast_snooping 0 1312 + ip link set dev br0 type bridge mcast_vlan_snooping 1 1313 + bridge mdb flush dev br0 1314 + 1315 + mdb_count_check_warn "Check MDB entries count warning after test" 1316 + 1317 + ip link set dev br0 type bridge mcast_vlan_snooping 0 1318 + ip link set dev br0 type bridge mcast_snooping 1 1319 + 1320 + log_test "MDB count warning: mcast_snooping and MDB flush" 1321 + } 1322 + 1323 + test_mdb_count_vlan_state_flush() 1324 + { 1325 + RET=0 1326 + 1327 + # check if we already have a warning 1328 + mdb_count_check_warn "Check MDB entries count warning before test" 1329 + 1330 + bridge mdb add dev br0 port "$swp1" grp 239.0.0.1 permanent vid 10 1331 + ip link set dev br0 down 1332 + bridge vlan set vid 10 dev "$swp1" state blocking 1333 + ip link set dev br0 type bridge mcast_vlan_snooping 1 1334 + ip link set dev br0 up 1335 + bridge mdb flush dev br0 1336 + 1337 + mdb_count_check_warn "Check MDB entries count warning after test" 1338 + 1339 + bridge vlan set vid 10 dev "$swp1" state forwarding 1340 + ip link set dev br0 type bridge mcast_vlan_snooping 0 1341 + 1342 + log_test "MDB count warning: disabled vlan state and MDB flush" 1343 + } 1344 + 1275 1345 # test groups 1276 1346 1277 1347 test_8021d() ··· 1367 1297 { 1368 1298 # Tests for vlan_filtering 1 mcast_vlan_snooping 0. 1369 1299 1300 + log_info "802.1q tests" 1370 1301 switch_create_8021q 1371 1302 setup_wait 1372 1303 ··· 1401 1330 test_8021qvs_maxgroups_cfg6 1402 1331 test_8021qvs_maxgroups_ctl6 1403 1332 test_8021qvs_toggle_vlan_snooping 1333 + 1334 + switch_destroy 1335 + } 1336 + 1337 + test_mdb_count_warning() 1338 + { 1339 + # Tests for mdb_n_entries warning 1340 + 1341 + log_info "MDB count warning tests" 1342 + switch_create_8021q 1343 + setup_wait 1344 + 1345 + test_mdb_count_mcast_vlan_snooping_flush 1346 + test_mdb_count_mcast_snooping_flush 1347 + test_mdb_count_vlan_state_flush 1404 1348 1405 1349 switch_destroy 1406 1350 }