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

Merge branch 'net-vlan-fix-vlan-0-refcount-imbalance-of-toggling-filtering-during-runtime'

Dong Chenchen says:

====================
net: vlan: fix VLAN 0 refcount imbalance of toggling filtering during runtime

Fix VLAN 0 refcount imbalance of toggling filtering during runtime.
====================

Link: https://patch.msgid.link/20250716034504.2285203-1-dongchenchen2@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+120 -21
+33 -9
net/8021q/vlan.c
··· 357 357 return err; 358 358 } 359 359 360 + static void vlan_vid0_add(struct net_device *dev) 361 + { 362 + struct vlan_info *vlan_info; 363 + int err; 364 + 365 + if (!(dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) 366 + return; 367 + 368 + pr_info("adding VLAN 0 to HW filter on device %s\n", dev->name); 369 + 370 + err = vlan_vid_add(dev, htons(ETH_P_8021Q), 0); 371 + if (err) 372 + return; 373 + 374 + vlan_info = rtnl_dereference(dev->vlan_info); 375 + vlan_info->auto_vid0 = true; 376 + } 377 + 378 + static void vlan_vid0_del(struct net_device *dev) 379 + { 380 + struct vlan_info *vlan_info = rtnl_dereference(dev->vlan_info); 381 + 382 + if (!vlan_info || !vlan_info->auto_vid0) 383 + return; 384 + 385 + vlan_info->auto_vid0 = false; 386 + vlan_vid_del(dev, htons(ETH_P_8021Q), 0); 387 + } 388 + 360 389 static int vlan_device_event(struct notifier_block *unused, unsigned long event, 361 390 void *ptr) 362 391 { ··· 407 378 return notifier_from_errno(err); 408 379 } 409 380 410 - if ((event == NETDEV_UP) && 411 - (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { 412 - pr_info("adding VLAN 0 to HW filter on device %s\n", 413 - dev->name); 414 - vlan_vid_add(dev, htons(ETH_P_8021Q), 0); 415 - } 416 - if (event == NETDEV_DOWN && 417 - (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) 418 - vlan_vid_del(dev, htons(ETH_P_8021Q), 0); 381 + if (event == NETDEV_UP) 382 + vlan_vid0_add(dev); 383 + else if (event == NETDEV_DOWN) 384 + vlan_vid0_del(dev); 419 385 420 386 vlan_info = rtnl_dereference(dev->vlan_info); 421 387 if (!vlan_info)
+1
net/8021q/vlan.h
··· 33 33 struct vlan_group grp; 34 34 struct list_head vid_list; 35 35 unsigned int nr_vids; 36 + bool auto_vid0; 36 37 struct rcu_head rcu; 37 38 }; 38 39
+86 -12
tools/testing/selftests/net/vlan_hw_filter.sh
··· 3 3 4 4 readonly NETNS="ns-$(mktemp -u XXXXXX)" 5 5 6 + ALL_TESTS=" 7 + test_vlan_filter_check 8 + test_vlan0_del_crash_01 9 + test_vlan0_del_crash_02 10 + test_vlan0_del_crash_03 11 + test_vid0_memleak 12 + " 13 + 6 14 ret=0 7 15 16 + setup() { 17 + ip netns add ${NETNS} 18 + } 19 + 8 20 cleanup() { 9 - ip netns del $NETNS 21 + ip netns del $NETNS 2>/dev/null 10 22 } 11 23 12 24 trap cleanup EXIT 13 25 14 26 fail() { 15 - echo "ERROR: ${1:-unexpected return code} (ret: $_)" >&2 16 - ret=1 27 + echo "ERROR: ${1:-unexpected return code} (ret: $_)" >&2 28 + ret=1 17 29 } 18 30 19 - ip netns add ${NETNS} 20 - ip netns exec ${NETNS} ip link add bond0 type bond mode 0 21 - ip netns exec ${NETNS} ip link add bond_slave_1 type veth peer veth2 22 - ip netns exec ${NETNS} ip link set bond_slave_1 master bond0 23 - ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off 24 - ip netns exec ${NETNS} ip link add link bond_slave_1 name bond_slave_1.0 type vlan id 0 25 - ip netns exec ${NETNS} ip link add link bond0 name bond0.0 type vlan id 0 26 - ip netns exec ${NETNS} ip link set bond_slave_1 nomaster 27 - ip netns exec ${NETNS} ip link del veth2 || fail "Please check vlan HW filter function" 31 + tests_run() 32 + { 33 + local current_test 34 + for current_test in ${TESTS:-$ALL_TESTS}; do 35 + $current_test 36 + done 37 + } 28 38 39 + test_vlan_filter_check() { 40 + setup 41 + ip netns exec ${NETNS} ip link add bond0 type bond mode 0 42 + ip netns exec ${NETNS} ip link add bond_slave_1 type veth peer veth2 43 + ip netns exec ${NETNS} ip link set bond_slave_1 master bond0 44 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off 45 + ip netns exec ${NETNS} ip link add link bond_slave_1 name bond_slave_1.0 type vlan id 0 46 + ip netns exec ${NETNS} ip link add link bond0 name bond0.0 type vlan id 0 47 + ip netns exec ${NETNS} ip link set bond_slave_1 nomaster 48 + ip netns exec ${NETNS} ip link del veth2 || fail "Please check vlan HW filter function" 49 + cleanup 50 + } 51 + 52 + #enable vlan_filter feature of real_dev with vlan0 during running time 53 + test_vlan0_del_crash_01() { 54 + setup 55 + ip netns exec ${NETNS} ip link add bond0 type bond mode 0 56 + ip netns exec ${NETNS} ip link add link bond0 name vlan0 type vlan id 0 protocol 802.1q 57 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off 58 + ip netns exec ${NETNS} ifconfig bond0 up 59 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter on 60 + ip netns exec ${NETNS} ifconfig bond0 down 61 + ip netns exec ${NETNS} ifconfig bond0 up 62 + ip netns exec ${NETNS} ip link del vlan0 || fail "Please check vlan HW filter function" 63 + cleanup 64 + } 65 + 66 + #enable vlan_filter feature and add vlan0 for real_dev during running time 67 + test_vlan0_del_crash_02() { 68 + setup 69 + ip netns exec ${NETNS} ip link add bond0 type bond mode 0 70 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off 71 + ip netns exec ${NETNS} ifconfig bond0 up 72 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter on 73 + ip netns exec ${NETNS} ip link add link bond0 name vlan0 type vlan id 0 protocol 802.1q 74 + ip netns exec ${NETNS} ifconfig bond0 down 75 + ip netns exec ${NETNS} ifconfig bond0 up 76 + ip netns exec ${NETNS} ip link del vlan0 || fail "Please check vlan HW filter function" 77 + cleanup 78 + } 79 + 80 + #enable vlan_filter feature of real_dev during running time 81 + #test kernel_bug of vlan unregister 82 + test_vlan0_del_crash_03() { 83 + setup 84 + ip netns exec ${NETNS} ip link add bond0 type bond mode 0 85 + ip netns exec ${NETNS} ip link add link bond0 name vlan0 type vlan id 0 protocol 802.1q 86 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off 87 + ip netns exec ${NETNS} ifconfig bond0 up 88 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter on 89 + ip netns exec ${NETNS} ifconfig bond0 down 90 + ip netns exec ${NETNS} ip link del vlan0 || fail "Please check vlan HW filter function" 91 + cleanup 92 + } 93 + 94 + test_vid0_memleak() { 95 + setup 96 + ip netns exec ${NETNS} ip link add bond0 up type bond mode 0 97 + ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off 98 + ip netns exec ${NETNS} ip link del dev bond0 || fail "Please check vlan HW filter function" 99 + cleanup 100 + } 101 + 102 + tests_run 29 103 exit $ret