selftests: netconsole: validate target resume

Introduce a new netconsole selftest to validate that netconsole is able
to resume a deactivated target when the low level interface comes back.

The test setups the network using netdevsim, creates a netconsole target
and then remove/add netdevsim in order to bring the same interfaces
back. Afterwards, the test validates that the target works as expected.

Targets are created via cmdline parameters to the module to ensure that
we are able to resume targets that were bound by mac and interface name.

Reviewed-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Andre Carvalho <asantostc@gmail.com>
Tested-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260118-netcons-retrigger-v11-7-4de36aebcf48@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Andre Carvalho 2026-01-18 11:00:27 +00:00 committed by Jakub Kicinski
parent 220dbe3c76
commit 6ecc08329b
3 changed files with 155 additions and 5 deletions

View File

@ -19,6 +19,7 @@ TEST_PROGS := \
netcons_cmdline.sh \
netcons_fragmented_msg.sh \
netcons_overflow.sh \
netcons_resume.sh \
netcons_sysdata.sh \
netcons_torture.sh \
netpoll_basic.py \

View File

@ -203,19 +203,21 @@ function do_cleanup() {
function cleanup_netcons() {
# delete netconsole dynamic reconfiguration
# do not fail if the target is already disabled
if [[ ! -d "${NETCONS_PATH}" ]]
local TARGET_PATH=${1:-${NETCONS_PATH}}
if [[ ! -d "${TARGET_PATH}" ]]
then
# in some cases this is called before netcons path is created
return
fi
if [[ $(cat "${NETCONS_PATH}"/enabled) != 0 ]]
if [[ $(cat "${TARGET_PATH}"/enabled) != 0 ]]
then
echo 0 > "${NETCONS_PATH}"/enabled || true
echo 0 > "${TARGET_PATH}"/enabled || true
fi
# Remove all the keys that got created during the selftest
find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete
find "${TARGET_PATH}/userdata/" -mindepth 1 -type d -delete
# Remove the configfs entry
rmdir "${NETCONS_PATH}"
rmdir "${TARGET_PATH}"
}
function cleanup() {
@ -377,6 +379,29 @@ function check_netconsole_module() {
fi
}
function wait_target_state() {
local TARGET=${1}
local STATE=${2}
local TARGET_PATH="${NETCONS_CONFIGFS}"/"${TARGET}"
local ENABLED=0
if [ "${STATE}" == "enabled" ]
then
ENABLED=1
fi
if [ ! -d "$TARGET_PATH" ]; then
echo "FAIL: Target does not exist." >&2
exit "${ksft_fail}"
fi
local CHECK_CMD="grep \"$ENABLED\" \"$TARGET_PATH/enabled\""
slowwait 2 sh -c "test -n \"\$($CHECK_CMD)\"" || {
echo "FAIL: ${TARGET} is not ${STATE}." >&2
exit "${ksft_fail}"
}
}
# A wrapper to translate protocol version to udp version
function wait_for_port() {
local NAMESPACE=${1}

View File

@ -0,0 +1,124 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0
# This test validates that netconsole is able to resume a target that was
# deactivated when its interface was removed when the interface is brought
# back up.
#
# The test configures a netconsole target and then removes netdevsim module to
# cause the interface to disappear. Targets are configured via cmdline to ensure
# targets bound by interface name and mac address can be resumed.
# The test verifies that the target moved to disabled state before adding
# netdevsim and the interface back.
#
# Finally, the test verifies that the target is re-enabled automatically and
# the message is received on the destination interface.
#
# Author: Andre Carvalho <asantostc@gmail.com>
set -euo pipefail
SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh
SAVED_SRCMAC="" # to be populated later
SAVED_DSTMAC="" # to be populated later
modprobe netdevsim 2> /dev/null || true
rmmod netconsole 2> /dev/null || true
check_netconsole_module
function cleanup() {
cleanup_netcons "${NETCONS_CONFIGFS}/cmdline0"
do_cleanup
rmmod netconsole
}
function trigger_reactivation() {
# Add back low level module
modprobe netdevsim
# Recreate namespace and two interfaces
set_network
# Restore MACs
ip netns exec "${NAMESPACE}" ip link set "${DSTIF}" \
address "${SAVED_DSTMAC}"
if [ "${BINDMODE}" == "mac" ]; then
ip link set dev "${SRCIF}" down
ip link set dev "${SRCIF}" address "${SAVED_SRCMAC}"
# Rename device in order to trigger target resume, as initial
# when device was recreated it didn't have correct mac address.
ip link set dev "${SRCIF}" name "${TARGET}"
fi
}
function trigger_deactivation() {
# Start by storing mac addresses so we can be restored in reactivate
SAVED_DSTMAC=$(ip netns exec "${NAMESPACE}" \
cat /sys/class/net/"$DSTIF"/address)
SAVED_SRCMAC=$(mac_get "${SRCIF}")
# Remove low level module
rmmod netdevsim
}
trap cleanup EXIT
# Run the test twice, with different cmdline parameters
for BINDMODE in "ifname" "mac"
do
echo "Running with bind mode: ${BINDMODE}" >&2
# Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5)
echo "6 5" > /proc/sys/kernel/printk
# Create one namespace and two interfaces
set_network
# Create the command line for netconsole, with the configuration from
# the function above
CMDLINE=$(create_cmdline_str "${BINDMODE}")
# The content of kmsg will be save to the following file
OUTPUT_FILE="/tmp/${TARGET}-${BINDMODE}"
# Load the module, with the cmdline set
modprobe netconsole "${CMDLINE}"
# Expose cmdline target in configfs
mkdir "${NETCONS_CONFIGFS}/cmdline0"
# Target should be enabled
wait_target_state "cmdline0" "enabled"
# Trigger deactivation by unloading netdevsim module. Target should be
# disabled.
trigger_deactivation
wait_target_state "cmdline0" "disabled"
# Trigger reactivation by loading netdevsim, recreating the network and
# restoring mac addresses. Target should be re-enabled.
trigger_reactivation
wait_target_state "cmdline0" "enabled"
# Listen for netconsole port inside the namespace and destination
# interface
listen_port_and_save_to "${OUTPUT_FILE}" &
# Wait for socat to start and listen to the port.
wait_local_port_listen "${NAMESPACE}" "${PORT}" udp
# Send the message
echo "${MSG}: ${TARGET}" > /dev/kmsg
# Wait until socat saves the file to disk
busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}"
# Make sure the message was received in the dst part
# and exit
validate_msg "${OUTPUT_FILE}"
# kill socat in case it is still running
pkill_socat
# Cleanup & unload the module
cleanup
echo "${BINDMODE} : Test passed" >&2
done
trap - EXIT
exit "${EXIT_STATUS}"