selftests: mptcp: add MP_FAIL reset testcase
[platform/kernel/linux-rpi.git] / tools / testing / selftests / net / mptcp / mptcp_join.sh
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 ret=0
10 sin=""
11 sinfail=""
12 sout=""
13 cin=""
14 cinfail=""
15 cinsent=""
16 cout=""
17 capout=""
18 ns1=""
19 ns2=""
20 ksft_skip=4
21 timeout_poll=30
22 timeout_test=$((timeout_poll * 2 + 1))
23 capture=0
24 checksum=0
25 ip_mptcp=0
26 check_invert=0
27 validate_checksum=0
28 init=0
29
30 declare -A all_tests
31 declare -a only_tests_ids
32 declare -a only_tests_names
33 declare -A failed_tests
34 TEST_COUNT=0
35 TEST_NAME=""
36 nr_blank=40
37
38 export FAILING_LINKS=""
39
40 # generated using "nfbpf_compile '(ip && (ip[54] & 0xf0) == 0x30) ||
41 #                                 (ip6 && (ip6[74] & 0xf0) == 0x30)'"
42 CBPF_MPTCP_SUBOPTION_ADD_ADDR="14,
43                                48 0 0 0,
44                                84 0 0 240,
45                                21 0 3 64,
46                                48 0 0 54,
47                                84 0 0 240,
48                                21 6 7 48,
49                                48 0 0 0,
50                                84 0 0 240,
51                                21 0 4 96,
52                                48 0 0 74,
53                                84 0 0 240,
54                                21 0 1 48,
55                                6 0 0 65535,
56                                6 0 0 0"
57
58 init_partial()
59 {
60         capout=$(mktemp)
61
62         local rndh
63         rndh=$(mktemp -u XXXXXX)
64
65         ns1="ns1-$rndh"
66         ns2="ns2-$rndh"
67
68         local netns
69         for netns in "$ns1" "$ns2"; do
70                 ip netns add $netns || exit $ksft_skip
71                 ip -net $netns link set lo up
72                 ip netns exec $netns sysctl -q net.mptcp.enabled=1
73                 ip netns exec $netns sysctl -q net.mptcp.pm_type=0
74                 ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0
75                 ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0
76                 if [ $checksum -eq 1 ]; then
77                         ip netns exec $netns sysctl -q net.mptcp.checksum_enabled=1
78                 fi
79         done
80
81         check_invert=0
82         validate_checksum=$checksum
83         FAILING_LINKS=""
84
85         #  ns1         ns2
86         # ns1eth1    ns2eth1
87         # ns1eth2    ns2eth2
88         # ns1eth3    ns2eth3
89         # ns1eth4    ns2eth4
90
91         local i
92         for i in $(seq 1 4); do
93                 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2"
94                 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i
95                 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad
96                 ip -net "$ns1" link set ns1eth$i up
97
98                 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i
99                 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad
100                 ip -net "$ns2" link set ns2eth$i up
101
102                 # let $ns2 reach any $ns1 address from any interface
103                 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i
104                 ip -net "$ns2" route add default via dead:beef:$i::1 dev ns2eth$i metric 10$i
105         done
106 }
107
108 init_shapers()
109 {
110         local i
111         for i in $(seq 1 4); do
112                 tc -n $ns1 qdisc add dev ns1eth$i root netem rate 20mbit delay 1
113                 tc -n $ns2 qdisc add dev ns2eth$i root netem rate 20mbit delay 1
114         done
115 }
116
117 cleanup_partial()
118 {
119         rm -f "$capout"
120
121         local netns
122         for netns in "$ns1" "$ns2"; do
123                 ip netns del $netns
124                 rm -f /tmp/$netns.{nstat,out}
125         done
126 }
127
128 check_tools()
129 {
130         if ! ip -Version &> /dev/null; then
131                 echo "SKIP: Could not run test without ip tool"
132                 exit $ksft_skip
133         fi
134
135         if ! iptables -V &> /dev/null; then
136                 echo "SKIP: Could not run all tests without iptables tool"
137                 exit $ksft_skip
138         fi
139
140         if ! ip6tables -V &> /dev/null; then
141                 echo "SKIP: Could not run all tests without ip6tables tool"
142                 exit $ksft_skip
143         fi
144 }
145
146 init() {
147         init=1
148
149         check_tools
150
151         sin=$(mktemp)
152         sout=$(mktemp)
153         cin=$(mktemp)
154         cinsent=$(mktemp)
155         cout=$(mktemp)
156
157         trap cleanup EXIT
158
159         make_file "$cin" "client" 1
160         make_file "$sin" "server" 1
161 }
162
163 cleanup()
164 {
165         rm -f "$cin" "$cout" "$sinfail"
166         rm -f "$sin" "$sout" "$cinsent" "$cinfail"
167         cleanup_partial
168 }
169
170 skip_test()
171 {
172         if [ "${#only_tests_ids[@]}" -eq 0 ] && [ "${#only_tests_names[@]}" -eq 0 ]; then
173                 return 1
174         fi
175
176         local i
177         for i in "${only_tests_ids[@]}"; do
178                 if [ "${TEST_COUNT}" -eq "${i}" ]; then
179                         return 1
180                 fi
181         done
182         for i in "${only_tests_names[@]}"; do
183                 if [ "${TEST_NAME}" = "${i}" ]; then
184                         return 1
185                 fi
186         done
187
188         return 0
189 }
190
191 # $1: test name
192 reset()
193 {
194         TEST_NAME="${1}"
195
196         TEST_COUNT=$((TEST_COUNT+1))
197
198         if skip_test; then
199                 return 1
200         fi
201
202         if [ "${init}" != "1" ]; then
203                 init
204         else
205                 cleanup_partial
206         fi
207
208         init_partial
209
210         return 0
211 }
212
213 # $1: test name
214 reset_with_cookies()
215 {
216         reset "${1}" || return 1
217
218         local netns
219         for netns in "$ns1" "$ns2"; do
220                 ip netns exec $netns sysctl -q net.ipv4.tcp_syncookies=2
221         done
222 }
223
224 # $1: test name
225 reset_with_add_addr_timeout()
226 {
227         local ip="${2:-4}"
228         local tables
229
230         reset "${1}" || return 1
231
232         tables="iptables"
233         if [ $ip -eq 6 ]; then
234                 tables="ip6tables"
235         fi
236
237         ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
238         ip netns exec $ns2 $tables -A OUTPUT -p tcp \
239                 -m tcp --tcp-option 30 \
240                 -m bpf --bytecode \
241                 "$CBPF_MPTCP_SUBOPTION_ADD_ADDR" \
242                 -j DROP
243 }
244
245 # $1: test name
246 reset_with_checksum()
247 {
248         local ns1_enable=$1
249         local ns2_enable=$2
250
251         reset "checksum test ${1} ${2}" || return 1
252
253         ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=$ns1_enable
254         ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=$ns2_enable
255
256         validate_checksum=1
257 }
258
259 reset_with_allow_join_id0()
260 {
261         local ns1_enable=$2
262         local ns2_enable=$3
263
264         reset "${1}" || return 1
265
266         ip netns exec $ns1 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns1_enable
267         ip netns exec $ns2 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns2_enable
268 }
269
270 # Modify TCP payload without corrupting the TCP packet
271 #
272 # This rule inverts a 8-bit word at byte offset 148 for the 2nd TCP ACK packets
273 # carrying enough data.
274 # Once it is done, the TCP Checksum field is updated so the packet is still
275 # considered as valid at the TCP level.
276 # Because the MPTCP checksum, covering the TCP options and data, has not been
277 # updated, the modification will be detected and an MP_FAIL will be emitted:
278 # what we want to validate here without corrupting "random" MPTCP options.
279 #
280 # To avoid having tc producing this pr_info() message for each TCP ACK packets
281 # not carrying enough data:
282 #
283 #     tc action pedit offset 162 out of bounds
284 #
285 # Netfilter is used to mark packets with enough data.
286 reset_with_fail()
287 {
288         reset "${1}" || return 1
289
290         ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
291         ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
292
293         check_invert=1
294         validate_checksum=1
295         local i="$2"
296         local ip="${3:-4}"
297         local tables
298
299         tables="iptables"
300         if [ $ip -eq 6 ]; then
301                 tables="ip6tables"
302         fi
303
304         ip netns exec $ns2 $tables \
305                 -t mangle \
306                 -A OUTPUT \
307                 -o ns2eth$i \
308                 -p tcp \
309                 -m length --length 150:9999 \
310                 -m statistic --mode nth --packet 1 --every 99999 \
311                 -j MARK --set-mark 42 || exit 1
312
313         tc -n $ns2 qdisc add dev ns2eth$i clsact || exit 1
314         tc -n $ns2 filter add dev ns2eth$i egress \
315                 protocol ip prio 1000 \
316                 handle 42 fw \
317                 action pedit munge offset 148 u8 invert \
318                 pipe csum tcp \
319                 index 100 || exit 1
320 }
321
322 fail_test()
323 {
324         ret=1
325         failed_tests[${TEST_COUNT}]="${TEST_NAME}"
326 }
327
328 get_failed_tests_ids()
329 {
330         # sorted
331         local i
332         for i in "${!failed_tests[@]}"; do
333                 echo "${i}"
334         done | sort -n
335 }
336
337 print_file_err()
338 {
339         ls -l "$1" 1>&2
340         echo "Trailing bytes are: "
341         tail -c 27 "$1"
342 }
343
344 check_transfer()
345 {
346         local in=$1
347         local out=$2
348         local what=$3
349         local i a b
350
351         local line
352         cmp -l "$in" "$out" | while read -r i a b; do
353                 local sum=$((0${a} + 0${b}))
354                 if [ $check_invert -eq 0 ] || [ $sum -ne $((0xff)) ]; then
355                         echo "[ FAIL ] $what does not match (in, out):"
356                         print_file_err "$in"
357                         print_file_err "$out"
358                         fail_test
359
360                         return 1
361                 else
362                         echo "$what has inverted byte at ${i}"
363                 fi
364         done
365
366         return 0
367 }
368
369 do_ping()
370 {
371         local listener_ns="$1"
372         local connector_ns="$2"
373         local connect_addr="$3"
374
375         if ! ip netns exec ${connector_ns} ping -q -c 1 $connect_addr >/dev/null; then
376                 echo "$listener_ns -> $connect_addr connectivity [ FAIL ]" 1>&2
377                 fail_test
378         fi
379 }
380
381 link_failure()
382 {
383         local ns="$1"
384
385         if [ -z "$FAILING_LINKS" ]; then
386                 l=$((RANDOM%4))
387                 FAILING_LINKS=$((l+1))
388         fi
389
390         local l
391         for l in $FAILING_LINKS; do
392                 local veth="ns1eth$l"
393                 ip -net "$ns" link set "$veth" down
394         done
395 }
396
397 # $1: IP address
398 is_v6()
399 {
400         [ -z "${1##*:*}" ]
401 }
402
403 # $1: ns, $2: port
404 wait_local_port_listen()
405 {
406         local listener_ns="${1}"
407         local port="${2}"
408
409         local port_hex
410         port_hex="$(printf "%04X" "${port}")"
411
412         local i
413         for i in $(seq 10); do
414                 ip netns exec "${listener_ns}" cat /proc/net/tcp* | \
415                         awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
416                         break
417                 sleep 0.1
418         done
419 }
420
421 rm_addr_count()
422 {
423         local ns=${1}
424
425         ip netns exec ${ns} nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'
426 }
427
428 # $1: ns, $2: old rm_addr counter in $ns
429 wait_rm_addr()
430 {
431         local ns="${1}"
432         local old_cnt="${2}"
433         local cnt
434
435         local i
436         for i in $(seq 10); do
437                 cnt=$(rm_addr_count ${ns})
438                 [ "$cnt" = "${old_cnt}" ] || break
439                 sleep 0.1
440         done
441 }
442
443 wait_mpj()
444 {
445         local ns="${1}"
446         local cnt old_cnt
447
448         old_cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
449
450         local i
451         for i in $(seq 10); do
452                 cnt=$(ip netns exec ${ns} nstat -as | grep MPJoinAckRx | awk '{print $2}')
453                 [ "$cnt" = "${old_cnt}" ] || break
454                 sleep 0.1
455         done
456 }
457
458 pm_nl_set_limits()
459 {
460         local ns=$1
461         local addrs=$2
462         local subflows=$3
463
464         if [ $ip_mptcp -eq 1 ]; then
465                 ip -n $ns mptcp limits set add_addr_accepted $addrs subflows $subflows
466         else
467                 ip netns exec $ns ./pm_nl_ctl limits $addrs $subflows
468         fi
469 }
470
471 pm_nl_add_endpoint()
472 {
473         local ns=$1
474         local addr=$2
475         local flags _flags
476         local port _port
477         local dev _dev
478         local id _id
479         local nr=2
480
481         local p
482         for p in "${@}"
483         do
484                 if [ $p = "flags" ]; then
485                         eval _flags=\$"$nr"
486                         [ -n "$_flags" ]; flags="flags $_flags"
487                 fi
488                 if [ $p = "dev" ]; then
489                         eval _dev=\$"$nr"
490                         [ -n "$_dev" ]; dev="dev $_dev"
491                 fi
492                 if [ $p = "id" ]; then
493                         eval _id=\$"$nr"
494                         [ -n "$_id" ]; id="id $_id"
495                 fi
496                 if [ $p = "port" ]; then
497                         eval _port=\$"$nr"
498                         [ -n "$_port" ]; port="port $_port"
499                 fi
500
501                 nr=$((nr + 1))
502         done
503
504         if [ $ip_mptcp -eq 1 ]; then
505                 ip -n $ns mptcp endpoint add $addr ${_flags//","/" "} $dev $id $port
506         else
507                 ip netns exec $ns ./pm_nl_ctl add $addr $flags $dev $id $port
508         fi
509 }
510
511 pm_nl_del_endpoint()
512 {
513         local ns=$1
514         local id=$2
515         local addr=$3
516
517         if [ $ip_mptcp -eq 1 ]; then
518                 ip -n $ns mptcp endpoint delete id $id $addr
519         else
520                 ip netns exec $ns ./pm_nl_ctl del $id $addr
521         fi
522 }
523
524 pm_nl_flush_endpoint()
525 {
526         local ns=$1
527
528         if [ $ip_mptcp -eq 1 ]; then
529                 ip -n $ns mptcp endpoint flush
530         else
531                 ip netns exec $ns ./pm_nl_ctl flush
532         fi
533 }
534
535 pm_nl_show_endpoints()
536 {
537         local ns=$1
538
539         if [ $ip_mptcp -eq 1 ]; then
540                 ip -n $ns mptcp endpoint show
541         else
542                 ip netns exec $ns ./pm_nl_ctl dump
543         fi
544 }
545
546 pm_nl_change_endpoint()
547 {
548         local ns=$1
549         local id=$2
550         local flags=$3
551
552         if [ $ip_mptcp -eq 1 ]; then
553                 ip -n $ns mptcp endpoint change id $id ${flags//","/" "}
554         else
555                 ip netns exec $ns ./pm_nl_ctl set id $id flags $flags
556         fi
557 }
558
559 pm_nl_check_endpoint()
560 {
561         local line expected_line
562         local need_title=$1
563         local msg="$2"
564         local ns=$3
565         local addr=$4
566         local _flags=""
567         local flags
568         local _port
569         local port
570         local dev
571         local _id
572         local id
573
574         if [ "${need_title}" = 1 ]; then
575                 printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}"
576         else
577                 printf "%-${nr_blank}s %s" " " "${msg}"
578         fi
579
580         shift 4
581         while [ -n "$1" ]; do
582                 if [ $1 = "flags" ]; then
583                         _flags=$2
584                         [ -n "$_flags" ]; flags="flags $_flags"
585                         shift
586                 elif [ $1 = "dev" ]; then
587                         [ -n "$2" ]; dev="dev $1"
588                         shift
589                 elif [ $1 = "id" ]; then
590                         _id=$2
591                         [ -n "$_id" ]; id="id $_id"
592                         shift
593                 elif [ $1 = "port" ]; then
594                         _port=$2
595                         [ -n "$_port" ]; port=" port $_port"
596                         shift
597                 fi
598
599                 shift
600         done
601
602         if [ -z "$id" ]; then
603                 echo "[skip] bad test - missing endpoint id"
604                 return
605         fi
606
607         if [ $ip_mptcp -eq 1 ]; then
608                 line=$(ip -n $ns mptcp endpoint show $id)
609                 # the dump order is: address id flags port dev
610                 expected_line="$addr"
611                 [ -n "$addr" ] && expected_line="$expected_line $addr"
612                 expected_line="$expected_line $id"
613                 [ -n "$_flags" ] && expected_line="$expected_line ${_flags//","/" "}"
614                 [ -n "$dev" ] && expected_line="$expected_line $dev"
615                 [ -n "$port" ] && expected_line="$expected_line $port"
616         else
617                 line=$(ip netns exec $ns ./pm_nl_ctl get $_id)
618                 # the dump order is: id flags dev address port
619                 expected_line="$id"
620                 [ -n "$flags" ] && expected_line="$expected_line $flags"
621                 [ -n "$dev" ] && expected_line="$expected_line $dev"
622                 [ -n "$addr" ] && expected_line="$expected_line $addr"
623                 [ -n "$_port" ] && expected_line="$expected_line $_port"
624         fi
625         if [ "$line" = "$expected_line" ]; then
626                 echo "[ ok ]"
627         else
628                 echo "[fail] expected '$expected_line' found '$line'"
629                 fail_test
630         fi
631 }
632
633 filter_tcp_from()
634 {
635         local ns="${1}"
636         local src="${2}"
637         local target="${3}"
638
639         ip netns exec "${ns}" iptables -A INPUT -s "${src}" -p tcp -j "${target}"
640 }
641
642 do_transfer()
643 {
644         local listener_ns="$1"
645         local connector_ns="$2"
646         local cl_proto="$3"
647         local srv_proto="$4"
648         local connect_addr="$5"
649         local test_link_fail="$6"
650         local addr_nr_ns1="$7"
651         local addr_nr_ns2="$8"
652         local speed="$9"
653         local sflags="${10}"
654
655         local port=$((10000 + TEST_COUNT - 1))
656         local cappid
657
658         :> "$cout"
659         :> "$sout"
660         :> "$capout"
661
662         if [ $capture -eq 1 ]; then
663                 local capuser
664                 if [ -z $SUDO_USER ] ; then
665                         capuser=""
666                 else
667                         capuser="-Z $SUDO_USER"
668                 fi
669
670                 capfile=$(printf "mp_join-%02u-%s.pcap" "$TEST_COUNT" "${listener_ns}")
671
672                 echo "Capturing traffic for test $TEST_COUNT into $capfile"
673                 ip netns exec ${listener_ns} tcpdump -i any -s 65535 -B 32768 $capuser -w $capfile > "$capout" 2>&1 &
674                 cappid=$!
675
676                 sleep 1
677         fi
678
679         NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \
680                 nstat -n
681         NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \
682                 nstat -n
683
684         local extra_args
685         if [ $speed = "fast" ]; then
686                 extra_args="-j"
687         elif [ $speed = "slow" ]; then
688                 extra_args="-r 50"
689         elif [[ $speed = "speed_"* ]]; then
690                 extra_args="-r ${speed:6}"
691         fi
692
693         if [[ "${addr_nr_ns2}" = "fastclose_"* ]]; then
694                 # disconnect
695                 extra_args="$extra_args -I ${addr_nr_ns2:10}"
696                 addr_nr_ns2=0
697         fi
698
699         local local_addr
700         if is_v6 "${connect_addr}"; then
701                 local_addr="::"
702         else
703                 local_addr="0.0.0.0"
704         fi
705
706         if [ "$test_link_fail" -gt 1 ];then
707                 timeout ${timeout_test} \
708                         ip netns exec ${listener_ns} \
709                                 ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
710                                         $extra_args ${local_addr} < "$sinfail" > "$sout" &
711         else
712                 timeout ${timeout_test} \
713                         ip netns exec ${listener_ns} \
714                                 ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \
715                                         $extra_args ${local_addr} < "$sin" > "$sout" &
716         fi
717         local spid=$!
718
719         wait_local_port_listen "${listener_ns}" "${port}"
720
721         if [ "$test_link_fail" -eq 0 ];then
722                 timeout ${timeout_test} \
723                         ip netns exec ${connector_ns} \
724                                 ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
725                                         $extra_args $connect_addr < "$cin" > "$cout" &
726         elif [ "$test_link_fail" -eq 1 ] || [ "$test_link_fail" -eq 2 ];then
727                 ( cat "$cinfail" ; sleep 2; link_failure $listener_ns ; cat "$cinfail" ) | \
728                         tee "$cinsent" | \
729                         timeout ${timeout_test} \
730                                 ip netns exec ${connector_ns} \
731                                         ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
732                                                 $extra_args $connect_addr > "$cout" &
733         else
734                 tee "$cinsent" < "$cinfail" | \
735                         timeout ${timeout_test} \
736                                 ip netns exec ${connector_ns} \
737                                         ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
738                                                 $extra_args $connect_addr > "$cout" &
739         fi
740         local cpid=$!
741
742         # let the mptcp subflow be established in background before
743         # do endpoint manipulation
744         if [ $addr_nr_ns1 != "0" ] || [ $addr_nr_ns2 != "0" ]; then
745                 sleep 1
746         fi
747
748         if [ $addr_nr_ns1 -gt 0 ]; then
749                 local counter=2
750                 local add_nr_ns1=${addr_nr_ns1}
751                 while [ $add_nr_ns1 -gt 0 ]; do
752                         local addr
753                         if is_v6 "${connect_addr}"; then
754                                 addr="dead:beef:$counter::1"
755                         else
756                                 addr="10.0.$counter.1"
757                         fi
758                         pm_nl_add_endpoint $ns1 $addr flags signal
759                         counter=$((counter + 1))
760                         add_nr_ns1=$((add_nr_ns1 - 1))
761                 done
762         elif [ $addr_nr_ns1 -lt 0 ]; then
763                 local rm_nr_ns1=$((-addr_nr_ns1))
764                 if [ $rm_nr_ns1 -lt 8 ]; then
765                         local counter=0
766                         local line
767                         pm_nl_show_endpoints ${listener_ns} | while read -r line; do
768                                 # shellcheck disable=SC2206 # we do want to split per word
769                                 local arr=($line)
770                                 local nr=0
771
772                                 local i
773                                 for i in "${arr[@]}"; do
774                                         if [ $i = "id" ]; then
775                                                 if [ $counter -eq $rm_nr_ns1 ]; then
776                                                         break
777                                                 fi
778                                                 id=${arr[$nr+1]}
779                                                 rm_addr=$(rm_addr_count ${connector_ns})
780                                                 pm_nl_del_endpoint ${listener_ns} $id
781                                                 wait_rm_addr ${connector_ns} ${rm_addr}
782                                                 counter=$((counter + 1))
783                                         fi
784                                         nr=$((nr + 1))
785                                 done
786                         done
787                 elif [ $rm_nr_ns1 -eq 8 ]; then
788                         pm_nl_flush_endpoint ${listener_ns}
789                 elif [ $rm_nr_ns1 -eq 9 ]; then
790                         pm_nl_del_endpoint ${listener_ns} 0 ${connect_addr}
791                 fi
792         fi
793
794         local flags="subflow"
795         if [[ "${addr_nr_ns2}" = "fullmesh_"* ]]; then
796                 flags="${flags},fullmesh"
797                 addr_nr_ns2=${addr_nr_ns2:9}
798         fi
799
800         # if newly added endpoints must be deleted, give the background msk
801         # some time to created them
802         [ $addr_nr_ns1 -gt 0 ] && [ $addr_nr_ns2 -lt 0 ] && sleep 1
803
804         if [ $addr_nr_ns2 -gt 0 ]; then
805                 local add_nr_ns2=${addr_nr_ns2}
806                 local counter=3
807                 while [ $add_nr_ns2 -gt 0 ]; do
808                         local addr
809                         if is_v6 "${connect_addr}"; then
810                                 addr="dead:beef:$counter::2"
811                         else
812                                 addr="10.0.$counter.2"
813                         fi
814                         pm_nl_add_endpoint $ns2 $addr flags $flags
815                         counter=$((counter + 1))
816                         add_nr_ns2=$((add_nr_ns2 - 1))
817                 done
818         elif [ $addr_nr_ns2 -lt 0 ]; then
819                 local rm_nr_ns2=$((-addr_nr_ns2))
820                 if [ $rm_nr_ns2 -lt 8 ]; then
821                         local counter=0
822                         local line
823                         pm_nl_show_endpoints ${connector_ns} | while read -r line; do
824                                 # shellcheck disable=SC2206 # we do want to split per word
825                                 local arr=($line)
826                                 local nr=0
827
828                                 local i
829                                 for i in "${arr[@]}"; do
830                                         if [ $i = "id" ]; then
831                                                 if [ $counter -eq $rm_nr_ns2 ]; then
832                                                         break
833                                                 fi
834                                                 local id rm_addr
835                                                 # rm_addr are serialized, allow the previous one to
836                                                 # complete
837                                                 id=${arr[$nr+1]}
838                                                 rm_addr=$(rm_addr_count ${listener_ns})
839                                                 pm_nl_del_endpoint ${connector_ns} $id
840                                                 wait_rm_addr ${listener_ns} ${rm_addr}
841                                                 counter=$((counter + 1))
842                                         fi
843                                         nr=$((nr + 1))
844                                 done
845                         done
846                 elif [ $rm_nr_ns2 -eq 8 ]; then
847                         pm_nl_flush_endpoint ${connector_ns}
848                 elif [ $rm_nr_ns2 -eq 9 ]; then
849                         local addr
850                         if is_v6 "${connect_addr}"; then
851                                 addr="dead:beef:1::2"
852                         else
853                                 addr="10.0.1.2"
854                         fi
855                         pm_nl_del_endpoint ${connector_ns} 0 $addr
856                 fi
857         fi
858
859         if [ -n "${sflags}" ]; then
860                 sleep 1
861
862                 local netns
863                 for netns in "$ns1" "$ns2"; do
864                         local line
865                         pm_nl_show_endpoints $netns | while read -r line; do
866                                 # shellcheck disable=SC2206 # we do want to split per word
867                                 local arr=($line)
868                                 local nr=0
869                                 local id
870
871                                 local i
872                                 for i in "${arr[@]}"; do
873                                         if [ $i = "id" ]; then
874                                                 id=${arr[$nr+1]}
875                                         fi
876                                         nr=$((nr + 1))
877                                 done
878                                 pm_nl_change_endpoint $netns $id $sflags
879                         done
880                 done
881         fi
882
883         wait $cpid
884         local retc=$?
885         wait $spid
886         local rets=$?
887
888         if [ $capture -eq 1 ]; then
889             sleep 1
890             kill $cappid
891         fi
892
893         NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \
894                 nstat | grep Tcp > /tmp/${listener_ns}.out
895         NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \
896                 nstat | grep Tcp > /tmp/${connector_ns}.out
897
898         if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
899                 echo " client exit code $retc, server $rets" 1>&2
900                 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2
901                 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port"
902                 cat /tmp/${listener_ns}.out
903                 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2
904                 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port"
905                 cat /tmp/${connector_ns}.out
906
907                 cat "$capout"
908                 fail_test
909                 return 1
910         fi
911
912         if [ "$test_link_fail" -gt 1 ];then
913                 check_transfer $sinfail $cout "file received by client"
914         else
915                 check_transfer $sin $cout "file received by client"
916         fi
917         retc=$?
918         if [ "$test_link_fail" -eq 0 ];then
919                 check_transfer $cin $sout "file received by server"
920         else
921                 check_transfer $cinsent $sout "file received by server"
922         fi
923         rets=$?
924
925         if [ $retc -eq 0 ] && [ $rets -eq 0 ];then
926                 cat "$capout"
927                 return 0
928         fi
929
930         cat "$capout"
931         return 1
932 }
933
934 make_file()
935 {
936         local name=$1
937         local who=$2
938         local size=$3
939
940         dd if=/dev/urandom of="$name" bs=1024 count=$size 2> /dev/null
941         echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
942
943         echo "Created $name (size $size KB) containing data sent by $who"
944 }
945
946 run_tests()
947 {
948         local listener_ns="$1"
949         local connector_ns="$2"
950         local connect_addr="$3"
951         local test_linkfail="${4:-0}"
952         local addr_nr_ns1="${5:-0}"
953         local addr_nr_ns2="${6:-0}"
954         local speed="${7:-fast}"
955         local sflags="${8:-""}"
956
957         local size
958
959         # The values above 2 are reused to make test files
960         # with the given sizes (KB)
961         if [ "$test_linkfail" -gt 2 ]; then
962                 size=$test_linkfail
963
964                 if [ -z "$cinfail" ]; then
965                         cinfail=$(mktemp)
966                 fi
967                 make_file "$cinfail" "client" $size
968         # create the input file for the failure test when
969         # the first failure test run
970         elif [ "$test_linkfail" -ne 0 ] && [ -z "$cinfail" ]; then
971                 # the client file must be considerably larger
972                 # of the maximum expected cwin value, or the
973                 # link utilization will be not predicable
974                 size=$((RANDOM%2))
975                 size=$((size+1))
976                 size=$((size*8192))
977                 size=$((size + ( RANDOM % 8192) ))
978
979                 cinfail=$(mktemp)
980                 make_file "$cinfail" "client" $size
981         fi
982
983         if [ "$test_linkfail" -gt 2 ]; then
984                 size=$test_linkfail
985
986                 if [ -z "$sinfail" ]; then
987                         sinfail=$(mktemp)
988                 fi
989                 make_file "$sinfail" "server" $size
990         elif [ "$test_linkfail" -eq 2 ] && [ -z "$sinfail" ]; then
991                 size=$((RANDOM%16))
992                 size=$((size+1))
993                 size=$((size*2048))
994
995                 sinfail=$(mktemp)
996                 make_file "$sinfail" "server" $size
997         fi
998
999         do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} \
1000                 ${test_linkfail} ${addr_nr_ns1} ${addr_nr_ns2} ${speed} ${sflags}
1001 }
1002
1003 dump_stats()
1004 {
1005         echo Server ns stats
1006         ip netns exec $ns1 nstat -as | grep Tcp
1007         echo Client ns stats
1008         ip netns exec $ns2 nstat -as | grep Tcp
1009 }
1010
1011 chk_csum_nr()
1012 {
1013         local csum_ns1=${1:-0}
1014         local csum_ns2=${2:-0}
1015         local count
1016         local dump_stats
1017         local extra_msg=""
1018         local allow_multi_errors_ns1=0
1019         local allow_multi_errors_ns2=0
1020
1021         if [[ "${csum_ns1}" = "+"* ]]; then
1022                 allow_multi_errors_ns1=1
1023                 csum_ns1=${csum_ns1:1}
1024         fi
1025         if [[ "${csum_ns2}" = "+"* ]]; then
1026                 allow_multi_errors_ns2=1
1027                 csum_ns2=${csum_ns2:1}
1028         fi
1029
1030         printf "%-${nr_blank}s %s" " " "sum"
1031         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
1032         [ -z "$count" ] && count=0
1033         if [ "$count" != "$csum_ns1" ]; then
1034                 extra_msg="$extra_msg ns1=$count"
1035         fi
1036         if { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
1037            { [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
1038                 echo "[fail] got $count data checksum error[s] expected $csum_ns1"
1039                 fail_test
1040                 dump_stats=1
1041         else
1042                 echo -n "[ ok ]"
1043         fi
1044         echo -n " - csum  "
1045         count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}')
1046         [ -z "$count" ] && count=0
1047         if [ "$count" != "$csum_ns2" ]; then
1048                 extra_msg="$extra_msg ns2=$count"
1049         fi
1050         if { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
1051            { [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
1052                 echo "[fail] got $count data checksum error[s] expected $csum_ns2"
1053                 fail_test
1054                 dump_stats=1
1055         else
1056                 echo -n "[ ok ]"
1057         fi
1058         [ "${dump_stats}" = 1 ] && dump_stats
1059
1060         echo "$extra_msg"
1061 }
1062
1063 chk_fail_nr()
1064 {
1065         local fail_tx=$1
1066         local fail_rx=$2
1067         local ns_invert=${3:-""}
1068         local count
1069         local dump_stats
1070         local ns_tx=$ns1
1071         local ns_rx=$ns2
1072         local extra_msg=""
1073         local allow_tx_lost=0
1074         local allow_rx_lost=0
1075
1076         if [[ $ns_invert = "invert" ]]; then
1077                 ns_tx=$ns2
1078                 ns_rx=$ns1
1079                 extra_msg=" invert"
1080         fi
1081
1082         if [[ "${fail_tx}" = "-"* ]]; then
1083                 allow_tx_lost=1
1084                 fail_tx=${fail_tx:1}
1085         fi
1086         if [[ "${fail_rx}" = "-"* ]]; then
1087                 allow_rx_lost=1
1088                 fail_rx=${fail_rx:1}
1089         fi
1090
1091         printf "%-${nr_blank}s %s" " " "ftx"
1092         count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}')
1093         [ -z "$count" ] && count=0
1094         if [ "$count" != "$fail_tx" ]; then
1095                 extra_msg="$extra_msg,tx=$count"
1096         fi
1097         if { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
1098            { [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
1099                 echo "[fail] got $count MP_FAIL[s] TX expected $fail_tx"
1100                 fail_test
1101                 dump_stats=1
1102         else
1103                 echo -n "[ ok ]"
1104         fi
1105
1106         echo -n " - failrx"
1107         count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}')
1108         [ -z "$count" ] && count=0
1109         if [ "$count" != "$fail_rx" ]; then
1110                 extra_msg="$extra_msg,rx=$count"
1111         fi
1112         if { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
1113            { [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
1114                 echo "[fail] got $count MP_FAIL[s] RX expected $fail_rx"
1115                 fail_test
1116                 dump_stats=1
1117         else
1118                 echo -n "[ ok ]"
1119         fi
1120
1121         [ "${dump_stats}" = 1 ] && dump_stats
1122
1123         echo "$extra_msg"
1124 }
1125
1126 chk_fclose_nr()
1127 {
1128         local fclose_tx=$1
1129         local fclose_rx=$2
1130         local count
1131         local dump_stats
1132
1133         printf "%-${nr_blank}s %s" " " "ctx"
1134         count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPFastcloseTx | awk '{print $2}')
1135         [ -z "$count" ] && count=0
1136         if [ "$count" != "$fclose_tx" ]; then
1137                 echo "[fail] got $count MP_FASTCLOSE[s] TX expected $fclose_tx"
1138                 fail_test
1139                 dump_stats=1
1140         else
1141                 echo -n "[ ok ]"
1142         fi
1143
1144         echo -n " - fclzrx"
1145         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPFastcloseRx | awk '{print $2}')
1146         [ -z "$count" ] && count=0
1147         if [ "$count" != "$fclose_rx" ]; then
1148                 echo "[fail] got $count MP_FASTCLOSE[s] RX expected $fclose_rx"
1149                 fail_test
1150                 dump_stats=1
1151         else
1152                 echo "[ ok ]"
1153         fi
1154
1155         [ "${dump_stats}" = 1 ] && dump_stats
1156 }
1157
1158 chk_rst_nr()
1159 {
1160         local rst_tx=$1
1161         local rst_rx=$2
1162         local ns_invert=${3:-""}
1163         local count
1164         local dump_stats
1165         local ns_tx=$ns1
1166         local ns_rx=$ns2
1167         local extra_msg=""
1168
1169         if [[ $ns_invert = "invert" ]]; then
1170                 ns_tx=$ns2
1171                 ns_rx=$ns1
1172                 extra_msg="   invert"
1173         fi
1174
1175         printf "%-${nr_blank}s %s" " " "rtx"
1176         count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPRstTx | awk '{print $2}')
1177         [ -z "$count" ] && count=0
1178         if [ "$count" != "$rst_tx" ]; then
1179                 echo "[fail] got $count MP_RST[s] TX expected $rst_tx"
1180                 fail_test
1181                 dump_stats=1
1182         else
1183                 echo -n "[ ok ]"
1184         fi
1185
1186         echo -n " - rstrx "
1187         count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPRstRx | awk '{print $2}')
1188         [ -z "$count" ] && count=0
1189         if [ "$count" != "$rst_rx" ]; then
1190                 echo "[fail] got $count MP_RST[s] RX expected $rst_rx"
1191                 fail_test
1192                 dump_stats=1
1193         else
1194                 echo -n "[ ok ]"
1195         fi
1196
1197         [ "${dump_stats}" = 1 ] && dump_stats
1198
1199         echo "$extra_msg"
1200 }
1201
1202 chk_infi_nr()
1203 {
1204         local infi_tx=$1
1205         local infi_rx=$2
1206         local count
1207         local dump_stats
1208
1209         printf "%-${nr_blank}s %s" " " "itx"
1210         count=$(ip netns exec $ns2 nstat -as | grep InfiniteMapTx | awk '{print $2}')
1211         [ -z "$count" ] && count=0
1212         if [ "$count" != "$infi_tx" ]; then
1213                 echo "[fail] got $count infinite map[s] TX expected $infi_tx"
1214                 fail_test
1215                 dump_stats=1
1216         else
1217                 echo -n "[ ok ]"
1218         fi
1219
1220         echo -n " - infirx"
1221         count=$(ip netns exec $ns1 nstat -as | grep InfiniteMapRx | awk '{print $2}')
1222         [ -z "$count" ] && count=0
1223         if [ "$count" != "$infi_rx" ]; then
1224                 echo "[fail] got $count infinite map[s] RX expected $infi_rx"
1225                 fail_test
1226                 dump_stats=1
1227         else
1228                 echo "[ ok ]"
1229         fi
1230
1231         [ "${dump_stats}" = 1 ] && dump_stats
1232 }
1233
1234 chk_join_nr()
1235 {
1236         local syn_nr=$1
1237         local syn_ack_nr=$2
1238         local ack_nr=$3
1239         local csum_ns1=${4:-0}
1240         local csum_ns2=${5:-0}
1241         local fail_nr=${6:-0}
1242         local rst_nr=${7:-0}
1243         local infi_nr=${8:-0}
1244         local corrupted_pkts=${9:-0}
1245         local count
1246         local dump_stats
1247         local with_cookie
1248         local title="${TEST_NAME}"
1249
1250         if [ "${corrupted_pkts}" -gt 0 ]; then
1251                 title+=": ${corrupted_pkts} corrupted pkts"
1252         fi
1253
1254         printf "%03u %-36s %s" "${TEST_COUNT}" "${title}" "syn"
1255         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}')
1256         [ -z "$count" ] && count=0
1257         if [ "$count" != "$syn_nr" ]; then
1258                 echo "[fail] got $count JOIN[s] syn expected $syn_nr"
1259                 fail_test
1260                 dump_stats=1
1261         else
1262                 echo -n "[ ok ]"
1263         fi
1264
1265         echo -n " - synack"
1266         with_cookie=$(ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies)
1267         count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinSynAckRx | awk '{print $2}')
1268         [ -z "$count" ] && count=0
1269         if [ "$count" != "$syn_ack_nr" ]; then
1270                 # simult connections exceeding the limit with cookie enabled could go up to
1271                 # synack validation as the conn limit can be enforced reliably only after
1272                 # the subflow creation
1273                 if [ "$with_cookie" = 2 ] && [ "$count" -gt "$syn_ack_nr" ] && [ "$count" -le "$syn_nr" ]; then
1274                         echo -n "[ ok ]"
1275                 else
1276                         echo "[fail] got $count JOIN[s] synack expected $syn_ack_nr"
1277                         fail_test
1278                         dump_stats=1
1279                 fi
1280         else
1281                 echo -n "[ ok ]"
1282         fi
1283
1284         echo -n " - ack"
1285         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinAckRx | awk '{print $2}')
1286         [ -z "$count" ] && count=0
1287         if [ "$count" != "$ack_nr" ]; then
1288                 echo "[fail] got $count JOIN[s] ack expected $ack_nr"
1289                 fail_test
1290                 dump_stats=1
1291         else
1292                 echo "[ ok ]"
1293         fi
1294         [ "${dump_stats}" = 1 ] && dump_stats
1295         if [ $validate_checksum -eq 1 ]; then
1296                 chk_csum_nr $csum_ns1 $csum_ns2
1297                 chk_fail_nr $fail_nr $fail_nr
1298                 chk_rst_nr $rst_nr $rst_nr
1299                 chk_infi_nr $infi_nr $infi_nr
1300         fi
1301 }
1302
1303 # a negative value for 'stale_max' means no upper bound:
1304 # for bidirectional transfer, if one peer sleep for a while
1305 # - as these tests do - we can have a quite high number of
1306 # stale/recover conversions, proportional to
1307 # sleep duration/ MPTCP-level RTX interval.
1308 chk_stale_nr()
1309 {
1310         local ns=$1
1311         local stale_min=$2
1312         local stale_max=$3
1313         local stale_delta=$4
1314         local dump_stats
1315         local stale_nr
1316         local recover_nr
1317
1318         printf "%-${nr_blank}s %-18s" " " "stale"
1319         stale_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}')
1320         [ -z "$stale_nr" ] && stale_nr=0
1321         recover_nr=$(ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}')
1322         [ -z "$recover_nr" ] && recover_nr=0
1323
1324         if [ $stale_nr -lt $stale_min ] ||
1325            { [ $stale_max -gt 0 ] && [ $stale_nr -gt $stale_max ]; } ||
1326            [ $((stale_nr - recover_nr)) -ne $stale_delta ]; then
1327                 echo "[fail] got $stale_nr stale[s] $recover_nr recover[s], " \
1328                      " expected stale in range [$stale_min..$stale_max]," \
1329                      " stale-recover delta $stale_delta "
1330                 fail_test
1331                 dump_stats=1
1332         else
1333                 echo "[ ok ]"
1334         fi
1335
1336         if [ "${dump_stats}" = 1 ]; then
1337                 echo $ns stats
1338                 ip netns exec $ns ip -s link show
1339                 ip netns exec $ns nstat -as | grep MPTcp
1340         fi
1341 }
1342
1343 chk_add_nr()
1344 {
1345         local add_nr=$1
1346         local echo_nr=$2
1347         local port_nr=${3:-0}
1348         local syn_nr=${4:-$port_nr}
1349         local syn_ack_nr=${5:-$port_nr}
1350         local ack_nr=${6:-$port_nr}
1351         local mis_syn_nr=${7:-0}
1352         local mis_ack_nr=${8:-0}
1353         local count
1354         local dump_stats
1355         local timeout
1356
1357         timeout=$(ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout)
1358
1359         printf "%-${nr_blank}s %s" " " "add"
1360         count=$(ip netns exec $ns2 nstat -as MPTcpExtAddAddr | grep MPTcpExtAddAddr | awk '{print $2}')
1361         [ -z "$count" ] && count=0
1362
1363         # if the test configured a short timeout tolerate greater then expected
1364         # add addrs options, due to retransmissions
1365         if [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
1366                 echo "[fail] got $count ADD_ADDR[s] expected $add_nr"
1367                 fail_test
1368                 dump_stats=1
1369         else
1370                 echo -n "[ ok ]"
1371         fi
1372
1373         echo -n " - echo  "
1374         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtEchoAdd | awk '{print $2}')
1375         [ -z "$count" ] && count=0
1376         if [ "$count" != "$echo_nr" ]; then
1377                 echo "[fail] got $count ADD_ADDR echo[s] expected $echo_nr"
1378                 fail_test
1379                 dump_stats=1
1380         else
1381                 echo -n "[ ok ]"
1382         fi
1383
1384         if [ $port_nr -gt 0 ]; then
1385                 echo -n " - pt "
1386                 count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtPortAdd | awk '{print $2}')
1387                 [ -z "$count" ] && count=0
1388                 if [ "$count" != "$port_nr" ]; then
1389                         echo "[fail] got $count ADD_ADDR[s] with a port-number expected $port_nr"
1390                         fail_test
1391                         dump_stats=1
1392                 else
1393                         echo "[ ok ]"
1394                 fi
1395
1396                 printf "%-${nr_blank}s %s" " " "syn"
1397                 count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx |
1398                         awk '{print $2}')
1399                 [ -z "$count" ] && count=0
1400                 if [ "$count" != "$syn_nr" ]; then
1401                         echo "[fail] got $count JOIN[s] syn with a different \
1402                                 port-number expected $syn_nr"
1403                         fail_test
1404                         dump_stats=1
1405                 else
1406                         echo -n "[ ok ]"
1407                 fi
1408
1409                 echo -n " - synack"
1410                 count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPJoinPortSynAckRx |
1411                         awk '{print $2}')
1412                 [ -z "$count" ] && count=0
1413                 if [ "$count" != "$syn_ack_nr" ]; then
1414                         echo "[fail] got $count JOIN[s] synack with a different \
1415                                 port-number expected $syn_ack_nr"
1416                         fail_test
1417                         dump_stats=1
1418                 else
1419                         echo -n "[ ok ]"
1420                 fi
1421
1422                 echo -n " - ack"
1423                 count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortAckRx |
1424                         awk '{print $2}')
1425                 [ -z "$count" ] && count=0
1426                 if [ "$count" != "$ack_nr" ]; then
1427                         echo "[fail] got $count JOIN[s] ack with a different \
1428                                 port-number expected $ack_nr"
1429                         fail_test
1430                         dump_stats=1
1431                 else
1432                         echo "[ ok ]"
1433                 fi
1434
1435                 printf "%-${nr_blank}s %s" " " "syn"
1436                 count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx |
1437                         awk '{print $2}')
1438                 [ -z "$count" ] && count=0
1439                 if [ "$count" != "$mis_syn_nr" ]; then
1440                         echo "[fail] got $count JOIN[s] syn with a mismatched \
1441                                 port-number expected $mis_syn_nr"
1442                         fail_test
1443                         dump_stats=1
1444                 else
1445                         echo -n "[ ok ]"
1446                 fi
1447
1448                 echo -n " - ack   "
1449                 count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortAckRx |
1450                         awk '{print $2}')
1451                 [ -z "$count" ] && count=0
1452                 if [ "$count" != "$mis_ack_nr" ]; then
1453                         echo "[fail] got $count JOIN[s] ack with a mismatched \
1454                                 port-number expected $mis_ack_nr"
1455                         fail_test
1456                         dump_stats=1
1457                 else
1458                         echo "[ ok ]"
1459                 fi
1460         else
1461                 echo ""
1462         fi
1463
1464         [ "${dump_stats}" = 1 ] && dump_stats
1465 }
1466
1467 chk_rm_nr()
1468 {
1469         local rm_addr_nr=$1
1470         local rm_subflow_nr=$2
1471         local invert
1472         local simult
1473         local count
1474         local dump_stats
1475         local addr_ns=$ns1
1476         local subflow_ns=$ns2
1477         local extra_msg=""
1478
1479         shift 2
1480         while [ -n "$1" ]; do
1481                 [ "$1" = "invert" ] && invert=true
1482                 [ "$1" = "simult" ] && simult=true
1483                 shift
1484         done
1485
1486         if [ -z $invert ]; then
1487                 addr_ns=$ns1
1488                 subflow_ns=$ns2
1489         elif [ $invert = "true" ]; then
1490                 addr_ns=$ns2
1491                 subflow_ns=$ns1
1492                 extra_msg="   invert"
1493         fi
1494
1495         printf "%-${nr_blank}s %s" " " "rm "
1496         count=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}')
1497         [ -z "$count" ] && count=0
1498         if [ "$count" != "$rm_addr_nr" ]; then
1499                 echo "[fail] got $count RM_ADDR[s] expected $rm_addr_nr"
1500                 fail_test
1501                 dump_stats=1
1502         else
1503                 echo -n "[ ok ]"
1504         fi
1505
1506         echo -n " - rmsf  "
1507         count=$(ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
1508         [ -z "$count" ] && count=0
1509         if [ -n "$simult" ]; then
1510                 local cnt suffix
1511
1512                 cnt=$(ip netns exec $addr_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}')
1513
1514                 # in case of simult flush, the subflow removal count on each side is
1515                 # unreliable
1516                 [ -z "$cnt" ] && cnt=0
1517                 count=$((count + cnt))
1518                 [ "$count" != "$rm_subflow_nr" ] && suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
1519                 if [ $count -ge "$rm_subflow_nr" ] && \
1520                    [ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
1521                         echo "[ ok ] $suffix"
1522                 else
1523                         echo "[fail] got $count RM_SUBFLOW[s] expected in range [$rm_subflow_nr:$((rm_subflow_nr*2))]"
1524                         fail_test
1525                         dump_stats=1
1526                 fi
1527                 return
1528         fi
1529         if [ "$count" != "$rm_subflow_nr" ]; then
1530                 echo "[fail] got $count RM_SUBFLOW[s] expected $rm_subflow_nr"
1531                 fail_test
1532                 dump_stats=1
1533         else
1534                 echo -n "[ ok ]"
1535         fi
1536
1537         [ "${dump_stats}" = 1 ] && dump_stats
1538
1539         echo "$extra_msg"
1540 }
1541
1542 chk_prio_nr()
1543 {
1544         local mp_prio_nr_tx=$1
1545         local mp_prio_nr_rx=$2
1546         local count
1547         local dump_stats
1548
1549         printf "%-${nr_blank}s %s" " " "ptx"
1550         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
1551         [ -z "$count" ] && count=0
1552         if [ "$count" != "$mp_prio_nr_tx" ]; then
1553                 echo "[fail] got $count MP_PRIO[s] TX expected $mp_prio_nr_tx"
1554                 fail_test
1555                 dump_stats=1
1556         else
1557                 echo -n "[ ok ]"
1558         fi
1559
1560         echo -n " - prx   "
1561         count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
1562         [ -z "$count" ] && count=0
1563         if [ "$count" != "$mp_prio_nr_rx" ]; then
1564                 echo "[fail] got $count MP_PRIO[s] RX expected $mp_prio_nr_rx"
1565                 fail_test
1566                 dump_stats=1
1567         else
1568                 echo "[ ok ]"
1569         fi
1570
1571         [ "${dump_stats}" = 1 ] && dump_stats
1572 }
1573
1574 chk_subflow_nr()
1575 {
1576         local need_title="$1"
1577         local msg="$2"
1578         local subflow_nr=$3
1579         local cnt1
1580         local cnt2
1581
1582         if [ -n "${need_title}" ]; then
1583                 printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}"
1584         else
1585                 printf "%-${nr_blank}s %s" " " "${msg}"
1586         fi
1587
1588         cnt1=$(ss -N $ns1 -tOni | grep -c token)
1589         cnt2=$(ss -N $ns2 -tOni | grep -c token)
1590         if [ "$cnt1" != "$subflow_nr" -o "$cnt2" != "$subflow_nr" ]; then
1591                 echo "[fail] got $cnt1:$cnt2 subflows expected $subflow_nr"
1592                 fail_test
1593                 dump_stats=1
1594         else
1595                 echo "[ ok ]"
1596         fi
1597
1598         [ "${dump_stats}" = 1 ] && ( ss -N $ns1 -tOni ; ss -N $ns1 -tOni | grep token; ip -n $ns1 mptcp endpoint )
1599 }
1600
1601 chk_link_usage()
1602 {
1603         local ns=$1
1604         local link=$2
1605         local out=$3
1606         local expected_rate=$4
1607
1608         local tx_link tx_total
1609         tx_link=$(ip netns exec $ns cat /sys/class/net/$link/statistics/tx_bytes)
1610         tx_total=$(stat --format=%s $out)
1611         local tx_rate=$((tx_link * 100 / tx_total))
1612         local tolerance=5
1613
1614         printf "%-${nr_blank}s %-18s" " " "link usage"
1615         if [ $tx_rate -lt $((expected_rate - tolerance)) ] || \
1616            [ $tx_rate -gt $((expected_rate + tolerance)) ]; then
1617                 echo "[fail] got $tx_rate% usage, expected $expected_rate%"
1618                 fail_test
1619         else
1620                 echo "[ ok ]"
1621         fi
1622 }
1623
1624 wait_attempt_fail()
1625 {
1626         local timeout_ms=$((timeout_poll * 1000))
1627         local time=0
1628         local ns=$1
1629
1630         while [ $time -lt $timeout_ms ]; do
1631                 local cnt
1632
1633                 cnt=$(ip netns exec $ns nstat -as TcpAttemptFails | grep TcpAttemptFails | awk '{print $2}')
1634
1635                 [ "$cnt" = 1 ] && return 1
1636                 time=$((time + 100))
1637                 sleep 0.1
1638         done
1639         return 1
1640 }
1641
1642 set_userspace_pm()
1643 {
1644         local ns=$1
1645
1646         ip netns exec $ns sysctl -q net.mptcp.pm_type=1
1647 }
1648
1649 subflows_tests()
1650 {
1651         if reset "no JOIN"; then
1652                 run_tests $ns1 $ns2 10.0.1.1
1653                 chk_join_nr 0 0 0
1654         fi
1655
1656         # subflow limited by client
1657         if reset "single subflow, limited by client"; then
1658                 pm_nl_set_limits $ns1 0 0
1659                 pm_nl_set_limits $ns2 0 0
1660                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1661                 run_tests $ns1 $ns2 10.0.1.1
1662                 chk_join_nr 0 0 0
1663         fi
1664
1665         # subflow limited by server
1666         if reset "single subflow, limited by server"; then
1667                 pm_nl_set_limits $ns1 0 0
1668                 pm_nl_set_limits $ns2 0 1
1669                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1670                 run_tests $ns1 $ns2 10.0.1.1
1671                 chk_join_nr 1 1 0
1672         fi
1673
1674         # subflow
1675         if reset "single subflow"; then
1676                 pm_nl_set_limits $ns1 0 1
1677                 pm_nl_set_limits $ns2 0 1
1678                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1679                 run_tests $ns1 $ns2 10.0.1.1
1680                 chk_join_nr 1 1 1
1681         fi
1682
1683         # multiple subflows
1684         if reset "multiple subflows"; then
1685                 pm_nl_set_limits $ns1 0 2
1686                 pm_nl_set_limits $ns2 0 2
1687                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1688                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
1689                 run_tests $ns1 $ns2 10.0.1.1
1690                 chk_join_nr 2 2 2
1691         fi
1692
1693         # multiple subflows limited by server
1694         if reset "multiple subflows, limited by server"; then
1695                 pm_nl_set_limits $ns1 0 1
1696                 pm_nl_set_limits $ns2 0 2
1697                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1698                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
1699                 run_tests $ns1 $ns2 10.0.1.1
1700                 chk_join_nr 2 2 1
1701         fi
1702
1703         # single subflow, dev
1704         if reset "single subflow, dev"; then
1705                 pm_nl_set_limits $ns1 0 1
1706                 pm_nl_set_limits $ns2 0 1
1707                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow dev ns2eth3
1708                 run_tests $ns1 $ns2 10.0.1.1
1709                 chk_join_nr 1 1 1
1710         fi
1711 }
1712
1713 subflows_error_tests()
1714 {
1715         # If a single subflow is configured, and matches the MPC src
1716         # address, no additional subflow should be created
1717         if reset "no MPC reuse with single endpoint"; then
1718                 pm_nl_set_limits $ns1 0 1
1719                 pm_nl_set_limits $ns2 0 1
1720                 pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
1721                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
1722                 chk_join_nr 0 0 0
1723         fi
1724
1725         # multiple subflows, with subflow creation error
1726         if reset "multi subflows, with failing subflow"; then
1727                 pm_nl_set_limits $ns1 0 2
1728                 pm_nl_set_limits $ns2 0 2
1729                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1730                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
1731                 filter_tcp_from $ns1 10.0.3.2 REJECT
1732                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
1733                 chk_join_nr 1 1 1
1734         fi
1735
1736         # multiple subflows, with subflow timeout on MPJ
1737         if reset "multi subflows, with subflow timeout"; then
1738                 pm_nl_set_limits $ns1 0 2
1739                 pm_nl_set_limits $ns2 0 2
1740                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1741                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
1742                 filter_tcp_from $ns1 10.0.3.2 DROP
1743                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
1744                 chk_join_nr 1 1 1
1745         fi
1746
1747         # multiple subflows, check that the endpoint corresponding to
1748         # closed subflow (due to reset) is not reused if additional
1749         # subflows are added later
1750         if reset "multi subflows, fair usage on close"; then
1751                 pm_nl_set_limits $ns1 0 1
1752                 pm_nl_set_limits $ns2 0 1
1753                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1754                 filter_tcp_from $ns1 10.0.3.2 REJECT
1755                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
1756
1757                 # mpj subflow will be in TW after the reset
1758                 wait_attempt_fail $ns2
1759                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
1760                 wait
1761
1762                 # additional subflow could be created only if the PM select
1763                 # the later endpoint, skipping the already used one
1764                 chk_join_nr 1 1 1
1765         fi
1766 }
1767
1768 signal_address_tests()
1769 {
1770         # add_address, unused
1771         if reset "unused signal address"; then
1772                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1773                 run_tests $ns1 $ns2 10.0.1.1
1774                 chk_join_nr 0 0 0
1775                 chk_add_nr 1 1
1776         fi
1777
1778         # accept and use add_addr
1779         if reset "signal address"; then
1780                 pm_nl_set_limits $ns1 0 1
1781                 pm_nl_set_limits $ns2 1 1
1782                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1783                 run_tests $ns1 $ns2 10.0.1.1
1784                 chk_join_nr 1 1 1
1785                 chk_add_nr 1 1
1786         fi
1787
1788         # accept and use add_addr with an additional subflow
1789         # note: signal address in server ns and local addresses in client ns must
1790         # belong to different subnets or one of the listed local address could be
1791         # used for 'add_addr' subflow
1792         if reset "subflow and signal"; then
1793                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1794                 pm_nl_set_limits $ns1 0 2
1795                 pm_nl_set_limits $ns2 1 2
1796                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1797                 run_tests $ns1 $ns2 10.0.1.1
1798                 chk_join_nr 2 2 2
1799                 chk_add_nr 1 1
1800         fi
1801
1802         # accept and use add_addr with additional subflows
1803         if reset "multiple subflows and signal"; then
1804                 pm_nl_set_limits $ns1 0 3
1805                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1806                 pm_nl_set_limits $ns2 1 3
1807                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1808                 pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
1809                 run_tests $ns1 $ns2 10.0.1.1
1810                 chk_join_nr 3 3 3
1811                 chk_add_nr 1 1
1812         fi
1813
1814         # signal addresses
1815         if reset "signal addresses"; then
1816                 pm_nl_set_limits $ns1 3 3
1817                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1818                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
1819                 pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
1820                 pm_nl_set_limits $ns2 3 3
1821                 run_tests $ns1 $ns2 10.0.1.1
1822                 chk_join_nr 3 3 3
1823                 chk_add_nr 3 3
1824         fi
1825
1826         # signal invalid addresses
1827         if reset "signal invalid addresses"; then
1828                 pm_nl_set_limits $ns1 3 3
1829                 pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
1830                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
1831                 pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
1832                 pm_nl_set_limits $ns2 3 3
1833                 run_tests $ns1 $ns2 10.0.1.1
1834                 chk_join_nr 1 1 1
1835                 chk_add_nr 3 3
1836         fi
1837
1838         # signal addresses race test
1839         if reset "signal addresses race test"; then
1840                 pm_nl_set_limits $ns1 4 4
1841                 pm_nl_set_limits $ns2 4 4
1842                 pm_nl_add_endpoint $ns1 10.0.1.1 flags signal
1843                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1844                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
1845                 pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
1846                 pm_nl_add_endpoint $ns2 10.0.1.2 flags signal
1847                 pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
1848                 pm_nl_add_endpoint $ns2 10.0.3.2 flags signal
1849                 pm_nl_add_endpoint $ns2 10.0.4.2 flags signal
1850
1851                 # the peer could possibly miss some addr notification, allow retransmission
1852                 ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
1853                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
1854                 chk_join_nr 3 3 3
1855
1856                 # the server will not signal the address terminating
1857                 # the MPC subflow
1858                 chk_add_nr 3 3
1859         fi
1860 }
1861
1862 link_failure_tests()
1863 {
1864         # accept and use add_addr with additional subflows and link loss
1865         if reset "multiple flows, signal, link failure"; then
1866                 # without any b/w limit each veth could spool the packets and get
1867                 # them acked at xmit time, so that the corresponding subflow will
1868                 # have almost always no outstanding pkts, the scheduler will pick
1869                 # always the first subflow and we will have hard time testing
1870                 # active backup and link switch-over.
1871                 # Let's set some arbitrary (low) virtual link limits.
1872                 init_shapers
1873                 pm_nl_set_limits $ns1 0 3
1874                 pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
1875                 pm_nl_set_limits $ns2 1 3
1876                 pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
1877                 pm_nl_add_endpoint $ns2 10.0.4.2 dev ns2eth4 flags subflow
1878                 run_tests $ns1 $ns2 10.0.1.1 1
1879                 chk_join_nr 3 3 3
1880                 chk_add_nr 1 1
1881                 chk_stale_nr $ns2 1 5 1
1882         fi
1883
1884         # accept and use add_addr with additional subflows and link loss
1885         # for bidirectional transfer
1886         if reset "multi flows, signal, bidi, link fail"; then
1887                 init_shapers
1888                 pm_nl_set_limits $ns1 0 3
1889                 pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
1890                 pm_nl_set_limits $ns2 1 3
1891                 pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
1892                 pm_nl_add_endpoint $ns2 10.0.4.2 dev ns2eth4 flags subflow
1893                 run_tests $ns1 $ns2 10.0.1.1 2
1894                 chk_join_nr 3 3 3
1895                 chk_add_nr 1 1
1896                 chk_stale_nr $ns2 1 -1 1
1897         fi
1898
1899         # 2 subflows plus 1 backup subflow with a lossy link, backup
1900         # will never be used
1901         if reset "backup subflow unused, link failure"; then
1902                 init_shapers
1903                 pm_nl_set_limits $ns1 0 2
1904                 pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
1905                 pm_nl_set_limits $ns2 1 2
1906                 FAILING_LINKS="1"
1907                 pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
1908                 run_tests $ns1 $ns2 10.0.1.1 1
1909                 chk_join_nr 2 2 2
1910                 chk_add_nr 1 1
1911                 chk_link_usage $ns2 ns2eth3 $cinsent 0
1912         fi
1913
1914         # 2 lossy links after half transfer, backup will get half of
1915         # the traffic
1916         if reset "backup flow used, multi links fail"; then
1917                 init_shapers
1918                 pm_nl_set_limits $ns1 0 2
1919                 pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
1920                 pm_nl_set_limits $ns2 1 2
1921                 pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
1922                 FAILING_LINKS="1 2"
1923                 run_tests $ns1 $ns2 10.0.1.1 1
1924                 chk_join_nr 2 2 2
1925                 chk_add_nr 1 1
1926                 chk_stale_nr $ns2 2 4 2
1927                 chk_link_usage $ns2 ns2eth3 $cinsent 50
1928         fi
1929
1930         # use a backup subflow with the first subflow on a lossy link
1931         # for bidirectional transfer
1932         if reset "backup flow used, bidi, link failure"; then
1933                 init_shapers
1934                 pm_nl_set_limits $ns1 0 2
1935                 pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
1936                 pm_nl_set_limits $ns2 1 3
1937                 pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
1938                 FAILING_LINKS="1 2"
1939                 run_tests $ns1 $ns2 10.0.1.1 2
1940                 chk_join_nr 2 2 2
1941                 chk_add_nr 1 1
1942                 chk_stale_nr $ns2 1 -1 2
1943                 chk_link_usage $ns2 ns2eth3 $cinsent 50
1944         fi
1945 }
1946
1947 add_addr_timeout_tests()
1948 {
1949         # add_addr timeout
1950         if reset_with_add_addr_timeout "signal address, ADD_ADDR timeout"; then
1951                 pm_nl_set_limits $ns1 0 1
1952                 pm_nl_set_limits $ns2 1 1
1953                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1954                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow
1955                 chk_join_nr 1 1 1
1956                 chk_add_nr 4 0
1957         fi
1958
1959         # add_addr timeout IPv6
1960         if reset_with_add_addr_timeout "signal address, ADD_ADDR6 timeout" 6; then
1961                 pm_nl_set_limits $ns1 0 1
1962                 pm_nl_set_limits $ns2 1 1
1963                 pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
1964                 run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
1965                 chk_join_nr 1 1 1
1966                 chk_add_nr 4 0
1967         fi
1968
1969         # signal addresses timeout
1970         if reset_with_add_addr_timeout "signal addresses, ADD_ADDR timeout"; then
1971                 pm_nl_set_limits $ns1 2 2
1972                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
1973                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
1974                 pm_nl_set_limits $ns2 2 2
1975                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 speed_10
1976                 chk_join_nr 2 2 2
1977                 chk_add_nr 8 0
1978         fi
1979
1980         # signal invalid addresses timeout
1981         if reset_with_add_addr_timeout "invalid address, ADD_ADDR timeout"; then
1982                 pm_nl_set_limits $ns1 2 2
1983                 pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
1984                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
1985                 pm_nl_set_limits $ns2 2 2
1986                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 speed_10
1987                 chk_join_nr 1 1 1
1988                 chk_add_nr 8 0
1989         fi
1990 }
1991
1992 remove_tests()
1993 {
1994         # single subflow, remove
1995         if reset "remove single subflow"; then
1996                 pm_nl_set_limits $ns1 0 1
1997                 pm_nl_set_limits $ns2 0 1
1998                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
1999                 run_tests $ns1 $ns2 10.0.1.1 0 0 -1 slow
2000                 chk_join_nr 1 1 1
2001                 chk_rm_nr 1 1
2002         fi
2003
2004         # multiple subflows, remove
2005         if reset "remove multiple subflows"; then
2006                 pm_nl_set_limits $ns1 0 2
2007                 pm_nl_set_limits $ns2 0 2
2008                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
2009                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2010                 run_tests $ns1 $ns2 10.0.1.1 0 0 -2 slow
2011                 chk_join_nr 2 2 2
2012                 chk_rm_nr 2 2
2013         fi
2014
2015         # single address, remove
2016         if reset "remove single address"; then
2017                 pm_nl_set_limits $ns1 0 1
2018                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2019                 pm_nl_set_limits $ns2 1 1
2020                 run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
2021                 chk_join_nr 1 1 1
2022                 chk_add_nr 1 1
2023                 chk_rm_nr 1 1 invert
2024         fi
2025
2026         # subflow and signal, remove
2027         if reset "remove subflow and signal"; then
2028                 pm_nl_set_limits $ns1 0 2
2029                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2030                 pm_nl_set_limits $ns2 1 2
2031                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2032                 run_tests $ns1 $ns2 10.0.1.1 0 -1 -1 slow
2033                 chk_join_nr 2 2 2
2034                 chk_add_nr 1 1
2035                 chk_rm_nr 1 1
2036         fi
2037
2038         # subflows and signal, remove
2039         if reset "remove subflows and signal"; then
2040                 pm_nl_set_limits $ns1 0 3
2041                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2042                 pm_nl_set_limits $ns2 1 3
2043                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2044                 pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
2045                 run_tests $ns1 $ns2 10.0.1.1 0 -1 -2 slow
2046                 chk_join_nr 3 3 3
2047                 chk_add_nr 1 1
2048                 chk_rm_nr 2 2
2049         fi
2050
2051         # addresses remove
2052         if reset "remove addresses"; then
2053                 pm_nl_set_limits $ns1 3 3
2054                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal id 250
2055                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
2056                 pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
2057                 pm_nl_set_limits $ns2 3 3
2058                 run_tests $ns1 $ns2 10.0.1.1 0 -3 0 slow
2059                 chk_join_nr 3 3 3
2060                 chk_add_nr 3 3
2061                 chk_rm_nr 3 3 invert
2062         fi
2063
2064         # invalid addresses remove
2065         if reset "remove invalid addresses"; then
2066                 pm_nl_set_limits $ns1 3 3
2067                 pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
2068                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
2069                 pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
2070                 pm_nl_set_limits $ns2 3 3
2071                 run_tests $ns1 $ns2 10.0.1.1 0 -3 0 slow
2072                 chk_join_nr 1 1 1
2073                 chk_add_nr 3 3
2074                 chk_rm_nr 3 1 invert
2075         fi
2076
2077         # subflows and signal, flush
2078         if reset "flush subflows and signal"; then
2079                 pm_nl_set_limits $ns1 0 3
2080                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2081                 pm_nl_set_limits $ns2 1 3
2082                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2083                 pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
2084                 run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
2085                 chk_join_nr 3 3 3
2086                 chk_add_nr 1 1
2087                 chk_rm_nr 1 3 invert simult
2088         fi
2089
2090         # subflows flush
2091         if reset "flush subflows"; then
2092                 pm_nl_set_limits $ns1 3 3
2093                 pm_nl_set_limits $ns2 3 3
2094                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow id 150
2095                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2096                 pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
2097                 run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
2098                 chk_join_nr 3 3 3
2099                 chk_rm_nr 0 3 simult
2100         fi
2101
2102         # addresses flush
2103         if reset "flush addresses"; then
2104                 pm_nl_set_limits $ns1 3 3
2105                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal id 250
2106                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
2107                 pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
2108                 pm_nl_set_limits $ns2 3 3
2109                 run_tests $ns1 $ns2 10.0.1.1 0 -8 -8 slow
2110                 chk_join_nr 3 3 3
2111                 chk_add_nr 3 3
2112                 chk_rm_nr 3 3 invert simult
2113         fi
2114
2115         # invalid addresses flush
2116         if reset "flush invalid addresses"; then
2117                 pm_nl_set_limits $ns1 3 3
2118                 pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
2119                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
2120                 pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
2121                 pm_nl_set_limits $ns2 3 3
2122                 run_tests $ns1 $ns2 10.0.1.1 0 -8 0 slow
2123                 chk_join_nr 1 1 1
2124                 chk_add_nr 3 3
2125                 chk_rm_nr 3 1 invert
2126         fi
2127
2128         # remove id 0 subflow
2129         if reset "remove id 0 subflow"; then
2130                 pm_nl_set_limits $ns1 0 1
2131                 pm_nl_set_limits $ns2 0 1
2132                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2133                 run_tests $ns1 $ns2 10.0.1.1 0 0 -9 slow
2134                 chk_join_nr 1 1 1
2135                 chk_rm_nr 1 1
2136         fi
2137
2138         # remove id 0 address
2139         if reset "remove id 0 address"; then
2140                 pm_nl_set_limits $ns1 0 1
2141                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2142                 pm_nl_set_limits $ns2 1 1
2143                 run_tests $ns1 $ns2 10.0.1.1 0 -9 0 slow
2144                 chk_join_nr 1 1 1
2145                 chk_add_nr 1 1
2146                 chk_rm_nr 1 1 invert
2147         fi
2148 }
2149
2150 add_tests()
2151 {
2152         # add single subflow
2153         if reset "add single subflow"; then
2154                 pm_nl_set_limits $ns1 0 1
2155                 pm_nl_set_limits $ns2 0 1
2156                 run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow
2157                 chk_join_nr 1 1 1
2158         fi
2159
2160         # add signal address
2161         if reset "add signal address"; then
2162                 pm_nl_set_limits $ns1 0 1
2163                 pm_nl_set_limits $ns2 1 1
2164                 run_tests $ns1 $ns2 10.0.1.1 0 1 0 slow
2165                 chk_join_nr 1 1 1
2166                 chk_add_nr 1 1
2167         fi
2168
2169         # add multiple subflows
2170         if reset "add multiple subflows"; then
2171                 pm_nl_set_limits $ns1 0 2
2172                 pm_nl_set_limits $ns2 0 2
2173                 run_tests $ns1 $ns2 10.0.1.1 0 0 2 slow
2174                 chk_join_nr 2 2 2
2175         fi
2176
2177         # add multiple subflows IPv6
2178         if reset "add multiple subflows IPv6"; then
2179                 pm_nl_set_limits $ns1 0 2
2180                 pm_nl_set_limits $ns2 0 2
2181                 run_tests $ns1 $ns2 dead:beef:1::1 0 0 2 slow
2182                 chk_join_nr 2 2 2
2183         fi
2184
2185         # add multiple addresses IPv6
2186         if reset "add multiple addresses IPv6"; then
2187                 pm_nl_set_limits $ns1 0 2
2188                 pm_nl_set_limits $ns2 2 2
2189                 run_tests $ns1 $ns2 dead:beef:1::1 0 2 0 slow
2190                 chk_join_nr 2 2 2
2191                 chk_add_nr 2 2
2192         fi
2193 }
2194
2195 ipv6_tests()
2196 {
2197         # subflow IPv6
2198         if reset "single subflow IPv6"; then
2199                 pm_nl_set_limits $ns1 0 1
2200                 pm_nl_set_limits $ns2 0 1
2201                 pm_nl_add_endpoint $ns2 dead:beef:3::2 dev ns2eth3 flags subflow
2202                 run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
2203                 chk_join_nr 1 1 1
2204         fi
2205
2206         # add_address, unused IPv6
2207         if reset "unused signal address IPv6"; then
2208                 pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
2209                 run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
2210                 chk_join_nr 0 0 0
2211                 chk_add_nr 1 1
2212         fi
2213
2214         # signal address IPv6
2215         if reset "single address IPv6"; then
2216                 pm_nl_set_limits $ns1 0 1
2217                 pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
2218                 pm_nl_set_limits $ns2 1 1
2219                 run_tests $ns1 $ns2 dead:beef:1::1 0 0 0 slow
2220                 chk_join_nr 1 1 1
2221                 chk_add_nr 1 1
2222         fi
2223
2224         # single address IPv6, remove
2225         if reset "remove single address IPv6"; then
2226                 pm_nl_set_limits $ns1 0 1
2227                 pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
2228                 pm_nl_set_limits $ns2 1 1
2229                 run_tests $ns1 $ns2 dead:beef:1::1 0 -1 0 slow
2230                 chk_join_nr 1 1 1
2231                 chk_add_nr 1 1
2232                 chk_rm_nr 1 1 invert
2233         fi
2234
2235         # subflow and signal IPv6, remove
2236         if reset "remove subflow and signal IPv6"; then
2237                 pm_nl_set_limits $ns1 0 2
2238                 pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
2239                 pm_nl_set_limits $ns2 1 2
2240                 pm_nl_add_endpoint $ns2 dead:beef:3::2 dev ns2eth3 flags subflow
2241                 run_tests $ns1 $ns2 dead:beef:1::1 0 -1 -1 slow
2242                 chk_join_nr 2 2 2
2243                 chk_add_nr 1 1
2244                 chk_rm_nr 1 1
2245         fi
2246 }
2247
2248 v4mapped_tests()
2249 {
2250         # subflow IPv4-mapped to IPv4-mapped
2251         if reset "single subflow IPv4-mapped"; then
2252                 pm_nl_set_limits $ns1 0 1
2253                 pm_nl_set_limits $ns2 0 1
2254                 pm_nl_add_endpoint $ns2 "::ffff:10.0.3.2" flags subflow
2255                 run_tests $ns1 $ns2 "::ffff:10.0.1.1"
2256                 chk_join_nr 1 1 1
2257         fi
2258
2259         # signal address IPv4-mapped with IPv4-mapped sk
2260         if reset "signal address IPv4-mapped"; then
2261                 pm_nl_set_limits $ns1 0 1
2262                 pm_nl_set_limits $ns2 1 1
2263                 pm_nl_add_endpoint $ns1 "::ffff:10.0.2.1" flags signal
2264                 run_tests $ns1 $ns2 "::ffff:10.0.1.1"
2265                 chk_join_nr 1 1 1
2266                 chk_add_nr 1 1
2267         fi
2268
2269         # subflow v4-map-v6
2270         if reset "single subflow v4-map-v6"; then
2271                 pm_nl_set_limits $ns1 0 1
2272                 pm_nl_set_limits $ns2 0 1
2273                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2274                 run_tests $ns1 $ns2 "::ffff:10.0.1.1"
2275                 chk_join_nr 1 1 1
2276         fi
2277
2278         # signal address v4-map-v6
2279         if reset "signal address v4-map-v6"; then
2280                 pm_nl_set_limits $ns1 0 1
2281                 pm_nl_set_limits $ns2 1 1
2282                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2283                 run_tests $ns1 $ns2 "::ffff:10.0.1.1"
2284                 chk_join_nr 1 1 1
2285                 chk_add_nr 1 1
2286         fi
2287
2288         # subflow v6-map-v4
2289         if reset "single subflow v6-map-v4"; then
2290                 pm_nl_set_limits $ns1 0 1
2291                 pm_nl_set_limits $ns2 0 1
2292                 pm_nl_add_endpoint $ns2 "::ffff:10.0.3.2" flags subflow
2293                 run_tests $ns1 $ns2 10.0.1.1
2294                 chk_join_nr 1 1 1
2295         fi
2296
2297         # signal address v6-map-v4
2298         if reset "signal address v6-map-v4"; then
2299                 pm_nl_set_limits $ns1 0 1
2300                 pm_nl_set_limits $ns2 1 1
2301                 pm_nl_add_endpoint $ns1 "::ffff:10.0.2.1" flags signal
2302                 run_tests $ns1 $ns2 10.0.1.1
2303                 chk_join_nr 1 1 1
2304                 chk_add_nr 1 1
2305         fi
2306
2307         # no subflow IPv6 to v4 address
2308         if reset "no JOIN with diff families v4-v6"; then
2309                 pm_nl_set_limits $ns1 0 1
2310                 pm_nl_set_limits $ns2 0 1
2311                 pm_nl_add_endpoint $ns2 dead:beef:2::2 flags subflow
2312                 run_tests $ns1 $ns2 10.0.1.1
2313                 chk_join_nr 0 0 0
2314         fi
2315
2316         # no subflow IPv6 to v4 address even if v6 has a valid v4 at the end
2317         if reset "no JOIN with diff families v4-v6-2"; then
2318                 pm_nl_set_limits $ns1 0 1
2319                 pm_nl_set_limits $ns2 0 1
2320                 pm_nl_add_endpoint $ns2 dead:beef:2::10.0.3.2 flags subflow
2321                 run_tests $ns1 $ns2 10.0.1.1
2322                 chk_join_nr 0 0 0
2323         fi
2324
2325         # no subflow IPv4 to v6 address, no need to slow down too then
2326         if reset "no JOIN with diff families v6-v4"; then
2327                 pm_nl_set_limits $ns1 0 1
2328                 pm_nl_set_limits $ns2 0 1
2329                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2330                 run_tests $ns1 $ns2 dead:beef:1::1
2331                 chk_join_nr 0 0 0
2332         fi
2333 }
2334
2335 backup_tests()
2336 {
2337         # single subflow, backup
2338         if reset "single subflow, backup"; then
2339                 pm_nl_set_limits $ns1 0 1
2340                 pm_nl_set_limits $ns2 0 1
2341                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
2342                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup
2343                 chk_join_nr 1 1 1
2344                 chk_prio_nr 0 1
2345         fi
2346
2347         # single address, backup
2348         if reset "single address, backup"; then
2349                 pm_nl_set_limits $ns1 0 1
2350                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2351                 pm_nl_set_limits $ns2 1 1
2352                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
2353                 chk_join_nr 1 1 1
2354                 chk_add_nr 1 1
2355                 chk_prio_nr 1 1
2356         fi
2357
2358         # single address with port, backup
2359         if reset "single address with port, backup"; then
2360                 pm_nl_set_limits $ns1 0 1
2361                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2362                 pm_nl_set_limits $ns2 1 1
2363                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
2364                 chk_join_nr 1 1 1
2365                 chk_add_nr 1 1
2366                 chk_prio_nr 1 1
2367         fi
2368 }
2369
2370 add_addr_ports_tests()
2371 {
2372         # signal address with port
2373         if reset "signal address with port"; then
2374                 pm_nl_set_limits $ns1 0 1
2375                 pm_nl_set_limits $ns2 1 1
2376                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2377                 run_tests $ns1 $ns2 10.0.1.1
2378                 chk_join_nr 1 1 1
2379                 chk_add_nr 1 1 1
2380         fi
2381
2382         # subflow and signal with port
2383         if reset "subflow and signal with port"; then
2384                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2385                 pm_nl_set_limits $ns1 0 2
2386                 pm_nl_set_limits $ns2 1 2
2387                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2388                 run_tests $ns1 $ns2 10.0.1.1
2389                 chk_join_nr 2 2 2
2390                 chk_add_nr 1 1 1
2391         fi
2392
2393         # single address with port, remove
2394         if reset "remove single address with port"; then
2395                 pm_nl_set_limits $ns1 0 1
2396                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2397                 pm_nl_set_limits $ns2 1 1
2398                 run_tests $ns1 $ns2 10.0.1.1 0 -1 0 slow
2399                 chk_join_nr 1 1 1
2400                 chk_add_nr 1 1 1
2401                 chk_rm_nr 1 1 invert
2402         fi
2403
2404         # subflow and signal with port, remove
2405         if reset "remove subflow and signal with port"; then
2406                 pm_nl_set_limits $ns1 0 2
2407                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2408                 pm_nl_set_limits $ns2 1 2
2409                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2410                 run_tests $ns1 $ns2 10.0.1.1 0 -1 -1 slow
2411                 chk_join_nr 2 2 2
2412                 chk_add_nr 1 1 1
2413                 chk_rm_nr 1 1
2414         fi
2415
2416         # subflows and signal with port, flush
2417         if reset "flush subflows and signal with port"; then
2418                 pm_nl_set_limits $ns1 0 3
2419                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2420                 pm_nl_set_limits $ns2 1 3
2421                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2422                 pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
2423                 run_tests $ns1 $ns2 10.0.1.1 0 -8 -2 slow
2424                 chk_join_nr 3 3 3
2425                 chk_add_nr 1 1
2426                 chk_rm_nr 1 3 invert simult
2427         fi
2428
2429         # multiple addresses with port
2430         if reset "multiple addresses with port"; then
2431                 pm_nl_set_limits $ns1 2 2
2432                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2433                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal port 10100
2434                 pm_nl_set_limits $ns2 2 2
2435                 run_tests $ns1 $ns2 10.0.1.1
2436                 chk_join_nr 2 2 2
2437                 chk_add_nr 2 2 2
2438         fi
2439
2440         # multiple addresses with ports
2441         if reset "multiple addresses with ports"; then
2442                 pm_nl_set_limits $ns1 2 2
2443                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
2444                 pm_nl_add_endpoint $ns1 10.0.3.1 flags signal port 10101
2445                 pm_nl_set_limits $ns2 2 2
2446                 run_tests $ns1 $ns2 10.0.1.1
2447                 chk_join_nr 2 2 2
2448                 chk_add_nr 2 2 2
2449         fi
2450 }
2451
2452 syncookies_tests()
2453 {
2454         # single subflow, syncookies
2455         if reset_with_cookies "single subflow with syn cookies"; then
2456                 pm_nl_set_limits $ns1 0 1
2457                 pm_nl_set_limits $ns2 0 1
2458                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2459                 run_tests $ns1 $ns2 10.0.1.1
2460                 chk_join_nr 1 1 1
2461         fi
2462
2463         # multiple subflows with syn cookies
2464         if reset_with_cookies "multiple subflows with syn cookies"; then
2465                 pm_nl_set_limits $ns1 0 2
2466                 pm_nl_set_limits $ns2 0 2
2467                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2468                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
2469                 run_tests $ns1 $ns2 10.0.1.1
2470                 chk_join_nr 2 2 2
2471         fi
2472
2473         # multiple subflows limited by server
2474         if reset_with_cookies "subflows limited by server w cookies"; then
2475                 pm_nl_set_limits $ns1 0 1
2476                 pm_nl_set_limits $ns2 0 2
2477                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2478                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
2479                 run_tests $ns1 $ns2 10.0.1.1
2480                 chk_join_nr 2 1 1
2481         fi
2482
2483         # test signal address with cookies
2484         if reset_with_cookies "signal address with syn cookies"; then
2485                 pm_nl_set_limits $ns1 0 1
2486                 pm_nl_set_limits $ns2 1 1
2487                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2488                 run_tests $ns1 $ns2 10.0.1.1
2489                 chk_join_nr 1 1 1
2490                 chk_add_nr 1 1
2491         fi
2492
2493         # test cookie with subflow and signal
2494         if reset_with_cookies "subflow and signal w cookies"; then
2495                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2496                 pm_nl_set_limits $ns1 0 2
2497                 pm_nl_set_limits $ns2 1 2
2498                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2499                 run_tests $ns1 $ns2 10.0.1.1
2500                 chk_join_nr 2 2 2
2501                 chk_add_nr 1 1
2502         fi
2503
2504         # accept and use add_addr with additional subflows
2505         if reset_with_cookies "subflows and signal w. cookies"; then
2506                 pm_nl_set_limits $ns1 0 3
2507                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2508                 pm_nl_set_limits $ns2 1 3
2509                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2510                 pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
2511                 run_tests $ns1 $ns2 10.0.1.1
2512                 chk_join_nr 3 3 3
2513                 chk_add_nr 1 1
2514         fi
2515 }
2516
2517 checksum_tests()
2518 {
2519         # checksum test 0 0
2520         if reset_with_checksum 0 0; then
2521                 pm_nl_set_limits $ns1 0 1
2522                 pm_nl_set_limits $ns2 0 1
2523                 run_tests $ns1 $ns2 10.0.1.1
2524                 chk_join_nr 0 0 0
2525         fi
2526
2527         # checksum test 1 1
2528         if reset_with_checksum 1 1; then
2529                 pm_nl_set_limits $ns1 0 1
2530                 pm_nl_set_limits $ns2 0 1
2531                 run_tests $ns1 $ns2 10.0.1.1
2532                 chk_join_nr 0 0 0
2533         fi
2534
2535         # checksum test 0 1
2536         if reset_with_checksum 0 1; then
2537                 pm_nl_set_limits $ns1 0 1
2538                 pm_nl_set_limits $ns2 0 1
2539                 run_tests $ns1 $ns2 10.0.1.1
2540                 chk_join_nr 0 0 0
2541         fi
2542
2543         # checksum test 1 0
2544         if reset_with_checksum 1 0; then
2545                 pm_nl_set_limits $ns1 0 1
2546                 pm_nl_set_limits $ns2 0 1
2547                 run_tests $ns1 $ns2 10.0.1.1
2548                 chk_join_nr 0 0 0
2549         fi
2550 }
2551
2552 deny_join_id0_tests()
2553 {
2554         # subflow allow join id0 ns1
2555         if reset_with_allow_join_id0 "single subflow allow join id0 ns1" 1 0; then
2556                 pm_nl_set_limits $ns1 1 1
2557                 pm_nl_set_limits $ns2 1 1
2558                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2559                 run_tests $ns1 $ns2 10.0.1.1
2560                 chk_join_nr 1 1 1
2561         fi
2562
2563         # subflow allow join id0 ns2
2564         if reset_with_allow_join_id0 "single subflow allow join id0 ns2" 0 1; then
2565                 pm_nl_set_limits $ns1 1 1
2566                 pm_nl_set_limits $ns2 1 1
2567                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2568                 run_tests $ns1 $ns2 10.0.1.1
2569                 chk_join_nr 0 0 0
2570         fi
2571
2572         # signal address allow join id0 ns1
2573         # ADD_ADDRs are not affected by allow_join_id0 value.
2574         if reset_with_allow_join_id0 "signal address allow join id0 ns1" 1 0; then
2575                 pm_nl_set_limits $ns1 1 1
2576                 pm_nl_set_limits $ns2 1 1
2577                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2578                 run_tests $ns1 $ns2 10.0.1.1
2579                 chk_join_nr 1 1 1
2580                 chk_add_nr 1 1
2581         fi
2582
2583         # signal address allow join id0 ns2
2584         # ADD_ADDRs are not affected by allow_join_id0 value.
2585         if reset_with_allow_join_id0 "signal address allow join id0 ns2" 0 1; then
2586                 pm_nl_set_limits $ns1 1 1
2587                 pm_nl_set_limits $ns2 1 1
2588                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2589                 run_tests $ns1 $ns2 10.0.1.1
2590                 chk_join_nr 1 1 1
2591                 chk_add_nr 1 1
2592         fi
2593
2594         # subflow and address allow join id0 ns1
2595         if reset_with_allow_join_id0 "subflow and address allow join id0 1" 1 0; then
2596                 pm_nl_set_limits $ns1 2 2
2597                 pm_nl_set_limits $ns2 2 2
2598                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2599                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2600                 run_tests $ns1 $ns2 10.0.1.1
2601                 chk_join_nr 2 2 2
2602         fi
2603
2604         # subflow and address allow join id0 ns2
2605         if reset_with_allow_join_id0 "subflow and address allow join id0 2" 0 1; then
2606                 pm_nl_set_limits $ns1 2 2
2607                 pm_nl_set_limits $ns2 2 2
2608                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2609                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2610                 run_tests $ns1 $ns2 10.0.1.1
2611                 chk_join_nr 1 1 1
2612         fi
2613 }
2614
2615 fullmesh_tests()
2616 {
2617         # fullmesh 1
2618         # 2 fullmesh addrs in ns2, added before the connection,
2619         # 1 non-fullmesh addr in ns1, added during the connection.
2620         if reset "fullmesh test 2x1"; then
2621                 pm_nl_set_limits $ns1 0 4
2622                 pm_nl_set_limits $ns2 1 4
2623                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,fullmesh
2624                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,fullmesh
2625                 run_tests $ns1 $ns2 10.0.1.1 0 1 0 slow
2626                 chk_join_nr 4 4 4
2627                 chk_add_nr 1 1
2628         fi
2629
2630         # fullmesh 2
2631         # 1 non-fullmesh addr in ns1, added before the connection,
2632         # 1 fullmesh addr in ns2, added during the connection.
2633         if reset "fullmesh test 1x1"; then
2634                 pm_nl_set_limits $ns1 1 3
2635                 pm_nl_set_limits $ns2 1 3
2636                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2637                 run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow
2638                 chk_join_nr 3 3 3
2639                 chk_add_nr 1 1
2640         fi
2641
2642         # fullmesh 3
2643         # 1 non-fullmesh addr in ns1, added before the connection,
2644         # 2 fullmesh addrs in ns2, added during the connection.
2645         if reset "fullmesh test 1x2"; then
2646                 pm_nl_set_limits $ns1 2 5
2647                 pm_nl_set_limits $ns2 1 5
2648                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2649                 run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
2650                 chk_join_nr 5 5 5
2651                 chk_add_nr 1 1
2652         fi
2653
2654         # fullmesh 4
2655         # 1 non-fullmesh addr in ns1, added before the connection,
2656         # 2 fullmesh addrs in ns2, added during the connection,
2657         # limit max_subflows to 4.
2658         if reset "fullmesh test 1x2, limited"; then
2659                 pm_nl_set_limits $ns1 2 4
2660                 pm_nl_set_limits $ns2 1 4
2661                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2662                 run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_2 slow
2663                 chk_join_nr 4 4 4
2664                 chk_add_nr 1 1
2665         fi
2666
2667         # set fullmesh flag
2668         if reset "set fullmesh flag test"; then
2669                 pm_nl_set_limits $ns1 4 4
2670                 pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
2671                 pm_nl_set_limits $ns2 4 4
2672                 run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow fullmesh
2673                 chk_join_nr 2 2 2
2674                 chk_rm_nr 0 1
2675         fi
2676
2677         # set nofullmesh flag
2678         if reset "set nofullmesh flag test"; then
2679                 pm_nl_set_limits $ns1 4 4
2680                 pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow,fullmesh
2681                 pm_nl_set_limits $ns2 4 4
2682                 run_tests $ns1 $ns2 10.0.1.1 0 0 fullmesh_1 slow nofullmesh
2683                 chk_join_nr 2 2 2
2684                 chk_rm_nr 0 1
2685         fi
2686
2687         # set backup,fullmesh flags
2688         if reset "set backup,fullmesh flags test"; then
2689                 pm_nl_set_limits $ns1 4 4
2690                 pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
2691                 pm_nl_set_limits $ns2 4 4
2692                 run_tests $ns1 $ns2 10.0.1.1 0 0 1 slow backup,fullmesh
2693                 chk_join_nr 2 2 2
2694                 chk_prio_nr 0 1
2695                 chk_rm_nr 0 1
2696         fi
2697
2698         # set nobackup,nofullmesh flags
2699         if reset "set nobackup,nofullmesh flags test"; then
2700                 pm_nl_set_limits $ns1 4 4
2701                 pm_nl_set_limits $ns2 4 4
2702                 pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,backup,fullmesh
2703                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow nobackup,nofullmesh
2704                 chk_join_nr 2 2 2
2705                 chk_prio_nr 0 1
2706                 chk_rm_nr 0 1
2707         fi
2708 }
2709
2710 fastclose_tests()
2711 {
2712         if reset "fastclose test"; then
2713                 run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_2
2714                 chk_join_nr 0 0 0
2715                 chk_fclose_nr 1 1
2716                 chk_rst_nr 1 1 invert
2717         fi
2718 }
2719
2720 pedit_action_pkts()
2721 {
2722         tc -n $ns2 -j -s action show action pedit index 100 | \
2723                 grep "packets" | \
2724                 sed 's/.*"packets":\([0-9]\+\),.*/\1/'
2725 }
2726
2727 fail_tests()
2728 {
2729         # single subflow
2730         if reset_with_fail "Infinite map" 1; then
2731                 run_tests $ns1 $ns2 10.0.1.1 128
2732                 chk_join_nr 0 0 0 +1 +0 1 0 1 "$(pedit_action_pkts)"
2733                 chk_fail_nr 1 -1 invert
2734         fi
2735
2736         # multiple subflows
2737         if reset_with_fail "MP_FAIL MP_RST" 2; then
2738                 tc -n $ns2 qdisc add dev ns2eth1 root netem rate 1mbit delay 5
2739                 pm_nl_set_limits $ns1 0 1
2740                 pm_nl_set_limits $ns2 0 1
2741                 pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
2742                 run_tests $ns1 $ns2 10.0.1.1 1024
2743                 chk_join_nr 1 1 1 1 0 1 1 0 "$(pedit_action_pkts)"
2744         fi
2745 }
2746
2747 userspace_tests()
2748 {
2749         # userspace pm type prevents add_addr
2750         if reset "userspace pm type prevents add_addr"; then
2751                 set_userspace_pm $ns1
2752                 pm_nl_set_limits $ns1 0 2
2753                 pm_nl_set_limits $ns2 0 2
2754                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2755                 run_tests $ns1 $ns2 10.0.1.1
2756                 chk_join_nr 0 0 0
2757                 chk_add_nr 0 0
2758         fi
2759
2760         # userspace pm type does not echo add_addr without daemon
2761         if reset "userspace pm no echo w/o daemon"; then
2762                 set_userspace_pm $ns2
2763                 pm_nl_set_limits $ns1 0 2
2764                 pm_nl_set_limits $ns2 0 2
2765                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2766                 run_tests $ns1 $ns2 10.0.1.1
2767                 chk_join_nr 0 0 0
2768                 chk_add_nr 1 0
2769         fi
2770
2771         # userspace pm type rejects join
2772         if reset "userspace pm type rejects join"; then
2773                 set_userspace_pm $ns1
2774                 pm_nl_set_limits $ns1 1 1
2775                 pm_nl_set_limits $ns2 1 1
2776                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2777                 run_tests $ns1 $ns2 10.0.1.1
2778                 chk_join_nr 1 1 0
2779         fi
2780
2781         # userspace pm type does not send join
2782         if reset "userspace pm type does not send join"; then
2783                 set_userspace_pm $ns2
2784                 pm_nl_set_limits $ns1 1 1
2785                 pm_nl_set_limits $ns2 1 1
2786                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2787                 run_tests $ns1 $ns2 10.0.1.1
2788                 chk_join_nr 0 0 0
2789         fi
2790
2791         # userspace pm type prevents mp_prio
2792         if reset "userspace pm type prevents mp_prio"; then
2793                 set_userspace_pm $ns1
2794                 pm_nl_set_limits $ns1 1 1
2795                 pm_nl_set_limits $ns2 1 1
2796                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2797                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow backup
2798                 chk_join_nr 1 1 0
2799                 chk_prio_nr 0 0
2800         fi
2801
2802         # userspace pm type prevents rm_addr
2803         if reset "userspace pm type prevents rm_addr"; then
2804                 set_userspace_pm $ns1
2805                 set_userspace_pm $ns2
2806                 pm_nl_set_limits $ns1 0 1
2807                 pm_nl_set_limits $ns2 0 1
2808                 pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
2809                 run_tests $ns1 $ns2 10.0.1.1 0 0 -1 slow
2810                 chk_join_nr 0 0 0
2811                 chk_rm_nr 0 0
2812         fi
2813 }
2814
2815 endpoint_tests()
2816 {
2817         # userspace pm type prevents add_addr
2818         if reset "implicit EP"; then
2819                 pm_nl_set_limits $ns1 2 2
2820                 pm_nl_set_limits $ns2 2 2
2821                 pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
2822                 run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
2823
2824                 wait_mpj $ns1
2825                 pm_nl_check_endpoint 1 "creation" \
2826                         $ns2 10.0.2.2 id 1 flags implicit
2827
2828                 pm_nl_add_endpoint $ns2 10.0.2.2 id 33
2829                 pm_nl_check_endpoint 0 "ID change is prevented" \
2830                         $ns2 10.0.2.2 id 1 flags implicit
2831
2832                 pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
2833                 pm_nl_check_endpoint 0 "modif is allowed" \
2834                         $ns2 10.0.2.2 id 1 flags signal
2835                 wait
2836         fi
2837
2838         if reset "delete and re-add"; then
2839                 pm_nl_set_limits $ns1 1 1
2840                 pm_nl_set_limits $ns2 1 1
2841                 pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
2842                 run_tests $ns1 $ns2 10.0.1.1 4 0 0 slow &
2843
2844                 wait_mpj $ns2
2845                 pm_nl_del_endpoint $ns2 2 10.0.2.2
2846                 sleep 0.5
2847                 chk_subflow_nr needtitle "after delete" 1
2848
2849                 pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
2850                 wait_mpj $ns2
2851                 chk_subflow_nr "" "after re-add" 2
2852                 wait
2853         fi
2854 }
2855
2856 # [$1: error message]
2857 usage()
2858 {
2859         if [ -n "${1}" ]; then
2860                 echo "${1}"
2861                 ret=1
2862         fi
2863
2864         echo "mptcp_join usage:"
2865
2866         local key
2867         for key in "${!all_tests[@]}"; do
2868                 echo "  -${key} ${all_tests[${key}]}"
2869         done
2870
2871         echo "  -c capture pcap files"
2872         echo "  -C enable data checksum"
2873         echo "  -i use ip mptcp"
2874         echo "  -h help"
2875
2876         echo "[test ids|names]"
2877
2878         exit ${ret}
2879 }
2880
2881
2882 # Use a "simple" array to force an specific order we cannot have with an associative one
2883 all_tests_sorted=(
2884         f@subflows_tests
2885         e@subflows_error_tests
2886         s@signal_address_tests
2887         l@link_failure_tests
2888         t@add_addr_timeout_tests
2889         r@remove_tests
2890         a@add_tests
2891         6@ipv6_tests
2892         4@v4mapped_tests
2893         b@backup_tests
2894         p@add_addr_ports_tests
2895         k@syncookies_tests
2896         S@checksum_tests
2897         d@deny_join_id0_tests
2898         m@fullmesh_tests
2899         z@fastclose_tests
2900         F@fail_tests
2901         u@userspace_tests
2902         I@endpoint_tests
2903 )
2904
2905 all_tests_args=""
2906 all_tests_names=()
2907 for subtests in "${all_tests_sorted[@]}"; do
2908         key="${subtests%@*}"
2909         value="${subtests#*@}"
2910
2911         all_tests_args+="${key}"
2912         all_tests_names+=("${value}")
2913         all_tests[${key}]="${value}"
2914 done
2915
2916 tests=()
2917 while getopts "${all_tests_args}cCih" opt; do
2918         case $opt in
2919                 ["${all_tests_args}"])
2920                         tests+=("${all_tests[${opt}]}")
2921                         ;;
2922                 c)
2923                         capture=1
2924                         ;;
2925                 C)
2926                         checksum=1
2927                         ;;
2928                 i)
2929                         ip_mptcp=1
2930                         ;;
2931                 h)
2932                         usage
2933                         ;;
2934                 *)
2935                         usage "Unknown option: -${opt}"
2936                         ;;
2937         esac
2938 done
2939
2940 shift $((OPTIND - 1))
2941
2942 for arg in "${@}"; do
2943         if [[ "${arg}" =~ ^[0-9]+$ ]]; then
2944                 only_tests_ids+=("${arg}")
2945         else
2946                 only_tests_names+=("${arg}")
2947         fi
2948 done
2949
2950 if [ ${#tests[@]} -eq 0 ]; then
2951         tests=("${all_tests_names[@]}")
2952 fi
2953
2954 for subtests in "${tests[@]}"; do
2955         "${subtests}"
2956 done
2957
2958 if [ ${ret} -ne 0 ]; then
2959         echo
2960         echo "${#failed_tests[@]} failure(s) has(ve) been detected:"
2961         for i in $(get_failed_tests_ids); do
2962                 echo -e "\t- ${i}: ${failed_tests[${i}]}"
2963         done
2964         echo
2965 fi
2966
2967 exit $ret