Commit 6701896e authored by Breno Leitao's avatar Breno Leitao Committed by Jakub Kicinski
Browse files

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: default avatarBreno Leitao <leitao@debian.org>
Reviewed-by: default avatarAndre Carvalho <asantostc@gmail.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20251107-netconsole_torture-v10-3-749227b55f63@debian.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 39acc6a9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ TEST_PROGS := \
	netcons_fragmented_msg.sh \
	netcons_overflow.sh \
	netcons_sysdata.sh \
	netcons_torture.sh \
	netpoll_basic.py \
	ping.py \
	psp.py \
+130 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0

# Repeatedly send kernel messages, toggles netconsole targets on and off,
# creates and deletes targets in parallel, and toggles the source interface to
# simulate stress conditions.
#
# This test aims to verify the robustness of netconsole under dynamic
# configurations and concurrent operations.
#
# The major goal is to run this test with LOCKDEP, Kmemleak and KASAN to make
# sure no issues is reported.
#
# Author: Breno Leitao <leitao@debian.org>

set -euo pipefail

SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")

source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh

# Number of times the main loop run
ITERATIONS=${1:-150}

# Only test extended format
FORMAT="extended"
# And ipv6 only
IP_VERSION="ipv6"

# Create, enable and delete some targets.
create_and_delete_random_target() {
	COUNT=2
	RND_PREFIX=$(mktemp -u netcons_rnd_XXXX_)

	if [ -d "${NETCONS_CONFIGFS}/${RND_PREFIX}${COUNT}"  ] || \
	   [ -d "${NETCONS_CONFIGFS}/${RND_PREFIX}0" ]; then
		echo "Function didn't finish yet, skipping it." >&2
		return
	fi

	# enable COUNT targets
	for i in $(seq ${COUNT})
	do
		RND_TARGET="${RND_PREFIX}"${i}
		RND_TARGET_PATH="${NETCONS_CONFIGFS}"/"${RND_TARGET}"

		# Basic population so the target can come up
		_create_dynamic_target "${FORMAT}" "${RND_TARGET_PATH}"
	done

	echo "netconsole selftest: ${COUNT} additional targets were created" > /dev/kmsg
	# disable them all
	for i in $(seq ${COUNT})
	do
		RND_TARGET="${RND_PREFIX}"${i}
		RND_TARGET_PATH="${NETCONS_CONFIGFS}"/"${RND_TARGET}"
		if [[ $(cat "${RND_TARGET_PATH}/enabled") -eq 1 ]]
		then
			echo 0 > "${RND_TARGET_PATH}"/enabled
		fi
		rmdir "${RND_TARGET_PATH}"
	done
}

# Disable and enable the target mid-air, while messages
# are being transmitted.
toggle_netcons_target() {
	for i in $(seq 2)
	do
		if [ ! -d "${NETCONS_PATH}" ]
		then
			break
		fi
		echo 0 > "${NETCONS_PATH}"/enabled 2> /dev/null || true
		# Try to enable a bit harder, given it might fail to enable
		# Write to `enabled` might fail depending on the lock, which is
		# highly contentious here
		for _ in $(seq 5)
		do
			echo 1 > "${NETCONS_PATH}"/enabled 2> /dev/null || true
		done
	done
}

toggle_iface(){
	ip link set "${SRCIF}" down
	ip link set "${SRCIF}" up
}

# Start here

modprobe netdevsim 2> /dev/null || true
modprobe netconsole 2> /dev/null || true

# Check for basic system dependency and exit if not found
check_for_dependencies
# Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5)
echo "6 5" > /proc/sys/kernel/printk
# Remove the namespace, interfaces and netconsole target on exit
trap cleanup EXIT
# Create one namespace and two interfaces
set_network "${IP_VERSION}"
# Create a dynamic target for netconsole
create_dynamic_target "${FORMAT}"

for i in $(seq "$ITERATIONS")
do
	for _ in $(seq 10)
	do
		echo "${MSG}: ${TARGET} ${i}" > /dev/kmsg
	done
	wait

	if (( i % 30 == 0 )); then
		toggle_netcons_target &
	fi

	if (( i % 50 == 0 )); then
		# create some targets, enable them, send msg and disable
		# all in a parallel thread
		create_and_delete_random_target &
	fi

	if (( i % 70 == 0 )); then
		toggle_iface &
	fi
done
wait

exit "${EXIT_STATUS}"