From: Breno Leitao <leitao@debian.org>
To: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Shuah Khan <shuah@kernel.org>
Cc: paulmck@kernel.org, davej@codemonkey.org.uk, riel@surriel.com,
gustavold@gmail.com, asantostc@gmail.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
samuelcrossley@gmail.com, Breno Leitao <leitao@debian.org>,
kernel-team@meta.com
Subject: [PATCH net-next RFC 6/6] selftests: netcons: test the per-target rate limit
Date: Tue, 18 Aug 2026 03:29:16 -0700 [thread overview]
Message-ID: <20260818-netcons_ratelimit-v1-6-8c5d2d17789c@debian.org> (raw)
In-Reply-To: <20260818-netcons_ratelimit-v1-0-8c5d2d17789c@debian.org>
Check that a new target starts unlimited and that a configured burst caps
what the target transmits. Dropping the interval back to zero has to
restore unlimited delivery and report what was lost to the receiver.
Only an upper bound is checked on the number of messages received.
netconsole is best-effort UDP and unrelated kernel messages draw from the
same bucket, so what arrives is not an exact count, while the cap is.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
.../selftests/drivers/net/netconsole/Makefile | 1 +
.../drivers/net/netconsole/netcons_ratelimit.sh | 160 +++++++++++++++++++++
2 files changed, 161 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/netconsole/Makefile b/tools/testing/selftests/drivers/net/netconsole/Makefile
index f0674c0017fc4..04cce40f162e9 100644
--- a/tools/testing/selftests/drivers/net/netconsole/Makefile
+++ b/tools/testing/selftests/drivers/net/netconsole/Makefile
@@ -10,6 +10,7 @@ TEST_PROGS := \
netcons_cmdline.sh \
netcons_fragmented_msg.sh \
netcons_overflow.sh \
+ netcons_ratelimit.sh \
netcons_resume.sh \
netcons_sysdata.sh \
netcons_torture.sh \
diff --git a/tools/testing/selftests/drivers/net/netconsole/netcons_ratelimit.sh b/tools/testing/selftests/drivers/net/netconsole/netcons_ratelimit.sh
new file mode 100755
index 0000000000000..38dd1599fe57d
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/netconsole/netcons_ratelimit.sh
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0
+
+# This test exercises the per-target rate limit. It configures a small burst
+# over an interval long enough that the bucket is never refilled, sends many
+# more messages than the burst allows, and checks that the target stops
+# transmitting once the bucket is empty.
+#
+# Clearing the interval has to restore unlimited delivery and tell the
+# receiver how many messages it missed, which is verified last.
+#
+# Author: Breno Leitao <leitao@debian.org>
+
+set -euo pipefail
+
+SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
+
+source "${SCRIPTDIR}"/../lib/sh/lib_netcons.sh
+
+# Messages sent while the limit is in place, comfortably above BURST so that
+# the bucket is drained
+MSG_COUNT=50
+BURST=5
+# Long enough that the bucket is not refilled while the test runs
+INTERVAL_MS=60000
+# Default the target starts with, as documented in netconsole.rst
+DEFAULT_BURST=10
+# What the target sends once it can transmit again
+DROP_NOTICE="messages dropped by rate limit"
+
+# The content of kmsg will be saved to the following file
+OUTPUT_FILE="/tmp/${TARGET}"
+
+function count_msgs() {
+ local FILE="${1}"
+
+ if [ ! -f "${FILE}" ]
+ then
+ echo 0
+ return
+ fi
+
+ # grep exits 1 on no match, which is a valid result here
+ grep -c "${MSG}" "${FILE}" || true
+}
+
+function send_msgs() {
+ local COUNT="${1}"
+ local I
+
+ for I in $(seq "${COUNT}")
+ do
+ echo "${MSG}: ${TARGET} ${I}" > /dev/kmsg
+ done
+}
+
+# A freshly created target has to be unlimited, otherwise every existing
+# netconsole user would start dropping messages after an upgrade
+function check_defaults() {
+ local INTERVAL BURST_DEFAULT
+
+ INTERVAL=$(cat "${NETCONS_PATH}"/ratelimit_interval_ms)
+ BURST_DEFAULT=$(cat "${NETCONS_PATH}"/ratelimit_burst)
+
+ if [ "${INTERVAL}" -ne 0 ] ||
+ [ "${BURST_DEFAULT}" -ne "${DEFAULT_BURST}" ]
+ then
+ echo "FAIL: unexpected rate limit defaults:" \
+ "interval=${INTERVAL} burst=${BURST_DEFAULT}" >&2
+ exit "${ksft_fail}"
+ fi
+}
+
+function check_limited() {
+ local RECEIVED
+
+ RECEIVED=$(count_msgs "${OUTPUT_FILE}")
+
+ # Unrelated kernel messages share the bucket, so fewer than BURST of
+ # ours can get through, but never more
+ if [ "${RECEIVED}" -gt "${BURST}" ]
+ then
+ echo "FAIL: received ${RECEIVED} messages with ratelimit_burst=${BURST}" >&2
+ cat "${OUTPUT_FILE}" >&2
+ exit "${ksft_fail}"
+ fi
+}
+
+# The notice below travels ahead of the message that reopened the bucket, so
+# waiting for the file to appear is not enough
+function msg_received() {
+ grep -q "${MSG}" "${OUTPUT_FILE}" 2> /dev/null
+}
+
+# The messages lost above have to be reported to the receiver
+function check_drops_reported() {
+ if ! grep -q "${DROP_NOTICE}" "${OUTPUT_FILE}"
+ then
+ echo "FAIL: no rate limit notice in ${OUTPUT_FILE}" >&2
+ cat "${OUTPUT_FILE}" >&2
+ exit "${ksft_fail}"
+ fi
+}
+
+# ========== #
+# 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
+# Remove the namespace, interfaces and netconsole target on exit
+trap cleanup EXIT
+
+# 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 a dynamic target for netconsole
+create_dynamic_target
+
+check_defaults
+
+# Set the burst before the interval, so that no message escapes while the
+# target still carries the default burst
+echo "${BURST}" > "${NETCONS_PATH}"/ratelimit_burst
+echo "${INTERVAL_MS}" > "${NETCONS_PATH}"/ratelimit_interval_ms
+
+listen_port_and_save_to "${OUTPUT_FILE}" &
+wait_for_port "${NAMESPACE}" "${PORT}" "ipv4"
+send_msgs "${MSG_COUNT}"
+# This half of the test is about messages that never arrive, so there is
+# nothing to busywait on
+sleep 1
+pkill_socat
+check_limited
+rm -f "${OUTPUT_FILE}"
+
+# Dropping the interval back to zero has to make the target unlimited again
+echo 0 > "${NETCONS_PATH}"/ratelimit_interval_ms
+
+listen_port_and_save_to "${OUTPUT_FILE}" &
+wait_for_port "${NAMESPACE}" "${PORT}" "ipv4"
+send_msgs 1
+if ! busywait "${BUSYWAIT_TIMEOUT}" msg_received
+then
+ echo "FAIL: Timed out waiting (${BUSYWAIT_TIMEOUT} ms) for netconsole" \
+ "message in ${OUTPUT_FILE} after clearing the rate limit" >&2
+ exit "${ksft_fail}"
+fi
+validate_msg "${OUTPUT_FILE}"
+check_drops_reported
+pkill_socat
+rm -f "${OUTPUT_FILE}"
+
+trap - EXIT
+cleanup
+exit "${ksft_pass}"
--
2.53.0-Meta
prev parent reply other threads:[~2026-08-18 10:30 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 10:29 [PATCH net-next RFC 0/6] netconsole: Support messages ratelimit-ing Breno Leitao
2026-08-18 10:29 ` [PATCH net-next RFC 1/6] netconsole: add a per-target message rate limit Breno Leitao
2026-08-18 10:29 ` [PATCH net-next RFC 2/6] netconsole: allow configuring the rate limit interval through configfs Breno Leitao
2026-08-18 10:29 ` [PATCH net-next RFC 3/6] netconsole: allow configuring the rate limit burst " Breno Leitao
2026-08-18 10:29 ` [PATCH net-next RFC 4/6] netconsole: tell the target when the rate limit drops messages Breno Leitao
2026-08-20 20:49 ` Gustavo Luiz Duarte
2026-08-21 12:41 ` Breno Leitao
2026-08-18 10:29 ` [PATCH net-next RFC 5/6] docs: netconsole: document rate limit feature Breno Leitao
2026-08-18 10:29 ` Breno Leitao [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818-netcons_ratelimit-v1-6-8c5d2d17789c@debian.org \
--to=leitao@debian.org \
--cc=andrew+netdev@lunn.ch \
--cc=asantostc@gmail.com \
--cc=corbet@lwn.net \
--cc=davej@codemonkey.org.uk \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gustavold@gmail.com \
--cc=horms@kernel.org \
--cc=kernel-team@meta.com \
--cc=kuba@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=paulmck@kernel.org \
--cc=riel@surriel.com \
--cc=samuelcrossley@gmail.com \
--cc=shuah@kernel.org \
--cc=skhan@linuxfoundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox