blob: cdf487ec97dcc6526fa9cd3e3ee08caad0e55d38 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
|
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
set -e
set -u
unset KBUILD_OUTPUT
current_dir="$(realpath "$(dirname "$0")")"
build_dir="$current_dir"
build_include="$current_dir/include.sh"
if test -f "$build_include"; then
# this include will define "$mk_build_dir" as the location the test was
# built. We will need this if the tests are installed in a location
# other than the kernel source
source "$build_include"
build_dir="$mk_build_dir"
fi
# Source settings for timeout value (also used by ksft runner)
source "$current_dir"/settings
# This test requires kernel source and the *.gcda data therein
# Locate the top level of the kernel source, and the net/rds
# subfolder with the appropriate *.gcno object files
ksrc_dir="$(realpath "$build_dir"/../../../../../)"
kconfig="$ksrc_dir/.config"
obj_dir="$ksrc_dir/net/rds"
GCOV_CMD=gcov
#check to see if the host has the required packages to generate a gcov report
check_gcov_env()
{
if ! which "$GCOV_CMD" > /dev/null 2>&1; then
echo "# Warning: Could not find gcov. "
GENERATE_GCOV_REPORT=0
return
fi
# the gcov version must match the gcc version
GCC_VER=$(gcc -dumpfullversion)
GCOV_VER=$($GCOV_CMD -v | grep gcov | awk '{print $3}'| awk 'BEGIN {FS="-"}{print $1}')
if [ "$GCOV_VER" != "$GCC_VER" ]; then
#attempt to find a matching gcov version
GCOV_CMD=gcov-$(gcc -dumpversion)
if ! which "$GCOV_CMD" > /dev/null 2>&1; then
echo "# Warning: Could not find an appropriate gcov installation. \
gcov version must match gcc version"
GENERATE_GCOV_REPORT=0
return
fi
#recheck version number of found gcov executable
GCOV_VER=$($GCOV_CMD -v | grep gcov | awk '{print $3}'| \
awk 'BEGIN {FS="-"}{print $1}')
if [ "$GCOV_VER" != "$GCC_VER" ]; then
echo "# Warning: Could not find an appropriate gcov installation. \
gcov version must match gcc version"
GENERATE_GCOV_REPORT=0
else
echo "# Warning: Mismatched gcc and gcov detected. Using $GCOV_CMD"
fi
fi
}
# Check to see if the kconfig has the required configs to generate a coverage report
check_gcov_conf()
{
if ! grep -x "CONFIG_GCOV_PROFILE_RDS=y" "$kconfig" > /dev/null 2>&1; then
echo "# INFO: CONFIG_GCOV_PROFILE_RDS should be enabled for coverage reports"
GENERATE_GCOV_REPORT=0
fi
if ! grep -x "CONFIG_GCOV_KERNEL=y" "$kconfig" > /dev/null 2>&1; then
echo "# INFO: CONFIG_GCOV_KERNEL should be enabled for coverage reports"
GENERATE_GCOV_REPORT=0
fi
if grep -x "CONFIG_GCOV_PROFILE_ALL=y" "$kconfig" > /dev/null 2>&1; then
echo "# INFO: CONFIG_GCOV_PROFILE_ALL should be disabled for coverage reports"
GENERATE_GCOV_REPORT=0
fi
if [ "$GENERATE_GCOV_REPORT" -eq 0 ]; then
echo "# To enable gcov reports, please run "\
"\"tools/testing/selftests/net/rds/config.sh -g\" and rebuild the kernel"
else
# if we have the required kernel configs, proceed to check the environment to
# ensure we have the required gcov packages
check_gcov_env
fi
}
# Checks if a kconfig is enabled (set to =y or =m)
# $1: kconfig symbol to check
# $2: (optional) module name backing $1
# Ex: check_conf_enabled CONFIG_RDS_TCP rds_tcp
# Modules for configs set to =m will be probed
# If omitted, only a built-in (=y) config is accepted.
# Returns on success. exits 4 on failure
# Kselftest framework requirement - SKIP code is 4.
check_conf_enabled() {
if grep -x "$1=y" "$kconfig" > /dev/null 2>&1; then
return
fi
if [ -n "${2:-}" ] && grep -x "$1=m" "$kconfig" > /dev/null 2>&1; then
probe_module "$2"
return
fi
echo "selftests: [SKIP] This test requires $1 enabled"
echo "Please run" \
"tools/testing/selftests/net/rds/config.sh and rebuild the kernel"
exit 4
}
check_rdma_conf_enabled() {
if grep -x "$1=y" "$kconfig" > /dev/null 2>&1; then
return
fi
if [ -n "${2:-}" ] && grep -x "$1=m" "$kconfig" > /dev/null 2>&1; then
probe_module "$2"
return
fi
echo "selftests: [XFAIL] rdma transport requires $1 enabled"
echo "To enable, run" \
"tools/testing/selftests/net/rds/config.sh -r and rebuild"
exit 2
}
# Load the module backing a config that is built as a loadable module
# (=m). Built-in (=y) configs are already available and don't reach
# here. Exits with the SKIP code if a required module cannot be loaded.
probe_module() {
if ! modprobe -q "$1"; then
echo "selftests: [SKIP] could not load required module $1"
exit 4
fi
}
check_conf() {
check_conf_enabled CONFIG_NET_SCH_NETEM sch_netem
check_conf_enabled CONFIG_VETH veth
check_conf_enabled CONFIG_NET_NS
check_conf_enabled CONFIG_RDS_TCP rds_tcp
check_conf_enabled CONFIG_RDS rds
}
# Check kernel config and host environment for RDS-RDMA support.
# Exits with XFAIL (2) if the user requested rdma but prerequisites
# are not met.
check_rdma_conf()
{
case "$TRANSPORT" in
*rdma*) ;;
*) return ;;
esac
# Kconfig will enforce CONFIG_INFINIBAND_* as dependencies
# of CONFIG_RDMA_RXE
check_rdma_conf_enabled CONFIG_RDMA_RXE rdma_rxe
check_rdma_conf_enabled CONFIG_RDS_RDMA rds_rdma
if ! which rdma > /dev/null 2>&1; then
echo "selftests: [XFAIL] rdma transport requires the 'rdma'" \
"tool (iproute2)"
exit 2
fi
}
check_env()
{
if ! test -d "$obj_dir"; then
echo "selftests: [SKIP] This test requires a kernel source tree"
exit 4
fi
if ! test -e "$kconfig"; then
echo "selftests: [SKIP] This test requires a configured kernel source tree"
exit 4
fi
if ! which strace > /dev/null 2>&1; then
echo "selftests: [SKIP] Could not run test without strace"
exit 4
fi
if ! which tcpdump > /dev/null 2>&1; then
echo "selftests: [SKIP] Could not run test without tcpdump"
exit 4
fi
if ! which python3 > /dev/null 2>&1; then
echo "selftests: [SKIP] Could not run test without python3"
exit 4
fi
python_major=$(python3 -c "import sys; print(sys.version_info[0])")
python_minor=$(python3 -c "import sys; print(sys.version_info[1])")
if [[ python_major -lt 3 || ( python_major -eq 3 && python_minor -lt 9 ) ]] ; then
echo "selftests: [SKIP] Could not run test without at least python3.9"
python3 -V
exit 4
fi
}
LOG_DIR="${RDS_LOG_DIR:-}"
TIMEOUT=$timeout
GENERATE_GCOV_REPORT=1
TRANSPORT=tcp
FLAGS=()
while getopts "d:l:c:u:t:T:" opt; do
case ${opt} in
d)
LOG_DIR=${OPTARG}
;;
l)
FLAGS+=("-l" "${OPTARG}")
;;
c)
FLAGS+=("-c" "${OPTARG}")
;;
t)
TIMEOUT=${OPTARG}
;;
u)
FLAGS+=("-u" "${OPTARG}")
;;
T)
TRANSPORT=${OPTARG}
;;
:)
echo "USAGE: rds_run.sh [-d logdir] [-l packet_loss]" \
"[-c packet_corruption] [-u packet_duplicate] [-t timeout]" \
"[-T tcp|rdma|tcp,rdma]"
exit 1
;;
?)
echo "Invalid option: -${OPTARG}."
exit 1
;;
esac
done
# Validate transport tokens
IFS=',' read -ra transports <<< "$TRANSPORT"
for t in "${transports[@]}"; do
if [ "$t" != "tcp" ] && [ "$t" != "rdma" ]; then
echo "rds_run.sh: unknown transport '$t' (expected tcp or rdma)"
exit 1
fi
done
FLAGS+=("--transport" "${TRANSPORT}")
check_env
check_conf
check_gcov_conf
check_rdma_conf
TRACE_CMD=()
if [[ -n "$LOG_DIR" ]]; then
FLAGS+=("-d" "$LOG_DIR")
TRACE_FILE="${LOG_DIR}/rds-strace.txt"
COVR_DIR="${LOG_DIR}/coverage/"
DMESG_FILE="${LOG_DIR}/rds-dmesg.out"
mkdir -p "$LOG_DIR"
mkdir -p "$COVR_DIR"
rm -f "$TRACE_FILE"
rm -f "$DMESG_FILE"
rm -f "$LOG_DIR"/rds-*.pcap
rm -f "$COVR_DIR"/gcovr*
echo "# Traces will be logged to ${TRACE_FILE}"
TRACE_CMD=(strace -T -tt -o "${TRACE_FILE}")
fi
set +e
echo "# running RDS tests..."
"${TRACE_CMD[@]}" python3 "$(dirname "$0")/test.py" "${FLAGS[@]}" -t "$TIMEOUT"
test_rc=$?
if [[ -n "$LOG_DIR" ]]; then
dmesg > "${DMESG_FILE}"
fi
if [[ -n "$LOG_DIR" ]] && [ "$GENERATE_GCOV_REPORT" -eq 1 ]; then
echo "# saving coverage data..."
# Ensure debugfs is mounted before reading gcov data.
if ! mountpoint -q /sys/kernel/debug 2>/dev/null; then
mount -t debugfs debugfs /sys/kernel/debug 2>/dev/null || true
fi
(set +x; cd /sys/kernel/debug/gcov; find ./* -name '*.gcda' | \
while read -r f
do
cat < "/sys/kernel/debug/gcov/$f" > "/$f"
done)
echo "# running gcovr..."
gcovr -s --html-details --gcov-executable "$GCOV_CMD" --gcov-ignore-parse-errors \
--root "${ksrc_dir}" -o "${COVR_DIR}/gcovr" "${ksrc_dir}/net/rds/" \
> "${LOG_DIR}/gcovr.log" 2>&1
echo "# gcovr log: ${LOG_DIR}/gcovr.log"
else
echo "# Coverage report will be skipped"
fi
if [ "$test_rc" -eq 0 ]; then
echo "# PASS: Test completed successfully"
else
echo "# FAIL: Test failed"
fi
exit "$test_rc"
|