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