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