]>
Commit | Line | Data |
---|---|---|
048d19d4 FW |
1 | #!/bin/bash |
2 | # SPDX-License-Identifier: GPL-2.0 | |
3 | ||
4 | time_start=$(date +%s) | |
5 | ||
767659f6 | 6 | optstring="S:R:d:e:l:r:h4cm:f:t" |
048d19d4 FW |
7 | ret=0 |
8 | sin="" | |
9 | sout="" | |
10 | cin="" | |
11 | cout="" | |
12 | ksft_skip=4 | |
13 | capture=false | |
5888a61c MB |
14 | timeout_poll=30 |
15 | timeout_test=$((timeout_poll * 2 + 1)) | |
048d19d4 FW |
16 | ipv6=true |
17 | ethtool_random_on=true | |
e5484658 | 18 | tc_delay="$((RANDOM%50))" |
048d19d4 | 19 | tc_loss=$((RANDOM%101)) |
048d19d4 FW |
20 | testmode="" |
21 | sndbuf=0 | |
8a4b910d | 22 | rcvbuf=0 |
048d19d4 | 23 | options_log=true |
767659f6 FW |
24 | do_tcp=0 |
25 | filesize=0 | |
048d19d4 FW |
26 | |
27 | if [ $tc_loss -eq 100 ];then | |
28 | tc_loss=1% | |
29 | elif [ $tc_loss -ge 10 ]; then | |
30 | tc_loss=0.$tc_loss% | |
31 | elif [ $tc_loss -ge 1 ]; then | |
32 | tc_loss=0.0$tc_loss% | |
33 | else | |
34 | tc_loss="" | |
35 | fi | |
36 | ||
37 | usage() { | |
38 | echo "Usage: $0 [ -a ]" | |
39 | echo -e "\t-d: tc/netem delay in milliseconds, e.g. \"-d 10\" (default random)" | |
40 | echo -e "\t-l: tc/netem loss percentage, e.g. \"-l 0.02\" (default random)" | |
41 | echo -e "\t-r: tc/netem reorder mode, e.g. \"-r 25% 50% gap 5\", use "-r 0" to disable reordering (default random)" | |
42 | echo -e "\t-e: ethtool features to disable, e.g.: \"-e tso -e gso\" (default: randomly disable any of tso/gso/gro)" | |
43 | echo -e "\t-4: IPv4 only: disable IPv6 tests (default: test both IPv4 and IPv6)" | |
44 | echo -e "\t-c: capture packets for each test using tcpdump (default: no capture)" | |
767659f6 | 45 | echo -e "\t-f: size of file to transfer in bytes (default random)" |
8a4b910d FW |
46 | echo -e "\t-S: set sndbuf value (default: use kernel default)" |
47 | echo -e "\t-R: set rcvbuf value (default: use kernel default)" | |
048d19d4 | 48 | echo -e "\t-m: test mode (poll, sendfile; default: poll)" |
767659f6 | 49 | echo -e "\t-t: also run tests with TCP (use twice to non-fallback tcp)" |
048d19d4 FW |
50 | } |
51 | ||
52 | while getopts "$optstring" option;do | |
53 | case "$option" in | |
54 | "h") | |
55 | usage $0 | |
56 | exit 0 | |
57 | ;; | |
58 | "d") | |
59 | if [ $OPTARG -ge 0 ];then | |
60 | tc_delay="$OPTARG" | |
61 | else | |
62 | echo "-d requires numeric argument, got \"$OPTARG\"" 1>&2 | |
63 | exit 1 | |
64 | fi | |
65 | ;; | |
66 | "e") | |
67 | ethtool_args="$ethtool_args $OPTARG off" | |
68 | ethtool_random_on=false | |
69 | ;; | |
70 | "l") | |
71 | tc_loss="$OPTARG" | |
72 | ;; | |
73 | "r") | |
74 | tc_reorder="$OPTARG" | |
75 | ;; | |
76 | "4") | |
77 | ipv6=false | |
78 | ;; | |
79 | "c") | |
80 | capture=true | |
81 | ;; | |
8a4b910d | 82 | "S") |
048d19d4 FW |
83 | if [ $OPTARG -ge 0 ];then |
84 | sndbuf="$OPTARG" | |
85 | else | |
8a4b910d FW |
86 | echo "-S requires numeric argument, got \"$OPTARG\"" 1>&2 |
87 | exit 1 | |
88 | fi | |
89 | ;; | |
90 | "R") | |
91 | if [ $OPTARG -ge 0 ];then | |
92 | rcvbuf="$OPTARG" | |
93 | else | |
94 | echo "-R requires numeric argument, got \"$OPTARG\"" 1>&2 | |
048d19d4 FW |
95 | exit 1 |
96 | fi | |
97 | ;; | |
98 | "m") | |
99 | testmode="$OPTARG" | |
100 | ;; | |
767659f6 FW |
101 | "f") |
102 | filesize="$OPTARG" | |
103 | ;; | |
104 | "t") | |
105 | do_tcp=$((do_tcp+1)) | |
106 | ;; | |
048d19d4 FW |
107 | "?") |
108 | usage $0 | |
109 | exit 1 | |
110 | ;; | |
111 | esac | |
112 | done | |
113 | ||
114 | sec=$(date +%s) | |
115 | rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) | |
116 | ns1="ns1-$rndh" | |
117 | ns2="ns2-$rndh" | |
118 | ns3="ns3-$rndh" | |
119 | ns4="ns4-$rndh" | |
120 | ||
121 | TEST_COUNT=0 | |
122 | ||
123 | cleanup() | |
124 | { | |
125 | rm -f "$cin" "$cout" | |
126 | rm -f "$sin" "$sout" | |
127 | rm -f "$capout" | |
128 | ||
129 | local netns | |
130 | for netns in "$ns1" "$ns2" "$ns3" "$ns4";do | |
131 | ip netns del $netns | |
767389c8 | 132 | rm -f /tmp/$netns.{nstat,out} |
048d19d4 FW |
133 | done |
134 | } | |
135 | ||
136 | ip -Version > /dev/null 2>&1 | |
137 | if [ $? -ne 0 ];then | |
138 | echo "SKIP: Could not run test without ip tool" | |
139 | exit $ksft_skip | |
140 | fi | |
141 | ||
142 | sin=$(mktemp) | |
143 | sout=$(mktemp) | |
144 | cin=$(mktemp) | |
145 | cout=$(mktemp) | |
146 | capout=$(mktemp) | |
147 | trap cleanup EXIT | |
148 | ||
149 | for i in "$ns1" "$ns2" "$ns3" "$ns4";do | |
150 | ip netns add $i || exit $ksft_skip | |
151 | ip -net $i link set lo up | |
152 | done | |
153 | ||
154 | # "$ns1" ns2 ns3 ns4 | |
155 | # ns1eth2 ns2eth1 ns2eth3 ns3eth2 ns3eth4 ns4eth3 | |
156 | # - drop 1% -> reorder 25% | |
157 | # <- TSO off - | |
158 | ||
159 | ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth1 netns "$ns2" | |
160 | ip link add ns2eth3 netns "$ns2" type veth peer name ns3eth2 netns "$ns3" | |
161 | ip link add ns3eth4 netns "$ns3" type veth peer name ns4eth3 netns "$ns4" | |
162 | ||
163 | ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth2 | |
164 | ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth2 nodad | |
165 | ||
166 | ip -net "$ns1" link set ns1eth2 up | |
167 | ip -net "$ns1" route add default via 10.0.1.2 | |
168 | ip -net "$ns1" route add default via dead:beef:1::2 | |
169 | ||
170 | ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1 | |
171 | ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad | |
172 | ip -net "$ns2" link set ns2eth1 up | |
173 | ||
174 | ip -net "$ns2" addr add 10.0.2.1/24 dev ns2eth3 | |
175 | ip -net "$ns2" addr add dead:beef:2::1/64 dev ns2eth3 nodad | |
176 | ip -net "$ns2" link set ns2eth3 up | |
177 | ip -net "$ns2" route add default via 10.0.2.2 | |
178 | ip -net "$ns2" route add default via dead:beef:2::2 | |
179 | ip netns exec "$ns2" sysctl -q net.ipv4.ip_forward=1 | |
180 | ip netns exec "$ns2" sysctl -q net.ipv6.conf.all.forwarding=1 | |
181 | ||
182 | ip -net "$ns3" addr add 10.0.2.2/24 dev ns3eth2 | |
183 | ip -net "$ns3" addr add dead:beef:2::2/64 dev ns3eth2 nodad | |
184 | ip -net "$ns3" link set ns3eth2 up | |
185 | ||
186 | ip -net "$ns3" addr add 10.0.3.2/24 dev ns3eth4 | |
187 | ip -net "$ns3" addr add dead:beef:3::2/64 dev ns3eth4 nodad | |
188 | ip -net "$ns3" link set ns3eth4 up | |
189 | ip -net "$ns3" route add default via 10.0.2.1 | |
190 | ip -net "$ns3" route add default via dead:beef:2::1 | |
191 | ip netns exec "$ns3" sysctl -q net.ipv4.ip_forward=1 | |
192 | ip netns exec "$ns3" sysctl -q net.ipv6.conf.all.forwarding=1 | |
193 | ||
194 | ip -net "$ns4" addr add 10.0.3.1/24 dev ns4eth3 | |
195 | ip -net "$ns4" addr add dead:beef:3::1/64 dev ns4eth3 nodad | |
196 | ip -net "$ns4" link set ns4eth3 up | |
197 | ip -net "$ns4" route add default via 10.0.3.2 | |
198 | ip -net "$ns4" route add default via dead:beef:3::2 | |
199 | ||
fed61c4b FW |
200 | # use TCP syn cookies, even if no flooding was detected. |
201 | ip netns exec "$ns2" sysctl -q net.ipv4.tcp_syncookies=2 | |
202 | ||
048d19d4 FW |
203 | set_ethtool_flags() { |
204 | local ns="$1" | |
205 | local dev="$2" | |
206 | local flags="$3" | |
207 | ||
208 | ip netns exec $ns ethtool -K $dev $flags 2>/dev/null | |
209 | [ $? -eq 0 ] && echo "INFO: set $ns dev $dev: ethtool -K $flags" | |
210 | } | |
211 | ||
212 | set_random_ethtool_flags() { | |
213 | local flags="" | |
214 | local r=$RANDOM | |
215 | ||
216 | local pick1=$((r & 1)) | |
217 | local pick2=$((r & 2)) | |
218 | local pick3=$((r & 4)) | |
219 | ||
220 | [ $pick1 -ne 0 ] && flags="tso off" | |
221 | [ $pick2 -ne 0 ] && flags="$flags gso off" | |
222 | [ $pick3 -ne 0 ] && flags="$flags gro off" | |
223 | ||
224 | [ -z "$flags" ] && return | |
225 | ||
226 | set_ethtool_flags "$1" "$2" "$flags" | |
227 | } | |
228 | ||
229 | if $ethtool_random_on;then | |
230 | set_random_ethtool_flags "$ns3" ns3eth2 | |
231 | set_random_ethtool_flags "$ns4" ns4eth3 | |
232 | else | |
233 | set_ethtool_flags "$ns3" ns3eth2 "$ethtool_args" | |
234 | set_ethtool_flags "$ns4" ns4eth3 "$ethtool_args" | |
235 | fi | |
236 | ||
237 | print_file_err() | |
238 | { | |
239 | ls -l "$1" 1>&2 | |
240 | echo "Trailing bytes are: " | |
241 | tail -c 27 "$1" | |
242 | } | |
243 | ||
244 | check_transfer() | |
245 | { | |
246 | local in=$1 | |
247 | local out=$2 | |
248 | local what=$3 | |
249 | ||
250 | cmp "$in" "$out" > /dev/null 2>&1 | |
251 | if [ $? -ne 0 ] ;then | |
252 | echo "[ FAIL ] $what does not match (in, out):" | |
253 | print_file_err "$in" | |
254 | print_file_err "$out" | |
255 | ||
256 | return 1 | |
257 | fi | |
258 | ||
259 | return 0 | |
260 | } | |
261 | ||
262 | check_mptcp_disabled() | |
263 | { | |
264 | local disabled_ns | |
265 | disabled_ns="ns_disabled-$sech-$(mktemp -u XXXXXX)" | |
266 | ip netns add ${disabled_ns} || exit $ksft_skip | |
267 | ||
268 | # net.mptcp.enabled should be enabled by default | |
269 | if [ "$(ip netns exec ${disabled_ns} sysctl net.mptcp.enabled | awk '{ print $3 }')" -ne 1 ]; then | |
270 | echo -e "net.mptcp.enabled sysctl is not 1 by default\t\t[ FAIL ]" | |
271 | ret=1 | |
272 | return 1 | |
273 | fi | |
274 | ip netns exec ${disabled_ns} sysctl -q net.mptcp.enabled=0 | |
275 | ||
276 | local err=0 | |
77a88274 | 277 | LC_ALL=C ip netns exec ${disabled_ns} ./mptcp_connect -p 10000 -s MPTCP 127.0.0.1 < "$cin" 2>&1 | \ |
048d19d4 FW |
278 | grep -q "^socket: Protocol not available$" && err=1 |
279 | ip netns delete ${disabled_ns} | |
280 | ||
281 | if [ ${err} -eq 0 ]; then | |
282 | echo -e "New MPTCP socket cannot be blocked via sysctl\t\t[ FAIL ]" | |
283 | ret=1 | |
284 | return 1 | |
285 | fi | |
286 | ||
287 | echo -e "New MPTCP socket can be blocked via sysctl\t\t[ OK ]" | |
288 | return 0 | |
289 | } | |
290 | ||
291 | check_mptcp_ulp_setsockopt() | |
292 | { | |
293 | local t retval | |
294 | t="ns_ulp-$sech-$(mktemp -u XXXXXX)" | |
295 | ||
296 | ip netns add ${t} || exit $ksft_skip | |
297 | if ! ip netns exec ${t} ./mptcp_connect -u -p 10000 -s TCP 127.0.0.1 2>&1; then | |
298 | printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) allowed\t[ FAIL ]\n" | |
299 | retval=1 | |
300 | ret=$retval | |
301 | else | |
302 | printf "setsockopt(..., TCP_ULP, \"mptcp\", ...) blocked\t[ OK ]\n" | |
303 | retval=0 | |
304 | fi | |
305 | ip netns del ${t} | |
306 | return $retval | |
307 | } | |
308 | ||
309 | # $1: IP address | |
310 | is_v6() | |
311 | { | |
312 | [ -z "${1##*:*}" ] | |
313 | } | |
314 | ||
315 | do_ping() | |
316 | { | |
317 | local listener_ns="$1" | |
318 | local connector_ns="$2" | |
319 | local connect_addr="$3" | |
320 | local ping_args="-q -c 1" | |
321 | ||
322 | if is_v6 "${connect_addr}"; then | |
323 | $ipv6 || return 0 | |
324 | ping_args="${ping_args} -6" | |
325 | fi | |
326 | ||
327 | ip netns exec ${connector_ns} ping ${ping_args} $connect_addr >/dev/null | |
328 | if [ $? -ne 0 ] ; then | |
329 | echo "$listener_ns -> $connect_addr connectivity [ FAIL ]" 1>&2 | |
330 | ret=1 | |
331 | ||
332 | return 1 | |
333 | fi | |
334 | ||
335 | return 0 | |
336 | } | |
337 | ||
45759a87 MB |
338 | # $1: ns, $2: MIB counter |
339 | get_mib_counter() | |
340 | { | |
341 | local listener_ns="${1}" | |
342 | local mib="${2}" | |
343 | ||
344 | # strip the header | |
345 | ip netns exec "${listener_ns}" \ | |
346 | nstat -z -a "${mib}" | \ | |
347 | tail -n+2 | \ | |
348 | while read a count c rest; do | |
349 | echo $count | |
350 | done | |
351 | } | |
352 | ||
048d19d4 FW |
353 | # $1: ns, $2: port |
354 | wait_local_port_listen() | |
355 | { | |
356 | local listener_ns="${1}" | |
357 | local port="${2}" | |
358 | ||
359 | local port_hex i | |
360 | ||
361 | port_hex="$(printf "%04X" "${port}")" | |
362 | for i in $(seq 10); do | |
363 | ip netns exec "${listener_ns}" cat /proc/net/tcp* | \ | |
364 | awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && | |
365 | break | |
366 | sleep 0.1 | |
367 | done | |
368 | } | |
369 | ||
370 | do_transfer() | |
371 | { | |
372 | local listener_ns="$1" | |
373 | local connector_ns="$2" | |
374 | local cl_proto="$3" | |
375 | local srv_proto="$4" | |
376 | local connect_addr="$5" | |
377 | local local_addr="$6" | |
df8aee6d | 378 | local extra_args="$7" |
048d19d4 FW |
379 | |
380 | local port | |
381 | port=$((10000+$TEST_COUNT)) | |
382 | TEST_COUNT=$((TEST_COUNT+1)) | |
383 | ||
8a4b910d FW |
384 | if [ "$rcvbuf" -gt 0 ]; then |
385 | extra_args="$extra_args -R $rcvbuf" | |
386 | fi | |
387 | ||
048d19d4 | 388 | if [ "$sndbuf" -gt 0 ]; then |
8a4b910d | 389 | extra_args="$extra_args -S $sndbuf" |
048d19d4 FW |
390 | fi |
391 | ||
392 | if [ -n "$testmode" ]; then | |
393 | extra_args="$extra_args -m $testmode" | |
394 | fi | |
395 | ||
396 | if [ -n "$extra_args" ] && $options_log; then | |
048d19d4 FW |
397 | echo "INFO: extra options: $extra_args" |
398 | fi | |
df8aee6d | 399 | options_log=false |
048d19d4 FW |
400 | |
401 | :> "$cout" | |
402 | :> "$sout" | |
403 | :> "$capout" | |
404 | ||
405 | local addr_port | |
406 | addr_port=$(printf "%s:%d" ${connect_addr} ${port}) | |
407 | printf "%.3s %-5s -> %.3s (%-20s) %-5s\t" ${connector_ns} ${cl_proto} ${listener_ns} ${addr_port} ${srv_proto} | |
408 | ||
409 | if $capture; then | |
410 | local capuser | |
411 | if [ -z $SUDO_USER ] ; then | |
412 | capuser="" | |
413 | else | |
414 | capuser="-Z $SUDO_USER" | |
415 | fi | |
416 | ||
0b8241fe MB |
417 | local capfile="${rndh}-${connector_ns:0:3}-${listener_ns:0:3}-${cl_proto}-${srv_proto}-${connect_addr}-${port}" |
418 | local capopt="-i any -s 65535 -B 32768 ${capuser}" | |
048d19d4 | 419 | |
0b8241fe MB |
420 | ip netns exec ${listener_ns} tcpdump ${capopt} -w "${capfile}-listener.pcap" >> "${capout}" 2>&1 & |
421 | local cappid_listener=$! | |
422 | ||
423 | ip netns exec ${connector_ns} tcpdump ${capopt} -w "${capfile}-connector.pcap" >> "${capout}" 2>&1 & | |
424 | local cappid_connector=$! | |
048d19d4 FW |
425 | |
426 | sleep 1 | |
427 | fi | |
428 | ||
76e5e27c MB |
429 | NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \ |
430 | nstat -n | |
431 | if [ ${listener_ns} != ${connector_ns} ]; then | |
432 | NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \ | |
433 | nstat -n | |
434 | fi | |
435 | ||
45759a87 MB |
436 | local stat_synrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX") |
437 | local stat_ackrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX") | |
438 | local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent") | |
439 | local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv") | |
fed61c4b | 440 | |
5888a61c MB |
441 | timeout ${timeout_test} \ |
442 | ip netns exec ${listener_ns} \ | |
443 | ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ | |
444 | $extra_args $local_addr < "$sin" > "$sout" & | |
048d19d4 FW |
445 | local spid=$! |
446 | ||
447 | wait_local_port_listen "${listener_ns}" "${port}" | |
448 | ||
449 | local start | |
450 | start=$(date +%s%3N) | |
5888a61c MB |
451 | timeout ${timeout_test} \ |
452 | ip netns exec ${connector_ns} \ | |
453 | ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ | |
454 | $extra_args $connect_addr < "$cin" > "$cout" & | |
048d19d4 FW |
455 | local cpid=$! |
456 | ||
457 | wait $cpid | |
458 | local retc=$? | |
459 | wait $spid | |
460 | local rets=$? | |
461 | ||
462 | local stop | |
463 | stop=$(date +%s%3N) | |
464 | ||
465 | if $capture; then | |
466 | sleep 1 | |
0b8241fe MB |
467 | kill ${cappid_listener} |
468 | kill ${cappid_connector} | |
048d19d4 FW |
469 | fi |
470 | ||
767389c8 PA |
471 | NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \ |
472 | nstat | grep Tcp > /tmp/${listener_ns}.out | |
473 | if [ ${listener_ns} != ${connector_ns} ]; then | |
474 | NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \ | |
475 | nstat | grep Tcp > /tmp/${connector_ns}.out | |
476 | fi | |
477 | ||
048d19d4 FW |
478 | local duration |
479 | duration=$((stop-start)) | |
45759a87 | 480 | printf "(duration %05sms) " "${duration}" |
048d19d4 | 481 | if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then |
45759a87 | 482 | echo "[ FAIL ] client exit code $retc, server $rets" 1>&2 |
8b974778 | 483 | echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2 |
767389c8 PA |
484 | ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port" |
485 | cat /tmp/${listener_ns}.out | |
8b974778 | 486 | echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2 |
767389c8 PA |
487 | ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port" |
488 | [ ${listener_ns} != ${connector_ns} ] && cat /tmp/${connector_ns}.out | |
45759a87 MB |
489 | |
490 | echo | |
048d19d4 FW |
491 | cat "$capout" |
492 | return 1 | |
493 | fi | |
494 | ||
495 | check_transfer $sin $cout "file received by client" | |
496 | retc=$? | |
497 | check_transfer $cin $sout "file received by server" | |
498 | rets=$? | |
499 | ||
45759a87 MB |
500 | local stat_synrx_now_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX") |
501 | local stat_ackrx_now_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX") | |
502 | local stat_cookietx_now=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent") | |
503 | local stat_cookierx_now=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv") | |
69ca3d29 | 504 | local stat_ooo_now=$(get_mib_counter "${listener_ns}" "TcpExtTCPOFOQueue") |
fed61c4b FW |
505 | |
506 | expect_synrx=$((stat_synrx_last_l)) | |
507 | expect_ackrx=$((stat_ackrx_last_l)) | |
508 | ||
509 | cookies=$(ip netns exec ${listener_ns} sysctl net.ipv4.tcp_syncookies) | |
510 | cookies=${cookies##*=} | |
511 | ||
512 | if [ ${cl_proto} = "MPTCP" ] && [ ${srv_proto} = "MPTCP" ]; then | |
513 | expect_synrx=$((stat_synrx_last_l+1)) | |
514 | expect_ackrx=$((stat_ackrx_last_l+1)) | |
515 | fi | |
5f88117f MB |
516 | |
517 | if [ ${stat_synrx_now_l} -lt ${expect_synrx} ]; then | |
518 | printf "[ FAIL ] lower MPC SYN rx (%d) than expected (%d)\n" \ | |
519 | "${stat_synrx_now_l}" "${expect_synrx}" 1>&2 | |
520 | retc=1 | |
521 | fi | |
69ca3d29 PA |
522 | if [ ${stat_ackrx_now_l} -lt ${expect_ackrx} -a ${stat_ooo_now} -eq 0 ]; then |
523 | if [ ${stat_ooo_now} -eq 0 ]; then | |
524 | printf "[ FAIL ] lower MPC ACK rx (%d) than expected (%d)\n" \ | |
525 | "${stat_ackrx_now_l}" "${expect_ackrx}" 1>&2 | |
526 | rets=1 | |
527 | else | |
528 | printf "[ Note ] fallback due to TCP OoO" | |
529 | fi | |
5f88117f MB |
530 | fi |
531 | ||
532 | if [ $retc -eq 0 ] && [ $rets -eq 0 ]; then | |
533 | printf "[ OK ]" | |
534 | fi | |
535 | ||
fed61c4b FW |
536 | if [ $cookies -eq 2 ];then |
537 | if [ $stat_cookietx_last -ge $stat_cookietx_now ] ;then | |
45759a87 | 538 | printf " WARN: CookieSent: did not advance" |
fed61c4b FW |
539 | fi |
540 | if [ $stat_cookierx_last -ge $stat_cookierx_now ] ;then | |
45759a87 | 541 | printf " WARN: CookieRecv: did not advance" |
fed61c4b FW |
542 | fi |
543 | else | |
544 | if [ $stat_cookietx_last -ne $stat_cookietx_now ] ;then | |
45759a87 | 545 | printf " WARN: CookieSent: changed" |
fed61c4b FW |
546 | fi |
547 | if [ $stat_cookierx_last -ne $stat_cookierx_now ] ;then | |
45759a87 | 548 | printf " WARN: CookieRecv: changed" |
fed61c4b FW |
549 | fi |
550 | fi | |
551 | ||
5f88117f MB |
552 | if [ ${stat_synrx_now_l} -gt ${expect_synrx} ]; then |
553 | printf " WARN: SYNRX: expect %d, got %d (probably retransmissions)" \ | |
45759a87 | 554 | "${expect_synrx}" "${stat_synrx_now_l}" |
fed61c4b | 555 | fi |
5f88117f MB |
556 | if [ ${stat_ackrx_now_l} -gt ${expect_ackrx} ]; then |
557 | printf " WARN: ACKRX: expect %d, got %d (probably retransmissions)" \ | |
45759a87 | 558 | "${expect_ackrx}" "${stat_ackrx_now_l}" |
048d19d4 FW |
559 | fi |
560 | ||
45759a87 | 561 | echo |
048d19d4 | 562 | cat "$capout" |
45759a87 | 563 | [ $retc -eq 0 ] && [ $rets -eq 0 ] |
048d19d4 FW |
564 | } |
565 | ||
566 | make_file() | |
567 | { | |
568 | local name=$1 | |
569 | local who=$2 | |
767659f6 FW |
570 | local SIZE=$filesize |
571 | local ksize | |
572 | local rem | |
048d19d4 | 573 | |
767659f6 FW |
574 | if [ $SIZE -eq 0 ]; then |
575 | local MAXSIZE=$((1024 * 1024 * 8)) | |
576 | local MINSIZE=$((1024 * 256)) | |
048d19d4 | 577 | |
767659f6 FW |
578 | SIZE=$(((RANDOM * RANDOM + MINSIZE) % MAXSIZE)) |
579 | fi | |
048d19d4 | 580 | |
767659f6 FW |
581 | ksize=$((SIZE / 1024)) |
582 | rem=$((SIZE - (ksize * 1024))) | |
583 | ||
584 | dd if=/dev/urandom of="$name" bs=1024 count=$ksize 2> /dev/null | |
585 | dd if=/dev/urandom conv=notrunc of="$name" bs=1 count=$rem 2> /dev/null | |
048d19d4 FW |
586 | echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name" |
587 | ||
767659f6 | 588 | echo "Created $name (size $(du -b "$name")) containing data sent by $who" |
048d19d4 FW |
589 | } |
590 | ||
591 | run_tests_lo() | |
592 | { | |
593 | local listener_ns="$1" | |
594 | local connector_ns="$2" | |
595 | local connect_addr="$3" | |
596 | local loopback="$4" | |
df8aee6d | 597 | local extra_args="$5" |
048d19d4 FW |
598 | local lret=0 |
599 | ||
600 | # skip if test programs are running inside same netns for subsequent runs. | |
601 | if [ $loopback -eq 0 ] && [ ${listener_ns} = ${connector_ns} ]; then | |
602 | return 0 | |
603 | fi | |
604 | ||
605 | # skip if we don't want v6 | |
606 | if ! $ipv6 && is_v6 "${connect_addr}"; then | |
607 | return 0 | |
608 | fi | |
609 | ||
610 | local local_addr | |
611 | if is_v6 "${connect_addr}"; then | |
612 | local_addr="::" | |
613 | else | |
614 | local_addr="0.0.0.0" | |
615 | fi | |
616 | ||
df8aee6d YL |
617 | do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP \ |
618 | ${connect_addr} ${local_addr} "${extra_args}" | |
048d19d4 FW |
619 | lret=$? |
620 | if [ $lret -ne 0 ]; then | |
621 | ret=$lret | |
622 | return 1 | |
623 | fi | |
624 | ||
767659f6 FW |
625 | if [ $do_tcp -eq 0 ]; then |
626 | # don't bother testing fallback tcp except for loopback case. | |
627 | if [ ${listener_ns} != ${connector_ns} ]; then | |
628 | return 0 | |
629 | fi | |
048d19d4 FW |
630 | fi |
631 | ||
df8aee6d YL |
632 | do_transfer ${listener_ns} ${connector_ns} MPTCP TCP \ |
633 | ${connect_addr} ${local_addr} "${extra_args}" | |
048d19d4 FW |
634 | lret=$? |
635 | if [ $lret -ne 0 ]; then | |
636 | ret=$lret | |
637 | return 1 | |
638 | fi | |
639 | ||
df8aee6d YL |
640 | do_transfer ${listener_ns} ${connector_ns} TCP MPTCP \ |
641 | ${connect_addr} ${local_addr} "${extra_args}" | |
048d19d4 FW |
642 | lret=$? |
643 | if [ $lret -ne 0 ]; then | |
644 | ret=$lret | |
645 | return 1 | |
646 | fi | |
647 | ||
767659f6 | 648 | if [ $do_tcp -gt 1 ] ;then |
df8aee6d YL |
649 | do_transfer ${listener_ns} ${connector_ns} TCP TCP \ |
650 | ${connect_addr} ${local_addr} "${extra_args}" | |
767659f6 FW |
651 | lret=$? |
652 | if [ $lret -ne 0 ]; then | |
653 | ret=$lret | |
654 | return 1 | |
655 | fi | |
656 | fi | |
657 | ||
048d19d4 FW |
658 | return 0 |
659 | } | |
660 | ||
661 | run_tests() | |
662 | { | |
663 | run_tests_lo $1 $2 $3 0 | |
664 | } | |
665 | ||
df8aee6d YL |
666 | run_tests_peekmode() |
667 | { | |
668 | local peekmode="$1" | |
669 | ||
670 | echo "INFO: with peek mode: ${peekmode}" | |
671 | run_tests_lo "$ns1" "$ns1" 10.0.1.1 1 "-P ${peekmode}" | |
672 | run_tests_lo "$ns1" "$ns1" dead:beef:1::1 1 "-P ${peekmode}" | |
673 | } | |
674 | ||
048d19d4 FW |
675 | make_file "$cin" "client" |
676 | make_file "$sin" "server" | |
677 | ||
678 | check_mptcp_disabled | |
679 | ||
680 | check_mptcp_ulp_setsockopt | |
681 | ||
682 | echo "INFO: validating network environment with pings" | |
683 | for sender in "$ns1" "$ns2" "$ns3" "$ns4";do | |
684 | do_ping "$ns1" $sender 10.0.1.1 | |
685 | do_ping "$ns1" $sender dead:beef:1::1 | |
686 | ||
687 | do_ping "$ns2" $sender 10.0.1.2 | |
688 | do_ping "$ns2" $sender dead:beef:1::2 | |
689 | do_ping "$ns2" $sender 10.0.2.1 | |
690 | do_ping "$ns2" $sender dead:beef:2::1 | |
691 | ||
692 | do_ping "$ns3" $sender 10.0.2.2 | |
693 | do_ping "$ns3" $sender dead:beef:2::2 | |
694 | do_ping "$ns3" $sender 10.0.3.2 | |
695 | do_ping "$ns3" $sender dead:beef:3::2 | |
696 | ||
697 | do_ping "$ns4" $sender 10.0.3.1 | |
698 | do_ping "$ns4" $sender dead:beef:3::1 | |
699 | done | |
700 | ||
e5484658 | 701 | [ -n "$tc_loss" ] && tc -net "$ns2" qdisc add dev ns2eth3 root netem loss random $tc_loss delay ${tc_delay}ms |
048d19d4 FW |
702 | echo -n "INFO: Using loss of $tc_loss " |
703 | test "$tc_delay" -gt 0 && echo -n "delay $tc_delay ms " | |
704 | ||
e5484658 CP |
705 | reorder_delay=$(($tc_delay / 4)) |
706 | ||
048d19d4 FW |
707 | if [ -z "${tc_reorder}" ]; then |
708 | reorder1=$((RANDOM%10)) | |
709 | reorder1=$((100 - reorder1)) | |
710 | reorder2=$((RANDOM%100)) | |
711 | ||
e5484658 | 712 | if [ $reorder_delay -gt 0 ] && [ $reorder1 -lt 100 ] && [ $reorder2 -gt 0 ]; then |
048d19d4 | 713 | tc_reorder="reorder ${reorder1}% ${reorder2}%" |
e5484658 | 714 | echo -n "$tc_reorder with delay ${reorder_delay}ms " |
048d19d4 FW |
715 | fi |
716 | elif [ "$tc_reorder" = "0" ];then | |
717 | tc_reorder="" | |
e5484658 | 718 | elif [ "$reorder_delay" -gt 0 ];then |
048d19d4 FW |
719 | # reordering requires some delay |
720 | tc_reorder="reorder $tc_reorder" | |
e5484658 | 721 | echo -n "$tc_reorder with delay ${reorder_delay}ms " |
048d19d4 FW |
722 | fi |
723 | ||
724 | echo "on ns3eth4" | |
725 | ||
e5484658 | 726 | tc -net "$ns3" qdisc add dev ns3eth4 root netem delay ${reorder_delay}ms $tc_reorder |
048d19d4 FW |
727 | |
728 | for sender in $ns1 $ns2 $ns3 $ns4;do | |
729 | run_tests_lo "$ns1" "$sender" 10.0.1.1 1 | |
730 | if [ $ret -ne 0 ] ;then | |
731 | echo "FAIL: Could not even run loopback test" 1>&2 | |
732 | exit $ret | |
733 | fi | |
734 | run_tests_lo "$ns1" $sender dead:beef:1::1 1 | |
735 | if [ $ret -ne 0 ] ;then | |
736 | echo "FAIL: Could not even run loopback v6 test" 2>&1 | |
737 | exit $ret | |
738 | fi | |
739 | ||
740 | run_tests "$ns2" $sender 10.0.1.2 | |
741 | run_tests "$ns2" $sender dead:beef:1::2 | |
742 | run_tests "$ns2" $sender 10.0.2.1 | |
743 | run_tests "$ns2" $sender dead:beef:2::1 | |
744 | ||
745 | run_tests "$ns3" $sender 10.0.2.2 | |
746 | run_tests "$ns3" $sender dead:beef:2::2 | |
747 | run_tests "$ns3" $sender 10.0.3.2 | |
748 | run_tests "$ns3" $sender dead:beef:3::2 | |
749 | ||
750 | run_tests "$ns4" $sender 10.0.3.1 | |
751 | run_tests "$ns4" $sender dead:beef:3::1 | |
752 | done | |
753 | ||
df8aee6d YL |
754 | run_tests_peekmode "saveWithPeek" |
755 | run_tests_peekmode "saveAfterPeek" | |
756 | ||
048d19d4 FW |
757 | time_end=$(date +%s) |
758 | time_run=$((time_end-time_start)) | |
759 | ||
760 | echo "Time: ${time_run} seconds" | |
761 | ||
762 | exit $ret |