Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4# Double quotes to prevent globbing and word splitting is recommended in new
5# code but we accept it, especially because there were too many before having
6# address all other issues detected by shellcheck.
7#shellcheck disable=SC2086
8
9. "$(dirname "${0}")/mptcp_lib.sh"
10
11ns1=""
12ns2=""
13ns3=""
14capture=false
15timeout_poll=30
16timeout_test=$((timeout_poll * 2 + 1))
17# a bit more space: because we have more to display
18MPTCP_LIB_TEST_FORMAT="%02u %-60s"
19ret=0
20bail=0
21slack=50
22large=""
23small=""
24sout=""
25cout=""
26capout=""
27size=0
28
29usage() {
30 echo "Usage: $0 [ -b ] [ -c ] [ -d ] [ -i]"
31 echo -e "\t-b: bail out after first error, otherwise runs all testcases"
32 echo -e "\t-c: capture packets for each test using tcpdump (default: no capture)"
33 echo -e "\t-d: debug this script"
34 echo -e "\t-i: use 'ip mptcp' instead of 'pm_nl_ctl'"
35}
36
37# This function is used in the cleanup trap
38#shellcheck disable=SC2317,SC2329
39cleanup()
40{
41 rm -f "$cout" "$sout"
42 rm -f "$large" "$small"
43 rm -f "$capout"
44
45 mptcp_lib_ns_exit "${ns1}" "${ns2}" "${ns3}"
46}
47
48mptcp_lib_check_mptcp
49mptcp_lib_check_tools ip tc
50
51# "$ns1" ns2 ns3
52# ns1eth1 ns2eth1 ns2eth3 ns3eth1
53# netem
54# ns1eth2 ns2eth2
55# netem
56
57setup()
58{
59 large=$(mktemp)
60 small=$(mktemp)
61 sout=$(mktemp)
62 cout=$(mktemp)
63 capout=$(mktemp)
64 size=$((2 * 2048 * 4096))
65
66 dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1
67 dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1
68
69 trap cleanup EXIT
70
71 mptcp_lib_ns_init ns1 ns2 ns3
72
73 ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
74 ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth2 netns "$ns2"
75 ip link add ns2eth3 netns "$ns2" type veth peer name ns3eth1 netns "$ns3"
76
77 ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth1
78 ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth1 nodad
79 ip -net "$ns1" link set ns1eth1 up mtu 1500
80 ip -net "$ns1" route add default via 10.0.1.2
81 ip -net "$ns1" route add default via dead:beef:1::2
82
83 ip -net "$ns1" addr add 10.0.2.1/24 dev ns1eth2
84 ip -net "$ns1" addr add dead:beef:2::1/64 dev ns1eth2 nodad
85 ip -net "$ns1" link set ns1eth2 up mtu 1500
86 ip -net "$ns1" route add default via 10.0.2.2 metric 101
87 ip -net "$ns1" route add default via dead:beef:2::2 metric 101
88
89 mptcp_lib_pm_nl_set_limits "${ns1}" 1 1
90 mptcp_lib_pm_nl_add_endpoint "${ns1}" 10.0.2.1 dev ns1eth2 flags subflow
91
92 ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1
93 ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad
94 ip -net "$ns2" link set ns2eth1 up mtu 1500
95
96 ip -net "$ns2" addr add 10.0.2.2/24 dev ns2eth2
97 ip -net "$ns2" addr add dead:beef:2::2/64 dev ns2eth2 nodad
98 ip -net "$ns2" link set ns2eth2 up mtu 1500
99
100 ip -net "$ns2" addr add 10.0.3.2/24 dev ns2eth3
101 ip -net "$ns2" addr add dead:beef:3::2/64 dev ns2eth3 nodad
102 ip -net "$ns2" link set ns2eth3 up mtu 1500
103 ip netns exec "$ns2" sysctl -q net.ipv4.ip_forward=1
104 ip netns exec "$ns2" sysctl -q net.ipv6.conf.all.forwarding=1
105
106 ip -net "$ns3" addr add 10.0.3.3/24 dev ns3eth1
107 ip -net "$ns3" addr add dead:beef:3::3/64 dev ns3eth1 nodad
108 ip -net "$ns3" link set ns3eth1 up mtu 1500
109 ip -net "$ns3" route add default via 10.0.3.2
110 ip -net "$ns3" route add default via dead:beef:3::2
111
112 mptcp_lib_pm_nl_set_limits "${ns3}" 1 1
113
114 # debug build can slow down measurably the test program
115 # we use quite tight time limit on the run-time, to ensure
116 # maximum B/W usage.
117 # Use kmemleak/lockdep/kasan/prove_locking presence as a rough
118 # estimate for this being a debug kernel and increase the
119 # maximum run-time accordingly. Observed run times for CI builds
120 # running selftests, including kbuild, were used to determine the
121 # amount of time to add.
122 grep -q ' kmemleak_init$\| lockdep_init$\| kasan_init$\| prove_locking$' /proc/kallsyms && slack=$((slack+550))
123}
124
125do_transfer()
126{
127 local cin=$1
128 local sin=$2
129 local max_time=$3
130 local port
131 port=$((10000+MPTCP_LIB_TEST_COUNTER))
132
133 :> "$cout"
134 :> "$sout"
135 :> "$capout"
136
137 if $capture; then
138 local capuser
139 local rndh="${ns1:4}"
140 if [ -z $SUDO_USER ] ; then
141 capuser=""
142 else
143 capuser="-Z $SUDO_USER"
144 fi
145
146 local capfile="${rndh}-${port}"
147 local capopt="-i any -s 65535 -B 32768 ${capuser}"
148
149 ip netns exec ${ns3} tcpdump ${capopt} -w "${capfile}-listener.pcap" >> "${capout}" 2>&1 &
150 local cappid_listener=$!
151
152 ip netns exec ${ns1} tcpdump ${capopt} -w "${capfile}-connector.pcap" >> "${capout}" 2>&1 &
153 local cappid_connector=$!
154
155 sleep 1
156 fi
157
158 mptcp_lib_nstat_init "${ns3}"
159 mptcp_lib_nstat_init "${ns1}"
160
161 ip netns exec ${ns3} \
162 ./mptcp_connect -jt ${timeout_poll} -l -p $port -T $max_time \
163 0.0.0.0 < "$sin" > "$sout" &
164 local spid=$!
165
166 mptcp_lib_wait_local_port_listen "${ns3}" "${port}"
167
168 ip netns exec ${ns1} \
169 ./mptcp_connect -jt ${timeout_poll} -p $port -T $max_time \
170 10.0.3.3 < "$cin" > "$cout" &
171 local cpid=$!
172
173 mptcp_lib_wait_timeout "${timeout_test}" "${ns3}" "${ns1}" "${port}" \
174 "${cpid}" "${spid}" &
175 local timeout_pid=$!
176
177 wait $cpid
178 local retc=$?
179 wait $spid
180 local rets=$?
181
182 if kill -0 $timeout_pid; then
183 # Finished before the timeout: kill the background job
184 mptcp_lib_kill_group_wait $timeout_pid
185 timeout_pid=0
186 fi
187
188 if $capture; then
189 sleep 1
190 kill ${cappid_listener}
191 kill ${cappid_connector}
192 fi
193
194 mptcp_lib_nstat_get "${ns3}"
195 mptcp_lib_nstat_get "${ns1}"
196
197 cmp $sin $cout > /dev/null 2>&1
198 local cmps=$?
199 cmp $cin $sout > /dev/null 2>&1
200 local cmpc=$?
201
202 if [ $retc -eq 0 ] && [ $rets -eq 0 ] &&
203 [ $cmpc -eq 0 ] && [ $cmps -eq 0 ] &&
204 [ $timeout_pid -eq 0 ]; then
205 printf "%-16s" " max $max_time "
206 mptcp_lib_pr_ok
207 cat "$capout"
208 return 0
209 fi
210
211 mptcp_lib_pr_fail "client exit code $retc, server $rets"
212 mptcp_lib_pr_err_stats "${ns3}" "${ns1}" "${port}"
213 ls -l $sin $cout
214 ls -l $cin $sout
215
216 cat "$capout"
217 return 1
218}
219
220run_test()
221{
222 local rate1=$1
223 local rate2=$2
224 local delay1=$3
225 local delay2=$4
226 local lret
227 local dev
228 shift 4
229 local msg=$*
230
231 [ $delay1 -gt 0 ] && delay1="delay ${delay1}ms" || delay1=""
232 [ $delay2 -gt 0 ] && delay2="delay ${delay2}ms" || delay2=""
233
234 for dev in ns1eth1 ns1eth2; do
235 tc -n $ns1 qdisc del dev $dev root >/dev/null 2>&1
236 done
237 for dev in ns2eth1 ns2eth2; do
238 tc -n $ns2 qdisc del dev $dev root >/dev/null 2>&1
239 done
240
241 # keep the queued pkts number low, or the RTT estimator will see
242 # increasing latency over time.
243 tc -n $ns1 qdisc add dev ns1eth1 root netem rate ${rate1}mbit $delay1 limit 50
244 tc -n $ns1 qdisc add dev ns1eth2 root netem rate ${rate2}mbit $delay2 limit 50
245 tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1 limit 50
246 tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2 limit 50
247
248 # time is measured in ms, account for transfer size, aggregated link speed
249 # and header overhead (10%)
250 # ms byte -> bit 10% mbit -> kbit -> bit 10%
251 local time=$((1000 * size * 8 * 10 / ((rate1 + rate2) * 1000 * 1000 * 9) ))
252
253 # mptcp_connect will do some sleeps to allow the mp_join handshake
254 # completion (see mptcp_connect): 200ms on each side, add some slack
255 time=$((time + 400 + slack))
256
257 mptcp_lib_print_title "$msg"
258 do_transfer $small $large $time
259 lret=$?
260 mptcp_lib_result_code "${lret}" "${msg}"
261 if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then
262 ret=$lret
263 [ $bail -eq 0 ] || exit $ret
264 fi
265
266 msg+=" - reverse direction"
267 mptcp_lib_print_title "${msg}"
268 do_transfer $large $small $time
269 lret=$?
270 mptcp_lib_result_code "${lret}" "${msg}"
271 if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then
272 ret=$lret
273 [ $bail -eq 0 ] || exit $ret
274 fi
275}
276
277while getopts "bcdhi" option;do
278 case "$option" in
279 "h")
280 usage $0
281 exit ${KSFT_PASS}
282 ;;
283 "b")
284 bail=1
285 ;;
286 "c")
287 capture=true
288 ;;
289 "d")
290 set -x
291 ;;
292 "i")
293 mptcp_lib_set_ip_mptcp
294 ;;
295 "?")
296 usage $0
297 exit ${KSFT_FAIL}
298 ;;
299 esac
300done
301
302setup
303mptcp_lib_subtests_last_ts_reset
304run_test 10 10 0 0 "balanced bwidth"
305run_test 10 10 1 25 "balanced bwidth with unbalanced delay"
306
307# we still need some additional infrastructure to pass the following test-cases
308MPTCP_LIB_SUBTEST_FLAKY=1 run_test 10 3 0 0 "unbalanced bwidth"
309run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay"
310run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay"
311
312mptcp_lib_result_print_all_tap
313exit $ret