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

selftest: netcons: create a torture test

Create a netconsole test that puts a lot of pressure on the netconsole
list manipulation. Do it by creating dynamic targets and deleting
targets while messages are being sent. Also put interface down while the
messages are being sent, as creating parallel targets.

The code launches three background jobs on distinct schedules:

* Toggle netcons target every 30 iterations
* create and delete random_target every 50 iterations
* toggle iface every 70 iterations

This creates multiple concurrency sources that interact with netconsole
states. This is good practice to simulate stress, and exercise netpoll
and netconsole locks.

This test already found an issue as reported in [1]

Link: https://lore.kernel.org/all/20250901-netpoll_memleak-v1-1-34a181977dfc@debian.org/ [1]
Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Andre Carvalho <asantostc@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20251107-netconsole_torture-v10-3-749227b55f63@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Breno Leitao and committed by
Jakub Kicinski
6701896e 39acc6a9

+131
+1
tools/testing/selftests/drivers/net/Makefile
··· 18 18 netcons_fragmented_msg.sh \ 19 19 netcons_overflow.sh \ 20 20 netcons_sysdata.sh \ 21 + netcons_torture.sh \ 21 22 netpoll_basic.py \ 22 23 ping.py \ 23 24 psp.py \
+130
tools/testing/selftests/drivers/net/netcons_torture.sh
··· 1 + #!/usr/bin/env bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + # Repeatedly send kernel messages, toggles netconsole targets on and off, 5 + # creates and deletes targets in parallel, and toggles the source interface to 6 + # simulate stress conditions. 7 + # 8 + # This test aims to verify the robustness of netconsole under dynamic 9 + # configurations and concurrent operations. 10 + # 11 + # The major goal is to run this test with LOCKDEP, Kmemleak and KASAN to make 12 + # sure no issues is reported. 13 + # 14 + # Author: Breno Leitao <leitao@debian.org> 15 + 16 + set -euo pipefail 17 + 18 + SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")") 19 + 20 + source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh 21 + 22 + # Number of times the main loop run 23 + ITERATIONS=${1:-150} 24 + 25 + # Only test extended format 26 + FORMAT="extended" 27 + # And ipv6 only 28 + IP_VERSION="ipv6" 29 + 30 + # Create, enable and delete some targets. 31 + create_and_delete_random_target() { 32 + COUNT=2 33 + RND_PREFIX=$(mktemp -u netcons_rnd_XXXX_) 34 + 35 + if [ -d "${NETCONS_CONFIGFS}/${RND_PREFIX}${COUNT}" ] || \ 36 + [ -d "${NETCONS_CONFIGFS}/${RND_PREFIX}0" ]; then 37 + echo "Function didn't finish yet, skipping it." >&2 38 + return 39 + fi 40 + 41 + # enable COUNT targets 42 + for i in $(seq ${COUNT}) 43 + do 44 + RND_TARGET="${RND_PREFIX}"${i} 45 + RND_TARGET_PATH="${NETCONS_CONFIGFS}"/"${RND_TARGET}" 46 + 47 + # Basic population so the target can come up 48 + _create_dynamic_target "${FORMAT}" "${RND_TARGET_PATH}" 49 + done 50 + 51 + echo "netconsole selftest: ${COUNT} additional targets were created" > /dev/kmsg 52 + # disable them all 53 + for i in $(seq ${COUNT}) 54 + do 55 + RND_TARGET="${RND_PREFIX}"${i} 56 + RND_TARGET_PATH="${NETCONS_CONFIGFS}"/"${RND_TARGET}" 57 + if [[ $(cat "${RND_TARGET_PATH}/enabled") -eq 1 ]] 58 + then 59 + echo 0 > "${RND_TARGET_PATH}"/enabled 60 + fi 61 + rmdir "${RND_TARGET_PATH}" 62 + done 63 + } 64 + 65 + # Disable and enable the target mid-air, while messages 66 + # are being transmitted. 67 + toggle_netcons_target() { 68 + for i in $(seq 2) 69 + do 70 + if [ ! -d "${NETCONS_PATH}" ] 71 + then 72 + break 73 + fi 74 + echo 0 > "${NETCONS_PATH}"/enabled 2> /dev/null || true 75 + # Try to enable a bit harder, given it might fail to enable 76 + # Write to `enabled` might fail depending on the lock, which is 77 + # highly contentious here 78 + for _ in $(seq 5) 79 + do 80 + echo 1 > "${NETCONS_PATH}"/enabled 2> /dev/null || true 81 + done 82 + done 83 + } 84 + 85 + toggle_iface(){ 86 + ip link set "${SRCIF}" down 87 + ip link set "${SRCIF}" up 88 + } 89 + 90 + # Start here 91 + 92 + modprobe netdevsim 2> /dev/null || true 93 + modprobe netconsole 2> /dev/null || true 94 + 95 + # Check for basic system dependency and exit if not found 96 + check_for_dependencies 97 + # Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5) 98 + echo "6 5" > /proc/sys/kernel/printk 99 + # Remove the namespace, interfaces and netconsole target on exit 100 + trap cleanup EXIT 101 + # Create one namespace and two interfaces 102 + set_network "${IP_VERSION}" 103 + # Create a dynamic target for netconsole 104 + create_dynamic_target "${FORMAT}" 105 + 106 + for i in $(seq "$ITERATIONS") 107 + do 108 + for _ in $(seq 10) 109 + do 110 + echo "${MSG}: ${TARGET} ${i}" > /dev/kmsg 111 + done 112 + wait 113 + 114 + if (( i % 30 == 0 )); then 115 + toggle_netcons_target & 116 + fi 117 + 118 + if (( i % 50 == 0 )); then 119 + # create some targets, enable them, send msg and disable 120 + # all in a parallel thread 121 + create_and_delete_random_target & 122 + fi 123 + 124 + if (( i % 70 == 0 )); then 125 + toggle_iface & 126 + fi 127 + done 128 + wait 129 + 130 + exit "${EXIT_STATUS}"