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

selftest: netcons: add test for netconsole over bonded interfaces

This patch adds a selftest that verifies netconsole functionality
over bonded network interfaces using netdevsim. It sets up two bonded
interfaces acting as transmit (TX) and receive (RX) ends, placed in
separate network namespaces. The test sends kernel log messages and
verifies that they are properly received on the bonded RX interfaces
with both IPv4 and IPv6, and using basic and extended netconsole
formats.

This patchset aims to test a long-standing netpoll subsystem where
netpoll has multiple users. (in this case netconsole and bonding). A
similar selftest has been discussed in [1] and [2].

This test also tries to enable bonding and netpoll in different order,
just to guarantee that all the possibilities are exercised.

Link: https://lore.kernel.org/all/20250905-netconsole_torture-v3-0-875c7febd316@debian.org/ [1]
Link: https://lore.kernel.org/lkml/96b940137a50e5c387687bb4f57de8b0435a653f.1404857349.git.decot@googlers.com/ [2]
Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20251107-netconsole_torture-v10-4-749227b55f63@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Breno Leitao and committed by
Jakub Kicinski
236682db 6701896e

+414 -7
+2
tools/testing/selftests/drivers/net/bonding/Makefile
··· 14 14 dev_addr_lists.sh \ 15 15 mode-1-recovery-updelay.sh \ 16 16 mode-2-recovery-updelay.sh \ 17 + netcons_over_bonding.sh \ 17 18 # end of TEST_PROGS 18 19 19 20 TEST_FILES := \ ··· 25 24 26 25 TEST_INCLUDES := \ 27 26 ../../../net/lib.sh \ 27 + ../lib/sh/lib_netcons.sh \ 28 28 ../../../net/forwarding/lib.sh \ 29 29 # end of TEST_INCLUDES 30 30
+4
tools/testing/selftests/drivers/net/bonding/config
··· 1 1 CONFIG_BONDING=y 2 2 CONFIG_BRIDGE=y 3 + CONFIG_CONFIGFS_FS=y 3 4 CONFIG_DUMMY=y 4 5 CONFIG_INET_ESP=y 5 6 CONFIG_INET_ESP_OFFLOAD=y ··· 10 9 CONFIG_NET_ACT_GACT=y 11 10 CONFIG_NET_CLS_FLOWER=y 12 11 CONFIG_NET_CLS_MATCHALL=m 12 + CONFIG_NETCONSOLE=m 13 + CONFIG_NETCONSOLE_DYNAMIC=y 14 + CONFIG_NETCONSOLE_EXTENDED_LOG=y 13 15 CONFIG_NETDEVSIM=m 14 16 CONFIG_NET_SCH_INGRESS=y 15 17 CONFIG_NLMON=y
+361
tools/testing/selftests/drivers/net/bonding/netcons_over_bonding.sh
··· 1 + #!/usr/bin/env bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # This selftest exercises trying to have multiple netpoll users at the same 5 + # time. 6 + # 7 + # This selftest has multiple smalls test inside, and the goal is to 8 + # get interfaces with bonding and netconsole in different orders in order 9 + # to catch any possible issue. 10 + # 11 + # The main test composes of four interfaces being created using netdevsim; two 12 + # of them are bonded to serve as the netconsole's transmit interface. The 13 + # remaining two interfaces are similarly bonded and assigned to a separate 14 + # network namespace, which acts as the receive interface, where socat monitors 15 + # for incoming messages. 16 + # 17 + # A netconsole message is then sent to ensure it is properly received across 18 + # this configuration. 19 + # 20 + # Later, run a few other tests, to make sure that bonding and netconsole 21 + # cannot coexist. 22 + # 23 + # The test's objective is to exercise netpoll usage when managed simultaneously 24 + # by multiple subsystems (netconsole and bonding). 25 + # 26 + # Author: Breno Leitao <leitao@debian.org> 27 + 28 + set -euo pipefail 29 + 30 + SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")") 31 + 32 + source "${SCRIPTDIR}"/../lib/sh/lib_netcons.sh 33 + 34 + modprobe netdevsim 2> /dev/null || true 35 + modprobe netconsole 2> /dev/null || true 36 + modprobe bonding 2> /dev/null || true 37 + modprobe veth 2> /dev/null || true 38 + 39 + # The content of kmsg will be save to the following file 40 + OUTPUT_FILE="/tmp/${TARGET}" 41 + 42 + # Check for basic system dependency and exit if not found 43 + check_for_dependencies 44 + # Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5) 45 + echo "6 5" > /proc/sys/kernel/printk 46 + # Remove the namespace, interfaces and netconsole target on exit 47 + trap cleanup_bond EXIT 48 + 49 + FORMAT="extended" 50 + IP_VERSION="ipv4" 51 + VETH0="veth"$(( RANDOM % 256)) 52 + VETH1="veth"$((256 + RANDOM % 256)) 53 + TXNS="" 54 + RXNS="" 55 + 56 + # Create "bond_tx_XX" and "bond_rx_XX" interfaces, and set DSTIF and SRCIF with 57 + # the bonding interfaces 58 + function setup_bonding_ifaces() { 59 + local RAND=$(( RANDOM % 100 )) 60 + BOND_TX_MAIN_IF="bond_tx_$RAND" 61 + BOND_RX_MAIN_IF="bond_rx_$RAND" 62 + 63 + # Setup TX 64 + if ! ip -n "${TXNS}" link add "${BOND_TX_MAIN_IF}" type bond mode balance-rr 65 + then 66 + echo "Failed to create bond TX interface. Is CONFIG_BONDING set?" >&2 67 + # only clean nsim ifaces and namespace. Nothing else has been 68 + # initialized 69 + cleanup_bond_nsim 70 + trap - EXIT 71 + exit "${ksft_skip}" 72 + fi 73 + 74 + # create_netdevsim() got the interface up, but it needs to be down 75 + # before being enslaved. 76 + ip -n "${TXNS}" \ 77 + link set "${BOND_TX1_SLAVE_IF}" down 78 + ip -n "${TXNS}" \ 79 + link set "${BOND_TX2_SLAVE_IF}" down 80 + ip -n "${TXNS}" \ 81 + link set "${BOND_TX1_SLAVE_IF}" master "${BOND_TX_MAIN_IF}" 82 + ip -n "${TXNS}" \ 83 + link set "${BOND_TX2_SLAVE_IF}" master "${BOND_TX_MAIN_IF}" 84 + ip -n "${TXNS}" \ 85 + link set "${BOND_TX_MAIN_IF}" up 86 + 87 + # Setup RX 88 + ip -n "${RXNS}" \ 89 + link add "${BOND_RX_MAIN_IF}" type bond mode balance-rr 90 + ip -n "${RXNS}" \ 91 + link set "${BOND_RX1_SLAVE_IF}" down 92 + ip -n "${RXNS}" \ 93 + link set "${BOND_RX2_SLAVE_IF}" down 94 + ip -n "${RXNS}" \ 95 + link set "${BOND_RX1_SLAVE_IF}" master "${BOND_RX_MAIN_IF}" 96 + ip -n "${RXNS}" \ 97 + link set "${BOND_RX2_SLAVE_IF}" master "${BOND_RX_MAIN_IF}" 98 + ip -n "${RXNS}" \ 99 + link set "${BOND_RX_MAIN_IF}" up 100 + 101 + export DSTIF="${BOND_RX_MAIN_IF}" 102 + export SRCIF="${BOND_TX_MAIN_IF}" 103 + } 104 + 105 + # Create 4 netdevsim interfaces. Two of them will be bound to TX bonding iface 106 + # and the other two will be bond to the RX interface (on the other namespace) 107 + function create_ifaces_bond() { 108 + BOND_TX1_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_TX_1}" "${TXNS}") 109 + BOND_TX2_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_TX_2}" "${TXNS}") 110 + BOND_RX1_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_RX_1}" "${RXNS}") 111 + BOND_RX2_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_RX_2}" "${RXNS}") 112 + } 113 + 114 + # netdevsim link BOND_TX to BOND_RX interfaces 115 + function link_ifaces_bond() { 116 + local BOND_TX1_SLAVE_IFIDX 117 + local BOND_TX2_SLAVE_IFIDX 118 + local BOND_RX1_SLAVE_IFIDX 119 + local BOND_RX2_SLAVE_IFIDX 120 + local TXNS_FD 121 + local RXNS_FD 122 + 123 + BOND_TX1_SLAVE_IFIDX=$(ip netns exec "${TXNS}" \ 124 + cat /sys/class/net/"$BOND_TX1_SLAVE_IF"/ifindex) 125 + BOND_TX2_SLAVE_IFIDX=$(ip netns exec "${TXNS}" \ 126 + cat /sys/class/net/"$BOND_TX2_SLAVE_IF"/ifindex) 127 + BOND_RX1_SLAVE_IFIDX=$(ip netns exec "${RXNS}" \ 128 + cat /sys/class/net/"$BOND_RX1_SLAVE_IF"/ifindex) 129 + BOND_RX2_SLAVE_IFIDX=$(ip netns exec "${RXNS}" \ 130 + cat /sys/class/net/"$BOND_RX2_SLAVE_IF"/ifindex) 131 + 132 + exec {TXNS_FD}</var/run/netns/"${TXNS}" 133 + exec {RXNS_FD}</var/run/netns/"${RXNS}" 134 + 135 + # Linking TX ifaces to the RX ones (on the other namespace) 136 + echo "${TXNS_FD}:$BOND_TX1_SLAVE_IFIDX $RXNS_FD:$BOND_RX1_SLAVE_IFIDX" \ 137 + > "$NSIM_DEV_SYS_LINK" 138 + echo "${TXNS_FD}:$BOND_TX2_SLAVE_IFIDX $RXNS_FD:$BOND_RX2_SLAVE_IFIDX" \ 139 + > "$NSIM_DEV_SYS_LINK" 140 + 141 + exec {TXNS_FD}<&- 142 + exec {RXNS_FD}<&- 143 + } 144 + 145 + function create_all_ifaces() { 146 + # setup_ns function is coming from lib.sh 147 + setup_ns TXNS RXNS 148 + export NAMESPACE="${RXNS}" 149 + 150 + # Create two interfaces for RX and two for TX 151 + create_ifaces_bond 152 + # Link netlink ifaces 153 + link_ifaces_bond 154 + } 155 + 156 + # configure DSTIF and SRCIF IPs 157 + function configure_ifaces_ips() { 158 + local IP_VERSION=${1:-"ipv4"} 159 + select_ipv4_or_ipv6 "${IP_VERSION}" 160 + 161 + ip -n "${RXNS}" addr add "${DSTIP}"/24 dev "${DSTIF}" 162 + ip -n "${RXNS}" link set "${DSTIF}" up 163 + 164 + ip -n "${TXNS}" addr add "${SRCIP}"/24 dev "${SRCIF}" 165 + ip -n "${TXNS}" link set "${SRCIF}" up 166 + } 167 + 168 + function test_enable_netpoll_on_enslaved_iface() { 169 + echo 0 > "${NETCONS_PATH}"/enabled 170 + 171 + # At this stage, BOND_TX1_SLAVE_IF is enslaved to BOND_TX_MAIN_IF, and 172 + # linked to BOND_RX1_SLAVE_IF inside the namespace. 173 + echo "${BOND_TX1_SLAVE_IF}" > "${NETCONS_PATH}"/dev_name 174 + 175 + # This should fail with the following message in dmesg: 176 + # netpoll: netconsole: ethX is a slave device, aborting 177 + set +e 178 + enable_netcons_ns 2> /dev/null 179 + set -e 180 + 181 + if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 1 ]] 182 + then 183 + echo "test failed: Bonding and netpoll cannot co-exists." >&2 184 + exit "${ksft_fail}" 185 + fi 186 + } 187 + 188 + function test_delete_bond_and_reenable_target() { 189 + ip -n "${TXNS}" \ 190 + link delete "${BOND_TX_MAIN_IF}" type bond 191 + 192 + # BOND_TX1_SLAVE_IF is not attached to a bond interface anymore 193 + # netpoll can be plugged in there 194 + echo "${BOND_TX1_SLAVE_IF}" > "${NETCONS_PATH}"/dev_name 195 + 196 + # this should work, since the interface is not enslaved 197 + enable_netcons_ns 198 + 199 + if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 0 ]] 200 + then 201 + echo "test failed: Unable to start netpoll on an unbond iface." >&2 202 + exit "${ksft_fail}" 203 + fi 204 + } 205 + 206 + # Send a netconsole message to the netconsole target 207 + function test_send_netcons_msg_through_bond_iface() { 208 + # Listen for netconsole port inside the namespace and 209 + # destination interface 210 + listen_port_and_save_to "${OUTPUT_FILE}" "${IP_VERSION}" & 211 + # Wait for socat to start and listen to the port. 212 + wait_for_port "${RXNS}" "${PORT}" "${IP_VERSION}" 213 + # Send the message 214 + echo "${MSG}: ${TARGET}" > /dev/kmsg 215 + # Wait until socat saves the file to disk 216 + busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}" 217 + # Make sure the message was received in the dst part 218 + # and exit 219 + validate_result "${OUTPUT_FILE}" "${FORMAT}" 220 + # kill socat in case it is still running 221 + pkill_socat 222 + } 223 + 224 + # BOND_TX1_SLAVE_IF has netconsole enabled on it, bind it to BOND_TX_MAIN_IF. 225 + # Given BOND_TX_MAIN_IF was deleted, recreate it first 226 + function test_enslave_netcons_enabled_iface { 227 + # netconsole got disabled while the interface was down 228 + if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 0 ]] 229 + then 230 + echo "test failed: netconsole expected to be enabled against BOND_TX1_SLAVE_IF" >&2 231 + exit "${ksft_fail}" 232 + fi 233 + 234 + # recreate the bonding iface. it got deleted by previous 235 + # test (test_delete_bond_and_reenable_target) 236 + ip -n "${TXNS}" \ 237 + link add "${BOND_TX_MAIN_IF}" type bond mode balance-rr 238 + 239 + # sub-interface need to be down before attaching to bonding 240 + # This will also disable netconsole. 241 + ip -n "${TXNS}" \ 242 + link set "${BOND_TX1_SLAVE_IF}" down 243 + ip -n "${TXNS}" \ 244 + link set "${BOND_TX1_SLAVE_IF}" master "${BOND_TX_MAIN_IF}" 245 + ip -n "${TXNS}" \ 246 + link set "${BOND_TX_MAIN_IF}" up 247 + 248 + # netconsole got disabled while the interface was down 249 + if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 1 ]] 250 + then 251 + echo "test failed: Device is part of a bond iface, cannot have netcons enabled" >&2 252 + exit "${ksft_fail}" 253 + fi 254 + } 255 + 256 + # Get netconsole enabled on a bonding interface and attach a second 257 + # sub-interface. 258 + function test_enslave_iface_to_bond { 259 + # BOND_TX_MAIN_IF has only BOND_TX1_SLAVE_IF right now 260 + echo "${BOND_TX_MAIN_IF}" > "${NETCONS_PATH}"/dev_name 261 + enable_netcons_ns 262 + 263 + # netcons is attached to bond0 and BOND_TX1_SLAVE_IF is 264 + # part of BOND_TX_MAIN_IF. Attach BOND_TX2_SLAVE_IF to BOND_TX_MAIN_IF. 265 + ip -n "${TXNS}" \ 266 + link set "${BOND_TX2_SLAVE_IF}" master "${BOND_TX_MAIN_IF}" 267 + if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 0 ]] 268 + then 269 + echo "test failed: Netconsole should be enabled on bonding interface. Failed" >&2 270 + exit "${ksft_fail}" 271 + fi 272 + } 273 + 274 + function test_enslave_iff_disabled_netpoll_iface { 275 + local ret 276 + 277 + # Create two interfaces. veth interfaces it known to have 278 + # IFF_DISABLE_NETPOLL set 279 + if ! ip link add "${VETH0}" type veth peer name "${VETH1}" 280 + then 281 + echo "Failed to create veth TX interface. Is CONFIG_VETH set?" >&2 282 + exit "${ksft_skip}" 283 + fi 284 + set +e 285 + # This will print RTNETLINK answers: Device or resource busy 286 + ip link set "${VETH0}" master "${BOND_TX_MAIN_IF}" 2> /dev/null 287 + ret=$? 288 + set -e 289 + if [[ $ret -eq 0 ]] 290 + then 291 + echo "test failed: veth interface could not be enslaved" 292 + exit "${ksft_fail}" 293 + fi 294 + } 295 + 296 + # Given that netconsole picks the current net namespace, we need to enable it 297 + # from inside the TXNS namespace 298 + function enable_netcons_ns() { 299 + ip netns exec "${TXNS}" sh -c \ 300 + "mount -t configfs configfs /sys/kernel/config && echo 1 > $NETCONS_PATH/enabled" 301 + } 302 + 303 + #################### 304 + # Tests start here # 305 + #################### 306 + 307 + # Create regular interfaces using netdevsim and link them 308 + create_all_ifaces 309 + 310 + # Setup the bonding interfaces 311 + # BOND_RX_MAIN_IF has BOND_RX{1,2}_SLAVE_IF 312 + # BOND_TX_MAIN_IF has BOND_TX{1,2}_SLAVE_IF 313 + setup_bonding_ifaces 314 + 315 + # Configure the ips as BOND_RX1_SLAVE_IF and BOND_TX1_SLAVE_IF 316 + configure_ifaces_ips "${IP_VERSION}" 317 + 318 + _create_dynamic_target "${FORMAT}" "${NETCONS_PATH}" 319 + enable_netcons_ns 320 + set_user_data 321 + 322 + # Test #1 : Create an bonding interface and attach netpoll into 323 + # the bonding interface. Netconsole/netpoll should work on 324 + # the bonding interface. 325 + test_send_netcons_msg_through_bond_iface 326 + echo "test #1: netpoll on bonding interface worked. Test passed" >&2 327 + 328 + # Test #2: Attach netpoll to an enslaved interface 329 + # Try to attach netpoll to an enslaved sub-interface (while still being part of 330 + # a bonding interface), which shouldn't be allowed 331 + test_enable_netpoll_on_enslaved_iface 332 + echo "test #2: netpoll correctly rejected enslaved interface (expected behavior). Test passed." >&2 333 + 334 + # Test #3: Unplug the sub-interface from bond and enable netconsole 335 + # Detach the interface from a bonding interface and attach netpoll again 336 + test_delete_bond_and_reenable_target 337 + echo "test #3: Able to attach to an unbound interface. Test passed." >&2 338 + 339 + # Test #4: Enslave a sub-interface that had netconsole enabled 340 + # Try to enslave an interface that has netconsole/netpoll enabled. 341 + # Previous test has netconsole enabled in BOND_TX1_SLAVE_IF, try to enslave it 342 + test_enslave_netcons_enabled_iface 343 + echo "test #4: Enslaving an interface with netpoll attached. Test passed." >&2 344 + 345 + # Test #5: Enslave a sub-interface to a bonding interface 346 + # Enslave an interface to a bond interface that has netpoll attached 347 + # At this stage, BOND_TX_MAIN_IF is created and BOND_TX1_SLAVE_IF is part of 348 + # it. Netconsole is currently disabled 349 + test_enslave_iface_to_bond 350 + echo "test #5: Enslaving an interface to bond+netpoll. Test passed." >&2 351 + 352 + # Test #6: Enslave a IFF_DISABLE_NETPOLL sub-interface to a bonding interface 353 + # At this stage, BOND_TX_MAIN_IF has both sub interface and netconsole is 354 + # enabled. This test will try to enslave an a veth (IFF_DISABLE_NETPOLL) interface 355 + # and it should fail, with netpoll: veth0 doesn't support polling 356 + test_enslave_iff_disabled_netpoll_iface 357 + echo "test #6: Enslaving IFF_DISABLE_NETPOLL ifaces to bond iface is not supported. Test passed." >&2 358 + 359 + cleanup_bond 360 + trap - EXIT 361 + exit "${EXIT_STATUS}"
+47 -7
tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
··· 11 11 LIBDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")") 12 12 13 13 SRCIF="" # to be populated later 14 + SRCIP="" # to be populated later 14 15 SRCIP4="192.0.2.1" 15 16 SRCIP6="fc00::1" 16 17 DSTIF="" # to be populated later 18 + DSTIP="" # to be populated later 17 19 DSTIP4="192.0.2.2" 18 20 DSTIP6="fc00::2" 19 21 ··· 30 28 # NAMESPACE will be populated by setup_ns with a random value 31 29 NAMESPACE="" 32 30 33 - # IDs for netdevsim 31 + # IDs for netdevsim. We either use NSIM_DEV_{1,2}_ID for standard test 32 + # or NSIM_BOND_{T,R}X_{1,2} for the bonding tests. Not both at the 33 + # same time. 34 34 NSIM_DEV_1_ID=$((256 + RANDOM % 256)) 35 35 NSIM_DEV_2_ID=$((512 + RANDOM % 256)) 36 + NSIM_BOND_TX_1=$((768 + RANDOM % 256)) 37 + NSIM_BOND_TX_2=$((1024 + RANDOM % 256)) 38 + NSIM_BOND_RX_1=$((1280 + RANDOM % 256)) 39 + NSIM_BOND_RX_2=$((1536 + RANDOM % 256)) 36 40 NSIM_DEV_SYS_NEW="/sys/bus/netdevsim/new_device" 41 + NSIM_DEV_SYS_LINK="/sys/bus/netdevsim/link_device" 37 42 38 43 # Used to create and delete namespaces 39 44 source "${LIBDIR}"/../../../../net/lib.sh 40 45 41 46 # Create netdevsim interfaces 42 47 create_ifaces() { 43 - 44 48 echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_NEW" 45 49 echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_NEW" 46 50 udevadm settle 2> /dev/null || true ··· 145 137 then 146 138 echo 1 > "${NCPATH}"/extended 147 139 fi 148 - 149 - echo 1 > "${NCPATH}"/enabled 150 - 151 140 } 152 141 153 142 function create_dynamic_target() { 154 143 local FORMAT=${1:-"extended"} 155 144 local NCPATH=${2:-"$NETCONS_PATH"} 156 145 _create_dynamic_target "${FORMAT}" "${NCPATH}" 146 + 147 + echo 1 > "${NCPATH}"/enabled 157 148 158 149 # This will make sure that the kernel was able to 159 150 # load the netconsole driver configuration. The console message ··· 200 193 echo "${DEFAULT_PRINTK_VALUES}" > /proc/sys/kernel/printk 201 194 } 202 195 203 - function cleanup() { 196 + function cleanup_netcons() { 204 197 # delete netconsole dynamic reconfiguration 205 - echo 0 > "${NETCONS_PATH}"/enabled 198 + # do not fail if the target is already disabled 199 + if [[ ! -d "${NETCONS_PATH}" ]] 200 + then 201 + # in some cases this is called before netcons path is created 202 + return 203 + fi 204 + if [[ $(cat "${NETCONS_PATH}"/enabled) != 0 ]] 205 + then 206 + echo 0 > "${NETCONS_PATH}"/enabled || true 207 + fi 206 208 # Remove all the keys that got created during the selftest 207 209 find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete 208 210 # Remove the configfs entry 209 211 rmdir "${NETCONS_PATH}" 212 + } 210 213 214 + function cleanup() { 215 + cleanup_netcons 211 216 do_cleanup 212 217 } 213 218 ··· 395 376 # otherwise the packet could be missed, and the test will fail. Happens 396 377 # more frequently on IPv6 397 378 sleep 1 379 + } 380 + 381 + # Clean up netdevsim ifaces created for bonding test 382 + function cleanup_bond_nsim() { 383 + ip -n "${TXNS}" \ 384 + link delete "${BOND_TX_MAIN_IF}" type bond || true 385 + ip -n "${RXNS}" \ 386 + link delete "${BOND_RX_MAIN_IF}" type bond || true 387 + 388 + cleanup_netdevsim "$NSIM_BOND_TX_1" 389 + cleanup_netdevsim "$NSIM_BOND_TX_2" 390 + cleanup_netdevsim "$NSIM_BOND_RX_1" 391 + cleanup_netdevsim "$NSIM_BOND_RX_2" 392 + } 393 + 394 + # cleanup tests that use bonding interfaces 395 + function cleanup_bond() { 396 + cleanup_netcons 397 + cleanup_bond_nsim 398 + cleanup_all_ns 399 + ip link delete "${VETH0}" || true 398 400 }