Skip to content

Commit fc4842c

Browse files
committed
Merge branch 'netconsole-msgid' into main
Gustavo Luiz Duarte says: ==================== netconsole: Add support for msgid in sysdata This patch series introduces a new feature to netconsole which allows appending a message ID to the userdata dictionary. If the msgid feature is enabled, the message ID is built from a per-target 32 bit counter that is incremented and appended to every message sent to the target. Example:: echo 1 > "/sys/kernel/config/netconsole/cmdline0/userdata/msgid_enabled" echo "This is message #1" > /dev/kmsg echo "This is message #2" > /dev/kmsg 13,434,54928466,-;This is message #1 msgid=1 13,435,54934019,-;This is message #2 msgid=2 This feature can be used by the target to detect if messages were dropped or reordered before reaching the target. This allows system administrators to assess the reliability of their netconsole pipeline and detect loss of messages due to network contention or temporary unavailability. --- Changes in v3: - Add kdoc documentation for msgcounter. - Link to v2: https://lore.kernel.org/r/20250612-netconsole-msgid-v2-0-d4c1abc84bac@gmail.com Changes in v2: - Use wrapping_assign_add() to avoid warnings in UBSAN and friends. - Improve documentation to clarify wrapping and distinguish msgid from sequnum. - Rebase and fix conflict in prepare_extradata(). - Link to v1: https://lore.kernel.org/r/20250611-netconsole-msgid-v1-0-1784a51feb1e@gmail.com ==================== Suggested-by: Breno Leitao <leitao@debian.org> Signed-off-by: Gustavo Luiz Duarte <gustavold@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents ec31583 + 8c587aa commit fc4842c

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

Documentation/networking/netconsole.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,38 @@ In this example, the message was sent by CPU 42.
340340
cpu=42 # kernel-populated value
341341

342342

343+
Message ID auto population in userdata
344+
--------------------------------------
345+
346+
Within the netconsole configfs hierarchy, there is a file named `msgid_enabled`
347+
located in the `userdata` directory. This file controls the message ID
348+
auto-population feature, which assigns a numeric id to each message sent to a
349+
given target and appends the ID to userdata dictionary in every message sent.
350+
351+
The message ID is generated using a per-target 32 bit counter that is
352+
incremented for every message sent to the target. Note that this counter will
353+
eventually wrap around after reaching uint32_t max value, so the message ID is
354+
not globally unique over time. However, it can still be used by the target to
355+
detect if messages were dropped before reaching the target by identifying gaps
356+
in the sequence of IDs.
357+
358+
It is important to distinguish message IDs from the message <sequnum> field.
359+
Some kernel messages may never reach netconsole (for example, due to printk
360+
rate limiting). Thus, a gap in <sequnum> cannot be solely relied upon to
361+
indicate that a message was dropped during transmission, as it may never have
362+
been sent via netconsole. The message ID, on the other hand, is only assigned
363+
to messages that are actually transmitted via netconsole.
364+
365+
Example::
366+
367+
echo "This is message #1" > /dev/kmsg
368+
echo "This is message #2" > /dev/kmsg
369+
13,434,54928466,-;This is message #1
370+
msgid=1
371+
13,435,54934019,-;This is message #2
372+
msgid=2
373+
374+
343375
Extended console:
344376
=================
345377

drivers/net/netconsole.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ enum sysdata_feature {
113113
SYSDATA_TASKNAME = BIT(1),
114114
/* Kernel release/version as part of sysdata */
115115
SYSDATA_RELEASE = BIT(2),
116+
/* Include a per-target message ID as part of sysdata */
117+
SYSDATA_MSGID = BIT(3),
116118
};
117119

118120
/**
@@ -123,6 +125,7 @@ enum sysdata_feature {
123125
* @extradata_complete: Cached, formatted string of append
124126
* @userdata_length: String length of usedata in extradata_complete.
125127
* @sysdata_fields: Sysdata features enabled.
128+
* @msgcounter: Message sent counter.
126129
* @stats: Packet send stats for the target. Used for debugging.
127130
* @enabled: On / off knob to enable / disable target.
128131
* Visible from userspace (read-write).
@@ -153,6 +156,8 @@ struct netconsole_target {
153156
size_t userdata_length;
154157
/* bit-wise with sysdata_feature bits */
155158
u32 sysdata_fields;
159+
/* protected by target_list_lock */
160+
u32 msgcounter;
156161
#endif
157162
struct netconsole_target_stats stats;
158163
bool enabled;
@@ -504,6 +509,19 @@ static void unregister_netcons_consoles(void)
504509
unregister_console(&netconsole);
505510
}
506511

512+
static ssize_t sysdata_msgid_enabled_show(struct config_item *item,
513+
char *buf)
514+
{
515+
struct netconsole_target *nt = to_target(item->ci_parent);
516+
bool msgid_enabled;
517+
518+
mutex_lock(&dynamic_netconsole_mutex);
519+
msgid_enabled = !!(nt->sysdata_fields & SYSDATA_MSGID);
520+
mutex_unlock(&dynamic_netconsole_mutex);
521+
522+
return sysfs_emit(buf, "%d\n", msgid_enabled);
523+
}
524+
507525
/*
508526
* This one is special -- targets created through the configfs interface
509527
* are not enabled (and the corresponding netpoll activated) by default.
@@ -799,6 +817,8 @@ static size_t count_extradata_entries(struct netconsole_target *nt)
799817
entries += 1;
800818
if (nt->sysdata_fields & SYSDATA_RELEASE)
801819
entries += 1;
820+
if (nt->sysdata_fields & SYSDATA_MSGID)
821+
entries += 1;
802822

803823
return entries;
804824
}
@@ -935,6 +955,40 @@ static void disable_sysdata_feature(struct netconsole_target *nt,
935955
nt->extradata_complete[nt->userdata_length] = 0;
936956
}
937957

958+
static ssize_t sysdata_msgid_enabled_store(struct config_item *item,
959+
const char *buf, size_t count)
960+
{
961+
struct netconsole_target *nt = to_target(item->ci_parent);
962+
bool msgid_enabled, curr;
963+
ssize_t ret;
964+
965+
ret = kstrtobool(buf, &msgid_enabled);
966+
if (ret)
967+
return ret;
968+
969+
mutex_lock(&dynamic_netconsole_mutex);
970+
curr = !!(nt->sysdata_fields & SYSDATA_MSGID);
971+
if (msgid_enabled == curr)
972+
goto unlock_ok;
973+
974+
if (msgid_enabled &&
975+
count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) {
976+
ret = -ENOSPC;
977+
goto unlock;
978+
}
979+
980+
if (msgid_enabled)
981+
nt->sysdata_fields |= SYSDATA_MSGID;
982+
else
983+
disable_sysdata_feature(nt, SYSDATA_MSGID);
984+
985+
unlock_ok:
986+
ret = strnlen(buf, count);
987+
unlock:
988+
mutex_unlock(&dynamic_netconsole_mutex);
989+
return ret;
990+
}
991+
938992
static ssize_t sysdata_release_enabled_store(struct config_item *item,
939993
const char *buf, size_t count)
940994
{
@@ -1050,6 +1104,7 @@ CONFIGFS_ATTR(userdatum_, value);
10501104
CONFIGFS_ATTR(sysdata_, cpu_nr_enabled);
10511105
CONFIGFS_ATTR(sysdata_, taskname_enabled);
10521106
CONFIGFS_ATTR(sysdata_, release_enabled);
1107+
CONFIGFS_ATTR(sysdata_, msgid_enabled);
10531108

10541109
static struct configfs_attribute *userdatum_attrs[] = {
10551110
&userdatum_attr_value,
@@ -1112,6 +1167,7 @@ static struct configfs_attribute *userdata_attrs[] = {
11121167
&sysdata_attr_cpu_nr_enabled,
11131168
&sysdata_attr_taskname_enabled,
11141169
&sysdata_attr_release_enabled,
1170+
&sysdata_attr_msgid_enabled,
11151171
NULL,
11161172
};
11171173

@@ -1309,6 +1365,14 @@ static int sysdata_append_release(struct netconsole_target *nt, int offset)
13091365
init_utsname()->release);
13101366
}
13111367

1368+
static int sysdata_append_msgid(struct netconsole_target *nt, int offset)
1369+
{
1370+
wrapping_assign_add(nt->msgcounter, 1);
1371+
return scnprintf(&nt->extradata_complete[offset],
1372+
MAX_EXTRADATA_ENTRY_LEN, " msgid=%u\n",
1373+
nt->msgcounter);
1374+
}
1375+
13121376
/*
13131377
* prepare_extradata - append sysdata at extradata_complete in runtime
13141378
* @nt: target to send message to
@@ -1331,6 +1395,8 @@ static int prepare_extradata(struct netconsole_target *nt)
13311395
extradata_len += sysdata_append_taskname(nt, extradata_len);
13321396
if (nt->sysdata_fields & SYSDATA_RELEASE)
13331397
extradata_len += sysdata_append_release(nt, extradata_len);
1398+
if (nt->sysdata_fields & SYSDATA_MSGID)
1399+
extradata_len += sysdata_append_msgid(nt, extradata_len);
13341400

13351401
WARN_ON_ONCE(extradata_len >
13361402
MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS);

tools/testing/selftests/drivers/net/netcons_sysdata.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ function set_release() {
5353
echo 1 > "${NETCONS_PATH}/userdata/release_enabled"
5454
}
5555

56+
# Enable the msgid to be appended to sysdata
57+
function set_msgid() {
58+
if [[ ! -f "${NETCONS_PATH}/userdata/msgid_enabled" ]]
59+
then
60+
echo "Not able to enable msgid sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/msgid_enabled" >&2
61+
exit "${ksft_skip}"
62+
fi
63+
64+
echo 1 > "${NETCONS_PATH}/userdata/msgid_enabled"
65+
}
66+
5667
# Disable the sysdata cpu_nr feature
5768
function unset_cpu_nr() {
5869
echo 0 > "${NETCONS_PATH}/userdata/cpu_nr_enabled"
@@ -67,13 +78,18 @@ function unset_release() {
6778
echo 0 > "${NETCONS_PATH}/userdata/release_enabled"
6879
}
6980

81+
function unset_msgid() {
82+
echo 0 > "${NETCONS_PATH}/userdata/msgid_enabled"
83+
}
84+
7085
# Test if MSG contains sysdata
7186
function validate_sysdata() {
7287
# OUTPUT_FILE will contain something like:
7388
# 6.11.1-0_fbk0_rc13_509_g30d75cea12f7,13,1822,115075213798,-;netconsole selftest: netcons_gtJHM
7489
# userdatakey=userdatavalue
7590
# cpu=X
7691
# taskname=<taskname>
92+
# msgid=<id>
7793

7894
# Echo is what this test uses to create the message. See runtest()
7995
# function
@@ -104,6 +120,12 @@ function validate_sysdata() {
104120
exit "${ksft_fail}"
105121
fi
106122

123+
if ! grep -q "msgid=[0-9]\+$" "${OUTPUT_FILE}"; then
124+
echo "FAIL: 'msgid=<id>' not found in ${OUTPUT_FILE}" >&2
125+
cat "${OUTPUT_FILE}" >&2
126+
exit "${ksft_fail}"
127+
fi
128+
107129
rm "${OUTPUT_FILE}"
108130
pkill_socat
109131
}
@@ -155,6 +177,12 @@ function validate_no_sysdata() {
155177
exit "${ksft_fail}"
156178
fi
157179

180+
if grep -q "msgid=" "${OUTPUT_FILE}"; then
181+
echo "FAIL: 'msgid= found in ${OUTPUT_FILE}" >&2
182+
cat "${OUTPUT_FILE}" >&2
183+
exit "${ksft_fail}"
184+
fi
185+
158186
rm "${OUTPUT_FILE}"
159187
}
160188

@@ -206,6 +234,7 @@ set_cpu_nr
206234
# Enable taskname to be appended to sysdata
207235
set_taskname
208236
set_release
237+
set_msgid
209238
runtest
210239
# Make sure the message was received in the dst part
211240
# and exit
@@ -235,6 +264,7 @@ MSG="Test #3 from CPU${CPU}"
235264
unset_cpu_nr
236265
unset_taskname
237266
unset_release
267+
unset_msgid
238268
runtest
239269
# At this time, cpu= shouldn't be present in the msg
240270
validate_no_sysdata

0 commit comments

Comments
 (0)