Thread (9 messages) flat view 9 messages, 2 authors, 2d ago
WARM2d

[PATCH net-next RFC 4/6] netconsole: tell the target when the rate limit drops messages

From: Breno Leitao <leitao@debian.org>
Date: 2026-08-18 10:30:04
Also in: linux-doc, linux-kselftest, lkml
Subsystem: netconsole, networking drivers, the rest · Maintainers: Breno Leitao, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Keep the number of messages dropped since the last report on the target
and send it to the receiver as soon as a message gets through again:

  netconsole: 45 messages dropped by rate limit

netconsole formats that record itself rather than calling printk(),
which would feed the console it is currently servicing. Nothing here has
a printk sequence number, so the extended header carries a zero.

The timestamp comes from local_clock(), the same clock printk stamps its
records with, but it is taken when the notice goes out rather than when
the message was logged. It can therefore read a few microseconds later
than the message it precedes.

The notice rides on the next message the bucket lets through, so a
target that goes quiet right after a burst of drops only reports them
once the host logs again, and a target with ratelimit_burst set to zero
never reports at all.

Signed-off-by: Breno Leitao <leitao@debian.org>
---
 drivers/net/netconsole.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 6d60a5188bf13..0af2e5b4335c0 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -50,6 +50,7 @@
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 #include <linux/ratelimit.h>
+#include <linux/sched/clock.h>
 
 MODULE_AUTHOR("Matt Mackall <mpm@selenic.com>");
 MODULE_DESCRIPTION("Console driver for network interfaces");
@@ -177,6 +178,7 @@ struct netcons_userdata {
  * @sysdata_fields:	Sysdata features enabled.
  * @msgcounter:	Message sent counter.
  * @ratelimit:	Opaque structure to ratelimit messages
+ * @pending_drops: Messages dropped since the last notice was sent.
  * @stats:	Packet send stats for the target. Used for debugging.
  * @state:	State of the target.
  *		Visible from userspace (read-write).
@@ -221,6 +223,7 @@ struct netconsole_target {
 	u32			sysdata_fields;
 	/* protected by target_list_lock */
 	u32			msgcounter;
+	u32			pending_drops;
 	struct ratelimit_state	ratelimit;
 #endif
 	struct netconsole_target_stats stats;
@@ -297,7 +300,20 @@ static bool netconsole_ratelimited(struct netconsole_target *nt)
 	if (oops_in_progress)
 		return false;
 
-	return !__ratelimit(&nt->ratelimit);
+	if (__ratelimit(&nt->ratelimit))
+		return false;
+
+	nt->pending_drops++;
+
+	return true;
+}
+
+static u32 netconsole_take_drops(struct netconsole_target *nt)
+{
+	u32 drops = nt->pending_drops;
+
+	nt->pending_drops = 0;
+	return drops;
 }
 
 #else	/* !CONFIG_NETCONSOLE_DYNAMIC */
@@ -345,6 +361,11 @@ static bool netconsole_ratelimited(struct netconsole_target *nt)
 	return false;
 }
 
+static u32 netconsole_take_drops(struct netconsole_target *nt)
+{
+	return 0;
+}
+
 #endif	/* CONFIG_NETCONSOLE_DYNAMIC */
 
 /* Check if the target was bound by mac address. */
@@ -2554,6 +2575,34 @@ static void send_msg_udp(struct netconsole_target *nt, const char *msg,
 	}
 }
 
+static void send_ratelimit_notice(struct netconsole_target *nt, bool extended)
+{
+	int len = 0;
+	u64 ts_usec;
+	u32 drops;
+
+	drops = netconsole_take_drops(nt);
+	if (!drops)
+		return;
+
+	if (extended) {
+		/* append the extended headers */
+		if (nt->release)
+			len = scnprintf(nt->buf, sizeof(nt->buf), "%s,",
+					init_utsname()->release);
+
+		ts_usec = div_u64(local_clock(), NSEC_PER_USEC);
+		len += scnprintf(nt->buf + len, sizeof(nt->buf) - len,
+				 "%u,0,%llu,-;", LOGLEVEL_WARNING, ts_usec);
+	}
+
+	len += scnprintf(nt->buf + len, sizeof(nt->buf) - len,
+			 "netconsole: %u messages dropped by rate limit\n",
+			 drops);
+
+	send_udp(nt, nt->buf, len);
+}
+
 /**
  * netconsole_write - Generic function to send a msg to all targets
  * @wctxt: nbcon write context
@@ -2583,6 +2632,8 @@ static void netconsole_write(struct nbcon_write_context *wctxt, bool extended)
 		if (!nbcon_enter_unsafe(wctxt))
 			return;
 
+		send_ratelimit_notice(nt, extended);
+
 		if (extended)
 			send_ext_msg_udp(nt, wctxt);
 		else
-- 
2.53.0-Meta
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help