| #!/usr/bin/env bash | |
| # SPDX-License-Identifier: GPL-2.0 | |
| # A test that makes sure that sysdata runtime CPU data is properly set | |
| # when a message is sent. | |
| # | |
| # There are 3 different tests, every time sent using a random CPU. | |
| # - Test #1 | |
| # * Only enable cpu_nr sysdata feature. | |
| # - Test #2 | |
| # * Keep cpu_nr sysdata feature enable and enable userdata. | |
| # - Test #3 | |
| # * keep userdata enabled, and disable sysdata cpu_nr feature. | |
| # | |
| # Author: Breno Leitao <leitao@debian.org> | |
| set -euo pipefail | |
| SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")") | |
| source "${SCRIPTDIR}"/../lib/sh/lib_netcons.sh | |
| # Enable the sysdata cpu_nr feature | |
| function set_cpu_nr() { | |
| if [[ ! -f "${NETCONS_PATH}/userdata/cpu_nr_enabled" ]] | |
| then | |
| echo "Populate CPU configfs path not available in ${NETCONS_PATH}/userdata/cpu_nr_enabled" >&2 | |
| exit "${ksft_skip}" | |
| fi | |
| echo 1 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" | |
| } | |
| # Enable the taskname to be appended to sysdata | |
| function set_taskname() { | |
| if [[ ! -f "${NETCONS_PATH}/userdata/taskname_enabled" ]] | |
| then | |
| echo "Not able to enable taskname sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/taskname_enabled" >&2 | |
| exit "${ksft_skip}" | |
| fi | |
| echo 1 > "${NETCONS_PATH}/userdata/taskname_enabled" | |
| } | |
| # Enable the release to be appended to sysdata | |
| function set_release() { | |
| if [[ ! -f "${NETCONS_PATH}/userdata/release_enabled" ]] | |
| then | |
| echo "Not able to enable release sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/release_enabled" >&2 | |
| exit "${ksft_skip}" | |
| fi | |
| echo 1 > "${NETCONS_PATH}/userdata/release_enabled" | |
| } | |
| # Enable the msgid to be appended to sysdata | |
| function set_msgid() { | |
| if [[ ! -f "${NETCONS_PATH}/userdata/msgid_enabled" ]] | |
| then | |
| echo "Not able to enable msgid sysdata append. Configfs not available in ${NETCONS_PATH}/userdata/msgid_enabled" >&2 | |
| exit "${ksft_skip}" | |
| fi | |
| echo 1 > "${NETCONS_PATH}/userdata/msgid_enabled" | |
| } | |
| # Disable the sysdata cpu_nr feature | |
| function unset_cpu_nr() { | |
| echo 0 > "${NETCONS_PATH}/userdata/cpu_nr_enabled" | |
| } | |
| # Once called, taskname=<..> will not be appended anymore | |
| function unset_taskname() { | |
| echo 0 > "${NETCONS_PATH}/userdata/taskname_enabled" | |
| } | |
| function unset_release() { | |
| echo 0 > "${NETCONS_PATH}/userdata/release_enabled" | |
| } | |
| function unset_msgid() { | |
| echo 0 > "${NETCONS_PATH}/userdata/msgid_enabled" | |
| } | |
| # Test if MSG contains sysdata | |
| function validate_sysdata() { | |
| # OUTPUT_FILE will contain something like: | |
| # 6.11.1-0_fbk0_rc13_509_g30d75cea12f7,13,1822,115075213798,-;netconsole selftest: netcons_gtJHM | |
| # userdatakey=userdatavalue | |
| # cpu=X | |
| # taskname=<taskname> | |
| # msgid=<id> | |
| # Echo is what this test uses to create the message. See runtest() | |
| # function | |
| SENDER="echo" | |
| if [ ! -f "$OUTPUT_FILE" ]; then | |
| echo "FAIL: File was not generated." >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if ! grep -q "${MSG}" "${OUTPUT_FILE}"; then | |
| echo "FAIL: ${MSG} not found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| # Check if cpu=XX exists in the file and matches the one used | |
| # in taskset(1) | |
| if ! grep -q "cpu=${CPU}\+" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'cpu=${CPU}' not found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if ! grep -q "taskname=${SENDER}" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'taskname=echo' not found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if ! grep -q "msgid=[0-9]\+$" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'msgid=<id>' not found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| rm "${OUTPUT_FILE}" | |
| pkill_socat | |
| } | |
| function validate_release() { | |
| RELEASE=$(uname -r) | |
| if [ ! -f "$OUTPUT_FILE" ]; then | |
| echo "FAIL: File was not generated." >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if ! grep -q "release=${RELEASE}" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'release=${RELEASE}' not found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| } | |
| # Test if MSG content exists in OUTPUT_FILE but no `cpu=` and `taskname=` | |
| # strings | |
| function validate_no_sysdata() { | |
| if [ ! -f "$OUTPUT_FILE" ]; then | |
| echo "FAIL: File was not generated." >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if ! grep -q "${MSG}" "${OUTPUT_FILE}"; then | |
| echo "FAIL: ${MSG} not found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if grep -q "cpu=" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'cpu= found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if grep -q "taskname=" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'taskname= found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if grep -q "release=" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'release= found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| if grep -q "msgid=" "${OUTPUT_FILE}"; then | |
| echo "FAIL: 'msgid= found in ${OUTPUT_FILE}" >&2 | |
| cat "${OUTPUT_FILE}" >&2 | |
| exit "${ksft_fail}" | |
| fi | |
| rm "${OUTPUT_FILE}" | |
| } | |
| # Start socat, send the message and wait for the file to show up in the file | |
| # system | |
| function runtest { | |
| # Listen for netconsole port inside the namespace and destination | |
| # interface | |
| listen_port_and_save_to "${OUTPUT_FILE}" & | |
| # Wait for socat to start and listen to the port. | |
| wait_local_port_listen "${NAMESPACE}" "${PORT}" udp | |
| # Send the message | |
| taskset -c "${CPU}" echo "${MSG}: ${TARGET}" > /dev/kmsg | |
| # Wait until socat saves the file to disk | |
| busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}" || true | |
| } | |
| # ========== # | |
| # Start here # | |
| # ========== # | |
| modprobe netdevsim 2> /dev/null || true | |
| modprobe netconsole 2> /dev/null || true | |
| # Check for basic system dependency and exit if not found | |
| check_for_dependencies | |
| # This test also depends on taskset(1). Check for it before starting the test | |
| check_for_taskset | |
| # Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5) | |
| echo "6 5" > /proc/sys/kernel/printk | |
| # Remove the namespace, interfaces and netconsole target on exit | |
| trap cleanup EXIT | |
| # Create one namespace and two interfaces | |
| set_network | |
| # Create a dynamic target for netconsole | |
| create_dynamic_target | |
| #==================================================== | |
| # TEST #1 | |
| # Send message from a random CPU | |
| #==================================================== | |
| # Random CPU in the system | |
| CPU=$((RANDOM % $(nproc))) | |
| OUTPUT_FILE="/tmp/${TARGET}_1" | |
| MSG="Test #1 from CPU${CPU}" | |
| # Enable the auto population of cpu_nr | |
| set_cpu_nr | |
| # Enable taskname to be appended to sysdata | |
| set_taskname | |
| set_release | |
| set_msgid | |
| runtest | |
| # Make sure the message was received in the dst part | |
| # and exit | |
| validate_release | |
| validate_sysdata | |
| #==================================================== | |
| # TEST #2 | |
| # This test now adds userdata together with sysdata | |
| # =================================================== | |
| # Get a new random CPU | |
| CPU=$((RANDOM % $(nproc))) | |
| OUTPUT_FILE="/tmp/${TARGET}_2" | |
| MSG="Test #2 from CPU${CPU}" | |
| set_user_data | |
| runtest | |
| validate_release | |
| validate_sysdata | |
| # =================================================== | |
| # TEST #3 | |
| # Unset all sysdata, fail if any userdata is set | |
| # =================================================== | |
| CPU=$((RANDOM % $(nproc))) | |
| OUTPUT_FILE="/tmp/${TARGET}_3" | |
| MSG="Test #3 from CPU${CPU}" | |
| unset_cpu_nr | |
| unset_taskname | |
| unset_release | |
| unset_msgid | |
| runtest | |
| # At this time, cpu= shouldn't be present in the msg | |
| validate_no_sysdata | |
| exit "${ksft_pass}" |