1#!/usr/bin/env bash 2# SPDX-License-Identifier: GPL-2.0 3 4# Test netconsole's message fragmentation functionality. 5# 6# When a message exceeds the maximum packet size, netconsole splits it into 7# multiple fragments for transmission. This test verifies: 8# - Correct fragmentation of large messages 9# - Proper reassembly of fragments at the receiver 10# - Preservation of userdata across fragments 11# - Behavior with and without kernel release version appending 12# 13# Author: Breno Leitao <leitao@debian.org> 14 15set -euo pipefail 16 17SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")") 18 19source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh 20 21modprobe netdevsim 2> /dev/null || true 22modprobe netconsole 2> /dev/null || true 23 24# The content of kmsg will be save to the following file 25OUTPUT_FILE="/tmp/${TARGET}" 26 27# set userdata to a long value. In this case, it is "1-2-3-4...50-" 28USERDATA_VALUE=$(printf -- '%.2s-' {1..60}) 29 30# Convert the header string in a regexp, so, we can remove 31# the second header as well. 32# A header looks like "13,468,514729715,-,ncfrag=0/1135;". If 33# release is appended, you might find something like:L 34# "6.13.0-04048-g4f561a87745a,13,468,514729715,-,ncfrag=0/1135;" 35function header_to_regex() { 36 # header is everything before ; 37 local HEADER="${1}" 38 REGEX=$(echo "${HEADER}" | cut -d'=' -f1) 39 echo "${REGEX}=[0-9]*\/[0-9]*;" 40} 41 42# We have two headers in the message. Remove both to get the full message, 43# and extract the full message. 44function extract_msg() { 45 local MSGFILE="${1}" 46 # Extract the header, which is the very first thing that arrives in the 47 # first list. 48 HEADER=$(sed -n '1p' "${MSGFILE}" | cut -d';' -f1) 49 HEADER_REGEX=$(header_to_regex "${HEADER}") 50 51 # Remove the two headers from the received message 52 # This will return the message without any header, similarly to what 53 # was sent. 54 sed "s/""${HEADER_REGEX}""//g" "${MSGFILE}" 55} 56 57# Validate the message, which has two messages glued together. 58# unwrap them to make sure all the characters were transmitted. 59# File will look like the following: 60# 13,468,514729715,-,ncfrag=0/1135;<message> 61# key=<part of key>-13,468,514729715,-,ncfrag=967/1135;<rest of the key> 62function validate_fragmented_result() { 63 # Discard the netconsole headers, and assemble the full message 64 RCVMSG=$(extract_msg "${1}") 65 66 # check for the main message 67 if ! echo "${RCVMSG}" | grep -q "${MSG}"; then 68 echo "Message body doesn't match." >&2 69 echo "msg received=" "${RCVMSG}" >&2 70 exit "${ksft_fail}" 71 fi 72 73 # check userdata 74 if ! echo "${RCVMSG}" | grep -q "${USERDATA_VALUE}"; then 75 echo "message userdata doesn't match" >&2 76 echo "msg received=" "${RCVMSG}" >&2 77 exit "${ksft_fail}" 78 fi 79 # test passed. hooray 80} 81 82# Check for basic system dependency and exit if not found 83check_for_dependencies 84# Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5) 85echo "6 5" > /proc/sys/kernel/printk 86# Remove the namespace, interfaces and netconsole target on exit 87trap cleanup EXIT 88# Create one namespace and two interfaces 89set_network 90# Create a dynamic target for netconsole 91create_dynamic_target 92# Set userdata "key" with the "value" value 93set_user_data 94 95 96# TEST 1: Send message and userdata. They will fragment 97# ======= 98MSG=$(printf -- 'MSG%.3s=' {1..150}) 99 100# Listen for netconsole port inside the namespace and destination interface 101listen_port_and_save_to "${OUTPUT_FILE}" & 102# Wait for socat to start and listen to the port. 103wait_local_port_listen "${NAMESPACE}" "${PORT}" udp 104# Send the message 105echo "${MSG}: ${TARGET}" > /dev/kmsg 106# Wait until socat saves the file to disk 107busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}" 108# Check if the message was not corrupted 109validate_fragmented_result "${OUTPUT_FILE}" 110 111# TEST 2: Test with smaller message, and without release appended 112# ======= 113MSG=$(printf -- 'FOOBAR%.3s=' {1..100}) 114# Let's disable release and test again. 115disable_release_append 116 117listen_port_and_save_to "${OUTPUT_FILE}" & 118wait_local_port_listen "${NAMESPACE}" "${PORT}" udp 119echo "${MSG}: ${TARGET}" > /dev/kmsg 120busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}" 121validate_fragmented_result "${OUTPUT_FILE}" 122exit "${ksft_pass}" 123