[PATCH net-next v3 6/6] selftests: netconsole: validate target resume

Andre Carvalho posted 6 patches 3 months ago
There is a newer version of this series
[PATCH net-next v3 6/6] selftests: netconsole: validate target resume
Posted by Andre Carvalho 3 months ago
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.

Signed-off-by: Andre Carvalho <asantostc@gmail.com>
---
 tools/testing/selftests/drivers/net/Makefile       |  1 +
 .../selftests/drivers/net/lib/sh/lib_netcons.sh    | 30 ++++++-
 .../selftests/drivers/net/netcons_resume.sh        | 92 ++++++++++++++++++++++
 3 files changed, 120 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 68e0bb603a9d..fbd81bec66cd 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -17,6 +17,7 @@ TEST_PROGS := \
 	netcons_cmdline.sh \
 	netcons_fragmented_msg.sh \
 	netcons_overflow.sh \
+	netcons_resume.sh \
 	netcons_sysdata.sh \
 	netpoll_basic.py \
 	ping.py \
diff --git a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
index 8e1085e89647..88b4bdfa84cf 100644
--- a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
+++ b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
@@ -186,12 +186,13 @@ function do_cleanup() {
 }
 
 function cleanup() {
+	local TARGETPATH=${1:-${NETCONS_PATH}}
 	# delete netconsole dynamic reconfiguration
-	echo 0 > "${NETCONS_PATH}"/enabled
+	echo 0 > "${TARGETPATH}"/enabled
 	# Remove all the keys that got created during the selftest
-	find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete
+	find "${TARGETPATH}/userdata/" -mindepth 1 -type d -delete
 	# Remove the configfs entry
-	rmdir "${NETCONS_PATH}"
+	rmdir "${TARGETPATH}"
 
 	do_cleanup
 }
@@ -350,6 +351,29 @@ function check_netconsole_module() {
 	fi
 }
 
+function wait_target_state() {
+	local TARGET=${1}
+	local STATE=${2}
+	local FILE="${NETCONS_CONFIGFS}"/"${TARGET}"/"enabled"
+
+	if [ "${STATE}" == "enabled" ]
+	then
+		ENABLED=1
+	else
+		ENABLED=0
+	fi
+
+	if [ ! -f "$FILE" ]; then
+		echo "FAIL: Target does not exist." >&2
+		exit "${ksft_fail}"
+	fi
+
+	slowwait 2 sh -c "test -n \"\$(grep \"${ENABLED}\" \"${FILE}\")\"" || {
+		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}
diff --git a/tools/testing/selftests/drivers/net/netcons_resume.sh b/tools/testing/selftests/drivers/net/netcons_resume.sh
new file mode 100755
index 000000000000..404df7abef1b
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/netcons_resume.sh
@@ -0,0 +1,92 @@
+#!/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
+
+modprobe netdevsim 2> /dev/null || true
+rmmod netconsole 2> /dev/null || true
+
+check_netconsole_module
+
+# 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
+	trap do_cleanup EXIT
+
+	# 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"
+	trap 'cleanup "${NETCONS_CONFIGFS}"/cmdline0' EXIT
+
+	# Target should be enabled
+	wait_target_state "cmdline0" "enabled"
+
+	# Remove low level module
+	rmmod netdevsim
+	# Target should be disabled
+	wait_target_state "cmdline0" "disabled"
+
+	# Add back low level module
+	modprobe netdevsim
+	# Recreate namespace and two interfaces
+	set_network
+	# Target should be enabled again
+	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 "${NETCONS_CONFIGFS}/cmdline0"
+	rmmod netconsole
+	trap - EXIT
+
+	echo "${BINDMODE} : Test passed" >&2
+done
+
+exit "${ksft_pass}"

-- 
2.51.2
Re: [PATCH net-next v3 6/6] selftests: netconsole: validate target resume
Posted by Breno Leitao 2 months, 4 weeks ago
On Sun, Nov 09, 2025 at 11:05:56AM +0000, Andre Carvalho wrote:
> 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.
> 
> Signed-off-by: Andre Carvalho <asantostc@gmail.com>
> ---
>  tools/testing/selftests/drivers/net/Makefile       |  1 +
>  .../selftests/drivers/net/lib/sh/lib_netcons.sh    | 30 ++++++-
>  .../selftests/drivers/net/netcons_resume.sh        | 92 ++++++++++++++++++++++
>  3 files changed, 120 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
> index 68e0bb603a9d..fbd81bec66cd 100644
> --- a/tools/testing/selftests/drivers/net/Makefile
> +++ b/tools/testing/selftests/drivers/net/Makefile
> @@ -17,6 +17,7 @@ TEST_PROGS := \
>  	netcons_cmdline.sh \
>  	netcons_fragmented_msg.sh \
>  	netcons_overflow.sh \
> +	netcons_resume.sh \
>  	netcons_sysdata.sh \
>  	netpoll_basic.py \
>  	ping.py \
> diff --git a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
> index 8e1085e89647..88b4bdfa84cf 100644
> --- a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
> +++ b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
> @@ -186,12 +186,13 @@ function do_cleanup() {
>  }
>  
>  function cleanup() {
> +	local TARGETPATH=${1:-${NETCONS_PATH}}
>  	# delete netconsole dynamic reconfiguration
> -	echo 0 > "${NETCONS_PATH}"/enabled
> +	echo 0 > "${TARGETPATH}"/enabled
>  	# Remove all the keys that got created during the selftest
> -	find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete
> +	find "${TARGETPATH}/userdata/" -mindepth 1 -type d -delete
>  	# Remove the configfs entry
> -	rmdir "${NETCONS_PATH}"
> +	rmdir "${TARGETPATH}"
>  
>  	do_cleanup
>  }
> @@ -350,6 +351,29 @@ function check_netconsole_module() {
>  	fi
>  }
>  
> +function wait_target_state() {
> +	local TARGET=${1}
> +	local STATE=${2}
> +	local FILE="${NETCONS_CONFIGFS}"/"${TARGET}"/"enabled"

local TARGET_PATH="${NETCONS_CONFIGFS}"/"${TARGET}"

> +
> +	if [ "${STATE}" == "enabled" ]
> +	then
> +		ENABLED=1

Shouldn't they be local variables in here ?

> +	else
> +		ENABLED=0
> +	fi
> +
> +	if [ ! -f "$FILE" ]; then

	if [ ! -f "${TARGET_PATH}" ]; then

> +		echo "FAIL: Target does not exist." >&2
> +		exit "${ksft_fail}"
> +	fi
> +
> +	slowwait 2 sh -c "test -n \"\$(grep \"${ENABLED}\" \"${FILE}\")\"" || {

	slowwait 2 sh -c "test -n \"\$(grep \"${ENABLED}\" \"${TARGET_PATH}/enabled\")\"" || {

> +		echo "FAIL: ${TARGET} is not ${STATE}." >&2
> +	}
> +}
> +
>  # A wrapper to translate protocol version to udp version
>  function wait_for_port() {
>  	local NAMESPACE=${1}
> diff --git a/tools/testing/selftests/drivers/net/netcons_resume.sh b/tools/testing/selftests/drivers/net/netcons_resume.sh
> new file mode 100755
> index 000000000000..404df7abef1b
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/netcons_resume.sh
> @@ -0,0 +1,92 @@
> +#!/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.

Comment above is a bit harder to understand.

> +#
> +# 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
> +
> +modprobe netdevsim 2> /dev/null || true
> +rmmod netconsole 2> /dev/null || true
> +
> +check_netconsole_module
> +
> +# 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
> +	trap do_cleanup EXIT

can we keep these trap lines outside of the loop?

> +
> +	# 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"
> +	trap 'cleanup "${NETCONS_CONFIGFS}"/cmdline0' EXIT
> +
> +	# Target should be enabled
> +	wait_target_state "cmdline0" "enabled"
> +
> +	# Remove low level module
> +	rmmod netdevsim
> +	# Target should be disabled
> +	wait_target_state "cmdline0" "disabled"
> +
> +	# Add back low level module
> +	modprobe netdevsim
> +	# Recreate namespace and two interfaces
> +	set_network
> +	# Target should be enabled again
> +	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 "${NETCONS_CONFIGFS}/cmdline0"
> +	rmmod netconsole

Why do we need to remove netconsole module in here?

Thanks for this patch. This is solving a real issue we have right now.
--breno
Re: [PATCH net-next v3 6/6] selftests: netconsole: validate target resume
Posted by Andre Carvalho 2 months, 4 weeks ago
On Tue, Nov 11, 2025 at 02:27:53AM -0800, Breno Leitao wrote:
> > +
> > +	if [ "${STATE}" == "enabled" ]
> > +	then
> > +		ENABLED=1
> 
> Shouldn't they be local variables in here ?

Yes, good point.

> > +	else
> > +		ENABLED=0
> > +	fi
> > +
> > +	if [ ! -f "$FILE" ]; then
> 
> 	if [ ! -f "${TARGET_PATH}" ]; then
> 
> > +		echo "FAIL: Target does not exist." >&2
> > +		exit "${ksft_fail}"
> > +	fi
> > +
> > +	slowwait 2 sh -c "test -n \"\$(grep \"${ENABLED}\" \"${FILE}\")\"" || {
> 
> 	slowwait 2 sh -c "test -n \"\$(grep \"${ENABLED}\" \"${TARGET_PATH}/enabled\")\"" || {
> 

Ack.

> > +		echo "FAIL: ${TARGET} is not ${STATE}." >&2
> > +	}
> > +}
> > +
> >  # A wrapper to translate protocol version to udp version
> >  function wait_for_port() {
> >  	local NAMESPACE=${1}
> > diff --git a/tools/testing/selftests/drivers/net/netcons_resume.sh b/tools/testing/selftests/drivers/net/netcons_resume.sh
> > new file mode 100755
> > index 000000000000..404df7abef1b
> > --- /dev/null
> > +++ b/tools/testing/selftests/drivers/net/netcons_resume.sh
> > @@ -0,0 +1,92 @@
> > +#!/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.
> 
> Comment above is a bit harder to understand.
> 

Agreed. What do you think of: 

# This test validates that netconsole is able to resume a previously deactivated
# target once its interface is brought back up. 

> > +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
> > +	trap do_cleanup EXIT
> 
> can we keep these trap lines outside of the loop?
> 

Let me try to do that. I'm using different handlers depending on how far we are on
the test but instead I think I should be able to use a similar approach as you did
with cleanup_netcons() in https://lore.kernel.org/netdev/20251107-netconsole_torture-v10-4-749227b55f63@debian.org/.

> > +	pkill_socat
> > +	# Cleanup & unload the module
> > +	cleanup "${NETCONS_CONFIGFS}/cmdline0"
> > +	rmmod netconsole
> 
> Why do we need to remove netconsole module in here?

We are removing the module here so we can load it on the second iteration of the
test with new cmdline. This is following a similar pattern to netcons_cmdline.sh.

> Thanks for this patch. This is solving a real issue we have right now.
> --breno

Thanks for the review!

-- 
Andre Carvalho