1#!/usr/bin/env bash 2# SPDX-License-Identifier: GPL-2.0 3 4# A test that makes sure that sysdata runtime CPU data is properly set 5# when a message is sent. 6# 7# There are 3 different tests, every time sent using a random CPU. 8# - Test #1 9# * Only enable cpu_nr sysdata feature. 10# - Test #2 11# * Keep cpu_nr sysdata feature enable and enable userdata. 12# - Test #3 13# * keep userdata enabled, and disable sysdata cpu_nr feature. 14# 15# Author: Breno Leitao <leitao@debian.org> 16 17set -euo pipefail 18 19SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")") 20 21source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh 22 23# Enable the sysdata cpu_nr feature 24function set_cpu_nr() { 25 if [[ ! -f "${NETCONS_PATH}/userdata/cpu_nr_enabled" ]] 26 then 27 echo "Populate CPU configfs path not available in ${NETCONS_PATH}/userdata/cpu_nr_enabled" >&2 28 exit "${ksft_skip}" 29 fi 30 31 echo 1 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" 32} 33 34# Enable the taskname to be appended to sysdata 35function set_taskname() { 36 if [[ ! -f "${NETCONS_PATH}/userdata/taskname_enabled" ]] 37 then 38 echo "Not able to enable taskname sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/taskname_enabled" >&2 39 exit "${ksft_skip}" 40 fi 41 42 echo 1 > "${NETCONS_PATH}/userdata/taskname_enabled" 43} 44 45# Enable the release to be appended to sysdata 46function set_release() { 47 if [[ ! -f "${NETCONS_PATH}/userdata/release_enabled" ]] 48 then 49 echo "Not able to enable release sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/release_enabled" >&2 50 exit "${ksft_skip}" 51 fi 52 53 echo 1 > "${NETCONS_PATH}/userdata/release_enabled" 54} 55 56# Enable the msgid to be appended to sysdata 57function 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 67# Disable the sysdata cpu_nr feature 68function unset_cpu_nr() { 69 echo 0 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" 70} 71 72# Once called, taskname=<..> will not be appended anymore 73function unset_taskname() { 74 echo 0 > "${NETCONS_PATH}/userdata/taskname_enabled" 75} 76 77function unset_release() { 78 echo 0 > "${NETCONS_PATH}/userdata/release_enabled" 79} 80 81function unset_msgid() { 82 echo 0 > "${NETCONS_PATH}/userdata/msgid_enabled" 83} 84 85# Test if MSG contains sysdata 86function validate_sysdata() { 87 # OUTPUT_FILE will contain something like: 88 # 6.11.1-0_fbk0_rc13_509_g30d75cea12f7,13,1822,115075213798,-;netconsole selftest: netcons_gtJHM 89 # userdatakey=userdatavalue 90 # cpu=X 91 # taskname=<taskname> 92 # msgid=<id> 93 94 # Echo is what this test uses to create the message. See runtest() 95 # function 96 SENDER="echo" 97 98 if [ ! -f "$OUTPUT_FILE" ]; then 99 echo "FAIL: File was not generated." >&2 100 exit "${ksft_fail}" 101 fi 102 103 if ! grep -q "${MSG}" "${OUTPUT_FILE}"; then 104 echo "FAIL: ${MSG} not found in ${OUTPUT_FILE}" >&2 105 cat "${OUTPUT_FILE}" >&2 106 exit "${ksft_fail}" 107 fi 108 109 # Check if cpu=XX exists in the file and matches the one used 110 # in taskset(1) 111 if ! grep -q "cpu=${CPU}\+" "${OUTPUT_FILE}"; then 112 echo "FAIL: 'cpu=${CPU}' not found in ${OUTPUT_FILE}" >&2 113 cat "${OUTPUT_FILE}" >&2 114 exit "${ksft_fail}" 115 fi 116 117 if ! grep -q "taskname=${SENDER}" "${OUTPUT_FILE}"; then 118 echo "FAIL: 'taskname=echo' not found in ${OUTPUT_FILE}" >&2 119 cat "${OUTPUT_FILE}" >&2 120 exit "${ksft_fail}" 121 fi 122 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 129 rm "${OUTPUT_FILE}" 130 pkill_socat 131} 132 133function validate_release() { 134 RELEASE=$(uname -r) 135 136 if [ ! -f "$OUTPUT_FILE" ]; then 137 echo "FAIL: File was not generated." >&2 138 exit "${ksft_fail}" 139 fi 140 141 if ! grep -q "release=${RELEASE}" "${OUTPUT_FILE}"; then 142 echo "FAIL: 'release=${RELEASE}' not found in ${OUTPUT_FILE}" >&2 143 cat "${OUTPUT_FILE}" >&2 144 exit "${ksft_fail}" 145 fi 146} 147 148# Test if MSG content exists in OUTPUT_FILE but no `cpu=` and `taskname=` 149# strings 150function validate_no_sysdata() { 151 if [ ! -f "$OUTPUT_FILE" ]; then 152 echo "FAIL: File was not generated." >&2 153 exit "${ksft_fail}" 154 fi 155 156 if ! grep -q "${MSG}" "${OUTPUT_FILE}"; then 157 echo "FAIL: ${MSG} not found in ${OUTPUT_FILE}" >&2 158 cat "${OUTPUT_FILE}" >&2 159 exit "${ksft_fail}" 160 fi 161 162 if grep -q "cpu=" "${OUTPUT_FILE}"; then 163 echo "FAIL: 'cpu= found in ${OUTPUT_FILE}" >&2 164 cat "${OUTPUT_FILE}" >&2 165 exit "${ksft_fail}" 166 fi 167 168 if grep -q "taskname=" "${OUTPUT_FILE}"; then 169 echo "FAIL: 'taskname= found in ${OUTPUT_FILE}" >&2 170 cat "${OUTPUT_FILE}" >&2 171 exit "${ksft_fail}" 172 fi 173 174 if grep -q "release=" "${OUTPUT_FILE}"; then 175 echo "FAIL: 'release= found in ${OUTPUT_FILE}" >&2 176 cat "${OUTPUT_FILE}" >&2 177 exit "${ksft_fail}" 178 fi 179 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 186 rm "${OUTPUT_FILE}" 187} 188 189# Start socat, send the message and wait for the file to show up in the file 190# system 191function runtest { 192 # Listen for netconsole port inside the namespace and destination 193 # interface 194 listen_port_and_save_to "${OUTPUT_FILE}" & 195 # Wait for socat to start and listen to the port. 196 wait_local_port_listen "${NAMESPACE}" "${PORT}" udp 197 # Send the message 198 taskset -c "${CPU}" echo "${MSG}: ${TARGET}" > /dev/kmsg 199 # Wait until socat saves the file to disk 200 busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}" 201} 202 203# ========== # 204# Start here # 205# ========== # 206 207modprobe netdevsim 2> /dev/null || true 208modprobe netconsole 2> /dev/null || true 209 210# Check for basic system dependency and exit if not found 211check_for_dependencies 212# This test also depends on taskset(1). Check for it before starting the test 213check_for_taskset 214 215# Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5) 216echo "6 5" > /proc/sys/kernel/printk 217# Remove the namespace, interfaces and netconsole target on exit 218trap cleanup EXIT 219# Create one namespace and two interfaces 220set_network 221# Create a dynamic target for netconsole 222create_dynamic_target 223 224#==================================================== 225# TEST #1 226# Send message from a random CPU 227#==================================================== 228# Random CPU in the system 229CPU=$((RANDOM % $(nproc))) 230OUTPUT_FILE="/tmp/${TARGET}_1" 231MSG="Test #1 from CPU${CPU}" 232# Enable the auto population of cpu_nr 233set_cpu_nr 234# Enable taskname to be appended to sysdata 235set_taskname 236set_release 237set_msgid 238runtest 239# Make sure the message was received in the dst part 240# and exit 241validate_release 242validate_sysdata 243 244#==================================================== 245# TEST #2 246# This test now adds userdata together with sysdata 247# =================================================== 248# Get a new random CPU 249CPU=$((RANDOM % $(nproc))) 250OUTPUT_FILE="/tmp/${TARGET}_2" 251MSG="Test #2 from CPU${CPU}" 252set_user_data 253runtest 254validate_release 255validate_sysdata 256 257# =================================================== 258# TEST #3 259# Unset all sysdata, fail if any userdata is set 260# =================================================== 261CPU=$((RANDOM % $(nproc))) 262OUTPUT_FILE="/tmp/${TARGET}_3" 263MSG="Test #3 from CPU${CPU}" 264unset_cpu_nr 265unset_taskname 266unset_release 267unset_msgid 268runtest 269# At this time, cpu= shouldn't be present in the msg 270validate_no_sysdata 271 272exit "${ksft_pass}" 273