Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+128
+32
Documentation/networking/netconsole.rst
··· 340 340 cpu=42 # kernel-populated value 341 341 342 342 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 + 343 375 Extended console: 344 376 ================= 345 377
+66
drivers/net/netconsole.c
··· 113 113 SYSDATA_TASKNAME = BIT(1), 114 114 /* Kernel release/version as part of sysdata */ 115 115 SYSDATA_RELEASE = BIT(2), 116 + /* Include a per-target message ID as part of sysdata */ 117 + SYSDATA_MSGID = BIT(3), 116 118 }; 117 119 118 120 /** ··· 125 123 * @extradata_complete: Cached, formatted string of append 126 124 * @userdata_length: String length of usedata in extradata_complete. 127 125 * @sysdata_fields: Sysdata features enabled. 126 + * @msgcounter: Message sent counter. 128 127 * @stats: Packet send stats for the target. Used for debugging. 129 128 * @enabled: On / off knob to enable / disable target. 130 129 * Visible from userspace (read-write). ··· 156 153 size_t userdata_length; 157 154 /* bit-wise with sysdata_feature bits */ 158 155 u32 sysdata_fields; 156 + /* protected by target_list_lock */ 157 + u32 msgcounter; 159 158 #endif 160 159 struct netconsole_target_stats stats; 161 160 bool enabled; ··· 509 504 unregister_console(&netconsole); 510 505 } 511 506 507 + static ssize_t sysdata_msgid_enabled_show(struct config_item *item, 508 + char *buf) 509 + { 510 + struct netconsole_target *nt = to_target(item->ci_parent); 511 + bool msgid_enabled; 512 + 513 + mutex_lock(&dynamic_netconsole_mutex); 514 + msgid_enabled = !!(nt->sysdata_fields & SYSDATA_MSGID); 515 + mutex_unlock(&dynamic_netconsole_mutex); 516 + 517 + return sysfs_emit(buf, "%d\n", msgid_enabled); 518 + } 519 + 512 520 /* 513 521 * This one is special -- targets created through the configfs interface 514 522 * are not enabled (and the corresponding netpoll activated) by default. ··· 817 799 entries += 1; 818 800 if (nt->sysdata_fields & SYSDATA_RELEASE) 819 801 entries += 1; 802 + if (nt->sysdata_fields & SYSDATA_MSGID) 803 + entries += 1; 820 804 821 805 return entries; 822 806 } ··· 955 935 nt->extradata_complete[nt->userdata_length] = 0; 956 936 } 957 937 938 + static ssize_t sysdata_msgid_enabled_store(struct config_item *item, 939 + const char *buf, size_t count) 940 + { 941 + struct netconsole_target *nt = to_target(item->ci_parent); 942 + bool msgid_enabled, curr; 943 + ssize_t ret; 944 + 945 + ret = kstrtobool(buf, &msgid_enabled); 946 + if (ret) 947 + return ret; 948 + 949 + mutex_lock(&dynamic_netconsole_mutex); 950 + curr = !!(nt->sysdata_fields & SYSDATA_MSGID); 951 + if (msgid_enabled == curr) 952 + goto unlock_ok; 953 + 954 + if (msgid_enabled && 955 + count_extradata_entries(nt) >= MAX_EXTRADATA_ITEMS) { 956 + ret = -ENOSPC; 957 + goto unlock; 958 + } 959 + 960 + if (msgid_enabled) 961 + nt->sysdata_fields |= SYSDATA_MSGID; 962 + else 963 + disable_sysdata_feature(nt, SYSDATA_MSGID); 964 + 965 + unlock_ok: 966 + ret = strnlen(buf, count); 967 + unlock: 968 + mutex_unlock(&dynamic_netconsole_mutex); 969 + return ret; 970 + } 971 + 958 972 static ssize_t sysdata_release_enabled_store(struct config_item *item, 959 973 const char *buf, size_t count) 960 974 { ··· 1104 1050 CONFIGFS_ATTR(sysdata_, cpu_nr_enabled); 1105 1051 CONFIGFS_ATTR(sysdata_, taskname_enabled); 1106 1052 CONFIGFS_ATTR(sysdata_, release_enabled); 1053 + CONFIGFS_ATTR(sysdata_, msgid_enabled); 1107 1054 1108 1055 static struct configfs_attribute *userdatum_attrs[] = { 1109 1056 &userdatum_attr_value, ··· 1167 1112 &sysdata_attr_cpu_nr_enabled, 1168 1113 &sysdata_attr_taskname_enabled, 1169 1114 &sysdata_attr_release_enabled, 1115 + &sysdata_attr_msgid_enabled, 1170 1116 NULL, 1171 1117 }; 1172 1118 ··· 1365 1309 init_utsname()->release); 1366 1310 } 1367 1311 1312 + static int sysdata_append_msgid(struct netconsole_target *nt, int offset) 1313 + { 1314 + wrapping_assign_add(nt->msgcounter, 1); 1315 + return scnprintf(&nt->extradata_complete[offset], 1316 + MAX_EXTRADATA_ENTRY_LEN, " msgid=%u\n", 1317 + nt->msgcounter); 1318 + } 1319 + 1368 1320 /* 1369 1321 * prepare_extradata - append sysdata at extradata_complete in runtime 1370 1322 * @nt: target to send message to ··· 1395 1331 extradata_len += sysdata_append_taskname(nt, extradata_len); 1396 1332 if (nt->sysdata_fields & SYSDATA_RELEASE) 1397 1333 extradata_len += sysdata_append_release(nt, extradata_len); 1334 + if (nt->sysdata_fields & SYSDATA_MSGID) 1335 + extradata_len += sysdata_append_msgid(nt, extradata_len); 1398 1336 1399 1337 WARN_ON_ONCE(extradata_len > 1400 1338 MAX_EXTRADATA_ENTRY_LEN * MAX_EXTRADATA_ITEMS);
+30
tools/testing/selftests/drivers/net/netcons_sysdata.sh
··· 53 53 echo 1 > "${NETCONS_PATH}/userdata/release_enabled" 54 54 } 55 55 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 + 56 67 # Disable the sysdata cpu_nr feature 57 68 function unset_cpu_nr() { 58 69 echo 0 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" ··· 78 67 echo 0 > "${NETCONS_PATH}/userdata/release_enabled" 79 68 } 80 69 70 + function unset_msgid() { 71 + echo 0 > "${NETCONS_PATH}/userdata/msgid_enabled" 72 + } 73 + 81 74 # Test if MSG contains sysdata 82 75 function validate_sysdata() { 83 76 # OUTPUT_FILE will contain something like: ··· 89 74 # userdatakey=userdatavalue 90 75 # cpu=X 91 76 # taskname=<taskname> 77 + # msgid=<id> 92 78 93 79 # Echo is what this test uses to create the message. See runtest() 94 80 # function ··· 116 100 117 101 if ! grep -q "taskname=${SENDER}" "${OUTPUT_FILE}"; then 118 102 echo "FAIL: 'taskname=echo' not found in ${OUTPUT_FILE}" >&2 103 + cat "${OUTPUT_FILE}" >&2 104 + exit "${ksft_fail}" 105 + fi 106 + 107 + if ! grep -q "msgid=[0-9]\+$" "${OUTPUT_FILE}"; then 108 + echo "FAIL: 'msgid=<id>' not found in ${OUTPUT_FILE}" >&2 119 109 cat "${OUTPUT_FILE}" >&2 120 110 exit "${ksft_fail}" 121 111 fi ··· 177 155 exit "${ksft_fail}" 178 156 fi 179 157 158 + if grep -q "msgid=" "${OUTPUT_FILE}"; then 159 + echo "FAIL: 'msgid= found in ${OUTPUT_FILE}" >&2 160 + cat "${OUTPUT_FILE}" >&2 161 + exit "${ksft_fail}" 162 + fi 163 + 180 164 rm "${OUTPUT_FILE}" 181 165 } 182 166 ··· 234 206 # Enable taskname to be appended to sysdata 235 207 set_taskname 236 208 set_release 209 + set_msgid 237 210 runtest 238 211 # Make sure the message was received in the dst part 239 212 # and exit ··· 264 235 unset_cpu_nr 265 236 unset_taskname 266 237 unset_release 238 + unset_msgid 267 239 runtest 268 240 # At this time, cpu= shouldn't be present in the msg 269 241 validate_no_sysdata