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