xref: /linux/tools/testing/selftests/net/rds/rds_run.sh (revision e3ab0affc10f444a86e1e3e7b35cf7a4d30ed456)
16d05d3cbSAllison Henderson#! /bin/bash
26d05d3cbSAllison Henderson# SPDX-License-Identifier: GPL-2.0
36d05d3cbSAllison Henderson
46d05d3cbSAllison Hendersonset -e
56d05d3cbSAllison Hendersonset -u
66d05d3cbSAllison Henderson
76d05d3cbSAllison Hendersonunset KBUILD_OUTPUT
86d05d3cbSAllison Henderson
96d05d3cbSAllison Hendersoncurrent_dir="$(realpath "$(dirname "$0")")"
106d05d3cbSAllison Hendersonbuild_dir="$current_dir"
116d05d3cbSAllison Henderson
126d05d3cbSAllison Hendersonbuild_include="$current_dir/include.sh"
136d05d3cbSAllison Hendersonif test -f "$build_include"; then
146d05d3cbSAllison Henderson	# this include will define "$mk_build_dir" as the location the test was
156d05d3cbSAllison Henderson	# built.  We will need this if the tests are installed in a location
166d05d3cbSAllison Henderson	# other than the kernel source
176d05d3cbSAllison Henderson
186d05d3cbSAllison Henderson	source "$build_include"
196d05d3cbSAllison Henderson	build_dir="$mk_build_dir"
206d05d3cbSAllison Hendersonfi
216d05d3cbSAllison Henderson
226d05d3cbSAllison Henderson# Source settings for timeout value (also used by ksft runner)
236d05d3cbSAllison Hendersonsource "$current_dir"/settings
246d05d3cbSAllison Henderson
256d05d3cbSAllison Henderson# This test requires kernel source and the *.gcda data therein
266d05d3cbSAllison Henderson# Locate the top level of the kernel source, and the net/rds
276d05d3cbSAllison Henderson# subfolder with the appropriate *.gcno object files
286d05d3cbSAllison Hendersonksrc_dir="$(realpath "$build_dir"/../../../../../)"
296d05d3cbSAllison Hendersonkconfig="$ksrc_dir/.config"
306d05d3cbSAllison Hendersonobj_dir="$ksrc_dir/net/rds"
316d05d3cbSAllison Henderson
326d05d3cbSAllison HendersonGCOV_CMD=gcov
336d05d3cbSAllison Henderson
346d05d3cbSAllison Henderson#check to see if the host has the required packages to generate a gcov report
356d05d3cbSAllison Hendersoncheck_gcov_env()
366d05d3cbSAllison Henderson{
376d05d3cbSAllison Henderson	if ! which "$GCOV_CMD" > /dev/null 2>&1; then
386d05d3cbSAllison Henderson		echo "# Warning: Could not find gcov. "
396d05d3cbSAllison Henderson		GENERATE_GCOV_REPORT=0
406d05d3cbSAllison Henderson		return
416d05d3cbSAllison Henderson	fi
426d05d3cbSAllison Henderson
436d05d3cbSAllison Henderson	# the gcov version must match the gcc version
446d05d3cbSAllison Henderson	GCC_VER=$(gcc -dumpfullversion)
456d05d3cbSAllison Henderson	GCOV_VER=$($GCOV_CMD -v | grep gcov | awk '{print $3}'| awk 'BEGIN {FS="-"}{print $1}')
466d05d3cbSAllison Henderson	if [ "$GCOV_VER" != "$GCC_VER" ]; then
476d05d3cbSAllison Henderson		#attempt to find a matching gcov version
486d05d3cbSAllison Henderson		GCOV_CMD=gcov-$(gcc -dumpversion)
496d05d3cbSAllison Henderson
506d05d3cbSAllison Henderson		if ! which "$GCOV_CMD" > /dev/null 2>&1; then
516d05d3cbSAllison Henderson			echo "# Warning: Could not find an appropriate gcov installation. \
526d05d3cbSAllison Henderson				gcov version must match gcc version"
536d05d3cbSAllison Henderson			GENERATE_GCOV_REPORT=0
546d05d3cbSAllison Henderson			return
556d05d3cbSAllison Henderson		fi
566d05d3cbSAllison Henderson
576d05d3cbSAllison Henderson		#recheck version number of found gcov executable
586d05d3cbSAllison Henderson		GCOV_VER=$($GCOV_CMD -v | grep gcov | awk '{print $3}'| \
596d05d3cbSAllison Henderson			awk 'BEGIN {FS="-"}{print $1}')
606d05d3cbSAllison Henderson		if [ "$GCOV_VER" != "$GCC_VER" ]; then
616d05d3cbSAllison Henderson			echo "# Warning: Could not find an appropriate gcov installation. \
626d05d3cbSAllison Henderson				gcov version must match gcc version"
636d05d3cbSAllison Henderson			GENERATE_GCOV_REPORT=0
646d05d3cbSAllison Henderson		else
656d05d3cbSAllison Henderson			echo "# Warning: Mismatched gcc and gcov detected.  Using $GCOV_CMD"
666d05d3cbSAllison Henderson		fi
676d05d3cbSAllison Henderson	fi
686d05d3cbSAllison Henderson}
696d05d3cbSAllison Henderson
706d05d3cbSAllison Henderson# Check to see if the kconfig has the required configs to generate a coverage report
716d05d3cbSAllison Hendersoncheck_gcov_conf()
726d05d3cbSAllison Henderson{
736d05d3cbSAllison Henderson	if ! grep -x "CONFIG_GCOV_PROFILE_RDS=y" "$kconfig" > /dev/null 2>&1; then
746d05d3cbSAllison Henderson		echo "# INFO: CONFIG_GCOV_PROFILE_RDS should be enabled for coverage reports"
756d05d3cbSAllison Henderson		GENERATE_GCOV_REPORT=0
766d05d3cbSAllison Henderson	fi
776d05d3cbSAllison Henderson	if ! grep -x "CONFIG_GCOV_KERNEL=y" "$kconfig" > /dev/null 2>&1; then
786d05d3cbSAllison Henderson		echo "# INFO: CONFIG_GCOV_KERNEL should be enabled for coverage reports"
796d05d3cbSAllison Henderson		GENERATE_GCOV_REPORT=0
806d05d3cbSAllison Henderson	fi
816d05d3cbSAllison Henderson	if grep -x "CONFIG_GCOV_PROFILE_ALL=y" "$kconfig" > /dev/null 2>&1; then
826d05d3cbSAllison Henderson		echo "# INFO: CONFIG_GCOV_PROFILE_ALL should be disabled for coverage reports"
836d05d3cbSAllison Henderson		GENERATE_GCOV_REPORT=0
846d05d3cbSAllison Henderson	fi
856d05d3cbSAllison Henderson
866d05d3cbSAllison Henderson	if [ "$GENERATE_GCOV_REPORT" -eq 0 ]; then
876d05d3cbSAllison Henderson		echo "# To enable gcov reports, please run "\
886d05d3cbSAllison Henderson			"\"tools/testing/selftests/net/rds/config.sh -g\" and rebuild the kernel"
896d05d3cbSAllison Henderson	else
906d05d3cbSAllison Henderson		# if we have the required kernel configs, proceed to check the environment to
916d05d3cbSAllison Henderson		# ensure we have the required gcov packages
926d05d3cbSAllison Henderson		check_gcov_env
936d05d3cbSAllison Henderson	fi
946d05d3cbSAllison Henderson}
956d05d3cbSAllison Henderson
96c5eb1376SAllison Henderson# Checks if a kconfig is enabled (set to =y or =m)
97c5eb1376SAllison Henderson# $1: kconfig symbol to check
98c5eb1376SAllison Henderson# $2: (optional) module name backing $1
99c5eb1376SAllison Henderson#     Ex: check_conf_enabled CONFIG_RDS_TCP rds_tcp
100c5eb1376SAllison Henderson#     Modules for configs set to  =m will be probed
101c5eb1376SAllison Henderson#     If omitted, only a built-in (=y) config is accepted.
102c5eb1376SAllison Henderson# Returns on success.  exits 4 on failure
1036d05d3cbSAllison Henderson# Kselftest framework requirement - SKIP code is 4.
1046d05d3cbSAllison Hendersoncheck_conf_enabled() {
105c5eb1376SAllison Henderson	if grep -x "$1=y" "$kconfig" > /dev/null 2>&1; then
106c5eb1376SAllison Henderson		return
1076d05d3cbSAllison Henderson	fi
108c5eb1376SAllison Henderson	if [ -n "${2:-}" ] && grep -x "$1=m" "$kconfig" > /dev/null 2>&1; then
109c5eb1376SAllison Henderson		probe_module "$2"
110c5eb1376SAllison Henderson		return
111c5eb1376SAllison Henderson	fi
112c5eb1376SAllison Henderson	echo "selftests: [SKIP] This test requires $1 enabled"
113c5eb1376SAllison Henderson	echo "Please run" \
114c5eb1376SAllison Henderson	     "tools/testing/selftests/net/rds/config.sh and rebuild the kernel"
115c5eb1376SAllison Henderson	exit 4
1166d05d3cbSAllison Henderson}
1176d05d3cbSAllison Henderson
1186d05d3cbSAllison Hendersoncheck_rdma_conf_enabled() {
119c5eb1376SAllison Henderson	if grep -x "$1=y" "$kconfig" > /dev/null 2>&1; then
120c5eb1376SAllison Henderson		return
121c5eb1376SAllison Henderson	fi
122c5eb1376SAllison Henderson	if [ -n "${2:-}" ] && grep -x "$1=m" "$kconfig" > /dev/null 2>&1; then
123c5eb1376SAllison Henderson		probe_module "$2"
124c5eb1376SAllison Henderson		return
125c5eb1376SAllison Henderson	fi
126*e3ab0affSAllison Henderson	echo "selftests: [XFAIL] rdma transport requires $1 enabled"
1276d05d3cbSAllison Henderson	echo "To enable, run" \
1286d05d3cbSAllison Henderson	     "tools/testing/selftests/net/rds/config.sh -r and rebuild"
129*e3ab0affSAllison Henderson	exit 2
1306d05d3cbSAllison Henderson}
1316d05d3cbSAllison Henderson
132c5eb1376SAllison Henderson# Load the module backing a config that is built as a loadable module
133c5eb1376SAllison Henderson# (=m).  Built-in (=y) configs are already available and don't reach
134c5eb1376SAllison Henderson# here.  Exits with the SKIP code if a required module cannot be loaded.
135c5eb1376SAllison Hendersonprobe_module() {
136c5eb1376SAllison Henderson	if ! modprobe -q "$1"; then
137c5eb1376SAllison Henderson		echo "selftests: [SKIP] could not load required module $1"
1386d05d3cbSAllison Henderson		exit 4
1396d05d3cbSAllison Henderson	fi
1406d05d3cbSAllison Henderson}
141c5eb1376SAllison Henderson
1426d05d3cbSAllison Hendersoncheck_conf() {
143c5eb1376SAllison Henderson	check_conf_enabled CONFIG_NET_SCH_NETEM sch_netem
144c5eb1376SAllison Henderson	check_conf_enabled CONFIG_VETH veth
1456d05d3cbSAllison Henderson	check_conf_enabled CONFIG_NET_NS
146c5eb1376SAllison Henderson	check_conf_enabled CONFIG_RDS_TCP rds_tcp
147c5eb1376SAllison Henderson	check_conf_enabled CONFIG_RDS rds
1486d05d3cbSAllison Henderson}
1496d05d3cbSAllison Henderson
1506d05d3cbSAllison Henderson# Check kernel config and host environment for RDS-RDMA support.
151*e3ab0affSAllison Henderson# Exits with XFAIL (2) if the user requested rdma but prerequisites
1526d05d3cbSAllison Henderson# are not met.
1536d05d3cbSAllison Hendersoncheck_rdma_conf()
1546d05d3cbSAllison Henderson{
1556d05d3cbSAllison Henderson	case "$TRANSPORT" in
1566d05d3cbSAllison Henderson	  *rdma*) ;;
1576d05d3cbSAllison Henderson	  *) return ;;
1586d05d3cbSAllison Henderson	esac
1596d05d3cbSAllison Henderson
1606d05d3cbSAllison Henderson	# Kconfig will enforce CONFIG_INFINIBAND_* as dependencies
1616d05d3cbSAllison Henderson	# of CONFIG_RDMA_RXE
162c5eb1376SAllison Henderson	check_rdma_conf_enabled CONFIG_RDMA_RXE rdma_rxe
163c5eb1376SAllison Henderson	check_rdma_conf_enabled CONFIG_RDS_RDMA rds_rdma
1646d05d3cbSAllison Henderson
1656d05d3cbSAllison Henderson	if ! which rdma > /dev/null 2>&1; then
166*e3ab0affSAllison Henderson		echo "selftests: [XFAIL] rdma transport requires the 'rdma'" \
1676d05d3cbSAllison Henderson		      "tool (iproute2)"
168*e3ab0affSAllison Henderson		exit 2
1696d05d3cbSAllison Henderson	fi
1706d05d3cbSAllison Henderson}
1716d05d3cbSAllison Henderson
1726d05d3cbSAllison Hendersoncheck_env()
1736d05d3cbSAllison Henderson{
1746d05d3cbSAllison Henderson	if ! test -d "$obj_dir"; then
1756d05d3cbSAllison Henderson		echo "selftests: [SKIP] This test requires a kernel source tree"
1766d05d3cbSAllison Henderson		exit 4
1776d05d3cbSAllison Henderson	fi
1786d05d3cbSAllison Henderson	if ! test -e "$kconfig"; then
1796d05d3cbSAllison Henderson		echo "selftests: [SKIP] This test requires a configured kernel source tree"
1806d05d3cbSAllison Henderson		exit 4
1816d05d3cbSAllison Henderson	fi
1826d05d3cbSAllison Henderson	if ! which strace > /dev/null 2>&1; then
1836d05d3cbSAllison Henderson		echo "selftests: [SKIP] Could not run test without strace"
1846d05d3cbSAllison Henderson		exit 4
1856d05d3cbSAllison Henderson	fi
1866d05d3cbSAllison Henderson	if ! which tcpdump > /dev/null 2>&1; then
1876d05d3cbSAllison Henderson		echo "selftests: [SKIP] Could not run test without tcpdump"
1886d05d3cbSAllison Henderson		exit 4
1896d05d3cbSAllison Henderson	fi
1906d05d3cbSAllison Henderson
1916d05d3cbSAllison Henderson	if ! which python3 > /dev/null 2>&1; then
1926d05d3cbSAllison Henderson		echo "selftests: [SKIP] Could not run test without python3"
1936d05d3cbSAllison Henderson		exit 4
1946d05d3cbSAllison Henderson	fi
1956d05d3cbSAllison Henderson
1966d05d3cbSAllison Henderson	python_major=$(python3 -c "import sys; print(sys.version_info[0])")
1976d05d3cbSAllison Henderson	python_minor=$(python3 -c "import sys; print(sys.version_info[1])")
1986d05d3cbSAllison Henderson	if [[ python_major -lt 3 || ( python_major -eq 3 && python_minor -lt 9 ) ]] ; then
1996d05d3cbSAllison Henderson		echo "selftests: [SKIP] Could not run test without at least python3.9"
2006d05d3cbSAllison Henderson		python3 -V
2016d05d3cbSAllison Henderson		exit 4
2026d05d3cbSAllison Henderson	fi
2036d05d3cbSAllison Henderson}
2046d05d3cbSAllison Henderson
2056d05d3cbSAllison HendersonLOG_DIR="${RDS_LOG_DIR:-}"
2066d05d3cbSAllison HendersonTIMEOUT=$timeout
2076d05d3cbSAllison HendersonGENERATE_GCOV_REPORT=1
2086d05d3cbSAllison HendersonTRANSPORT=tcp
2096d05d3cbSAllison HendersonFLAGS=()
2106d05d3cbSAllison Henderson
2116d05d3cbSAllison Hendersonwhile getopts "d:l:c:u:t:T:" opt; do
2126d05d3cbSAllison Henderson  case ${opt} in
2136d05d3cbSAllison Henderson    d)
2146d05d3cbSAllison Henderson      LOG_DIR=${OPTARG}
2156d05d3cbSAllison Henderson      ;;
2166d05d3cbSAllison Henderson    l)
2176d05d3cbSAllison Henderson      FLAGS+=("-l" "${OPTARG}")
2186d05d3cbSAllison Henderson      ;;
2196d05d3cbSAllison Henderson    c)
2206d05d3cbSAllison Henderson      FLAGS+=("-c" "${OPTARG}")
2216d05d3cbSAllison Henderson      ;;
2226d05d3cbSAllison Henderson    t)
2236d05d3cbSAllison Henderson      TIMEOUT=${OPTARG}
2246d05d3cbSAllison Henderson      ;;
2256d05d3cbSAllison Henderson    u)
2266d05d3cbSAllison Henderson      FLAGS+=("-u" "${OPTARG}")
2276d05d3cbSAllison Henderson      ;;
2286d05d3cbSAllison Henderson    T)
2296d05d3cbSAllison Henderson      TRANSPORT=${OPTARG}
2306d05d3cbSAllison Henderson      ;;
2316d05d3cbSAllison Henderson    :)
2326d05d3cbSAllison Henderson      echo "USAGE: rds_run.sh [-d logdir] [-l packet_loss]" \
2336d05d3cbSAllison Henderson           "[-c packet_corruption] [-u packet_duplicate] [-t timeout]" \
2346d05d3cbSAllison Henderson           "[-T tcp|rdma|tcp,rdma]"
2356d05d3cbSAllison Henderson      exit 1
2366d05d3cbSAllison Henderson      ;;
2376d05d3cbSAllison Henderson    ?)
2386d05d3cbSAllison Henderson      echo "Invalid option: -${OPTARG}."
2396d05d3cbSAllison Henderson      exit 1
2406d05d3cbSAllison Henderson      ;;
2416d05d3cbSAllison Henderson  esac
2426d05d3cbSAllison Hendersondone
2436d05d3cbSAllison Henderson
2446d05d3cbSAllison Henderson# Validate transport tokens
2456d05d3cbSAllison HendersonIFS=',' read -ra transports <<< "$TRANSPORT"
2466d05d3cbSAllison Hendersonfor t in "${transports[@]}"; do
2476d05d3cbSAllison Henderson    if [ "$t" != "tcp" ] && [ "$t" != "rdma" ]; then
2486d05d3cbSAllison Henderson        echo "rds_run.sh: unknown transport '$t' (expected tcp or rdma)"
2496d05d3cbSAllison Henderson        exit 1
2506d05d3cbSAllison Henderson    fi
2516d05d3cbSAllison Hendersondone
2526d05d3cbSAllison Henderson
2536d05d3cbSAllison HendersonFLAGS+=("--transport" "${TRANSPORT}")
2546d05d3cbSAllison Henderson
2556d05d3cbSAllison Hendersoncheck_env
2566d05d3cbSAllison Hendersoncheck_conf
2576d05d3cbSAllison Hendersoncheck_gcov_conf
2586d05d3cbSAllison Hendersoncheck_rdma_conf
2596d05d3cbSAllison Henderson
2606d05d3cbSAllison HendersonTRACE_CMD=()
2616d05d3cbSAllison Hendersonif [[ -n "$LOG_DIR" ]]; then
2626d05d3cbSAllison Henderson   FLAGS+=("-d" "$LOG_DIR")
2636d05d3cbSAllison Henderson
2646d05d3cbSAllison Henderson   TRACE_FILE="${LOG_DIR}/rds-strace.txt"
2656d05d3cbSAllison Henderson   COVR_DIR="${LOG_DIR}/coverage/"
2666d05d3cbSAllison Henderson   DMESG_FILE="${LOG_DIR}/rds-dmesg.out"
2676d05d3cbSAllison Henderson
2686d05d3cbSAllison Henderson   mkdir -p  "$LOG_DIR"
2696d05d3cbSAllison Henderson   mkdir -p "$COVR_DIR"
2706d05d3cbSAllison Henderson
2716d05d3cbSAllison Henderson   rm -f "$TRACE_FILE"
2726d05d3cbSAllison Henderson   rm -f "$DMESG_FILE"
2736d05d3cbSAllison Henderson   rm -f "$LOG_DIR"/rds-*.pcap
2746d05d3cbSAllison Henderson   rm -f "$COVR_DIR"/gcovr*
2756d05d3cbSAllison Henderson
2766d05d3cbSAllison Henderson   echo "# Traces will be logged to ${TRACE_FILE}"
2776d05d3cbSAllison Henderson   TRACE_CMD=(strace -T -tt -o "${TRACE_FILE}")
2786d05d3cbSAllison Hendersonfi
2796d05d3cbSAllison Henderson
2806d05d3cbSAllison Hendersonset +e
2816d05d3cbSAllison Hendersonecho "# running RDS tests..."
2826d05d3cbSAllison Henderson"${TRACE_CMD[@]}" python3 "$(dirname "$0")/test.py" "${FLAGS[@]}" -t "$TIMEOUT"
2836d05d3cbSAllison Henderson
2846d05d3cbSAllison Hendersontest_rc=$?
2856d05d3cbSAllison Henderson
2866d05d3cbSAllison Hendersonif [[ -n "$LOG_DIR" ]]; then
2876d05d3cbSAllison Henderson   dmesg > "${DMESG_FILE}"
2886d05d3cbSAllison Hendersonfi
2896d05d3cbSAllison Henderson
2906d05d3cbSAllison Hendersonif [[ -n "$LOG_DIR" ]] && [ "$GENERATE_GCOV_REPORT" -eq 1 ]; then
2916d05d3cbSAllison Henderson       echo "# saving coverage data..."
2926d05d3cbSAllison Henderson
2936d05d3cbSAllison Henderson       # Ensure debugfs is mounted before reading gcov data.
2946d05d3cbSAllison Henderson       if ! mountpoint -q /sys/kernel/debug 2>/dev/null; then
2956d05d3cbSAllison Henderson               mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null || true
2966d05d3cbSAllison Henderson       fi
2976d05d3cbSAllison Henderson
2986d05d3cbSAllison Henderson       (set +x; cd /sys/kernel/debug/gcov; find ./* -name '*.gcda' | \
2996d05d3cbSAllison Henderson       while read -r f
3006d05d3cbSAllison Henderson       do
3016d05d3cbSAllison Henderson               cat < "/sys/kernel/debug/gcov/$f" > "/$f"
3026d05d3cbSAllison Henderson       done)
3036d05d3cbSAllison Henderson
3046d05d3cbSAllison Henderson       echo "# running gcovr..."
3056d05d3cbSAllison Henderson       gcovr -s --html-details --gcov-executable "$GCOV_CMD" --gcov-ignore-parse-errors \
3066d05d3cbSAllison Henderson             --root "${ksrc_dir}" -o "${COVR_DIR}/gcovr" "${ksrc_dir}/net/rds/" \
3076d05d3cbSAllison Henderson             > "${LOG_DIR}/gcovr.log" 2>&1
3086d05d3cbSAllison Henderson       echo "# gcovr log: ${LOG_DIR}/gcovr.log"
3096d05d3cbSAllison Hendersonelse
3106d05d3cbSAllison Henderson       echo "# Coverage report will be skipped"
3116d05d3cbSAllison Hendersonfi
3126d05d3cbSAllison Henderson
3136d05d3cbSAllison Hendersonif [ "$test_rc" -eq 0 ]; then
3146d05d3cbSAllison Henderson	echo "# PASS: Test completed successfully"
3156d05d3cbSAllison Hendersonelse
3166d05d3cbSAllison Henderson	echo "# FAIL: Test failed"
3176d05d3cbSAllison Hendersonfi
3186d05d3cbSAllison Henderson
3196d05d3cbSAllison Hendersonexit "$test_rc"
320