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