• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4. "$(dirname "${0}")/mptcp_lib.sh"
5
6mptcp_lib_check_mptcp
7
8if ! mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
9	echo "userspace pm tests are not supported by the kernel: SKIP"
10	exit ${KSFT_SKIP}
11fi
12
13ip -Version > /dev/null 2>&1
14if [ $? -ne 0 ];then
15	echo "SKIP: Cannot not run test without ip tool"
16	exit ${KSFT_SKIP}
17fi
18
19ANNOUNCED=6        # MPTCP_EVENT_ANNOUNCED
20REMOVED=7          # MPTCP_EVENT_REMOVED
21SUB_ESTABLISHED=10 # MPTCP_EVENT_SUB_ESTABLISHED
22SUB_CLOSED=11      # MPTCP_EVENT_SUB_CLOSED
23
24AF_INET=2
25AF_INET6=10
26
27evts_pid=0
28client4_pid=0
29server4_pid=0
30client6_pid=0
31server6_pid=0
32client4_token=""
33server4_token=""
34client6_token=""
35server6_token=""
36client4_port=0;
37client6_port=0;
38app4_port=50002
39new4_port=50003
40app6_port=50004
41client_addr_id=${RANDOM:0:2}
42server_addr_id=${RANDOM:0:2}
43
44sec=$(date +%s)
45rndh=$(stdbuf -o0 -e0 printf %x "$sec")-$(mktemp -u XXXXXX)
46ns1="ns1-$rndh"
47ns2="ns2-$rndh"
48
49kill_wait()
50{
51	kill $1 > /dev/null 2>&1
52	wait $1 2>/dev/null
53}
54
55cleanup()
56{
57	echo "cleanup"
58
59	rm -rf $file
60
61	# Terminate the MPTCP connection and related processes
62	if [ $client4_pid -ne 0 ]; then
63		kill -SIGUSR1 $client4_pid > /dev/null 2>&1
64	fi
65	if [ $server4_pid -ne 0 ]; then
66		kill_wait $server4_pid
67	fi
68	if [ $client6_pid -ne 0 ]; then
69		kill -SIGUSR1 $client6_pid > /dev/null 2>&1
70	fi
71	if [ $server6_pid -ne 0 ]; then
72		kill_wait $server6_pid
73	fi
74	if [ $evts_pid -ne 0 ]; then
75		kill_wait $evts_pid
76	fi
77	local netns
78	for netns in "$ns1" "$ns2" ;do
79		ip netns del "$netns"
80	done
81}
82
83trap cleanup EXIT
84
85# Create and configure network namespaces for testing
86for i in "$ns1" "$ns2" ;do
87	ip netns add "$i" || exit 1
88	ip -net "$i" link set lo up
89	ip netns exec "$i" sysctl -q net.mptcp.enabled=1
90	ip netns exec "$i" sysctl -q net.mptcp.pm_type=1
91done
92
93#  "$ns1"              ns2
94#     ns1eth2    ns2eth1
95
96ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
97
98# Add IPv4/v6 addresses to the namespaces
99ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth2
100ip -net "$ns1" addr add 10.0.2.1/24 dev ns1eth2
101ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth2 nodad
102ip -net "$ns1" addr add dead:beef:2::1/64 dev ns1eth2 nodad
103ip -net "$ns1" link set ns1eth2 up
104
105ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1
106ip -net "$ns2" addr add 10.0.2.2/24 dev ns2eth1
107ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad
108ip -net "$ns2" addr add dead:beef:2::2/64 dev ns2eth1 nodad
109ip -net "$ns2" link set ns2eth1 up
110
111stdbuf -o0 -e0 printf "Created network namespaces ns1, ns2         \t\t\t[OK]\n"
112
113make_file()
114{
115	# Store a chunk of data in a file to transmit over an MPTCP connection
116	local name=$1
117	local ksize=1
118
119	dd if=/dev/urandom of="$name" bs=2 count=$ksize 2> /dev/null
120	echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
121}
122
123make_connection()
124{
125	local file
126	file=$(mktemp)
127	make_file "$file" "client"
128
129	local is_v6=$1
130	local app_port=$app4_port
131	local connect_addr="10.0.1.1"
132	local listen_addr="0.0.0.0"
133	if [ "$is_v6" = "v6" ]
134	then
135		connect_addr="dead:beef:1::1"
136		listen_addr="::"
137		app_port=$app6_port
138	else
139		is_v6="v4"
140	fi
141
142	# Capture netlink events over the two network namespaces running
143	# the MPTCP client and server
144	local client_evts
145	client_evts=$(mktemp)
146	:>"$client_evts"
147	ip netns exec "$ns2" ./pm_nl_ctl events >> "$client_evts" 2>&1 &
148	local client_evts_pid=$!
149	local server_evts
150	server_evts=$(mktemp)
151	:>"$server_evts"
152	ip netns exec "$ns1" ./pm_nl_ctl events >> "$server_evts" 2>&1 &
153	local server_evts_pid=$!
154	sleep 0.5
155
156	# Run the server
157	ip netns exec "$ns1" \
158	   ./mptcp_connect -s MPTCP -w 300 -p $app_port -l $listen_addr > /dev/null 2>&1 &
159	local server_pid=$!
160	sleep 0.5
161
162	# Run the client, transfer $file and stay connected to the server
163	# to conduct tests
164	ip netns exec "$ns2" \
165	   ./mptcp_connect -s MPTCP -w 300 -m sendfile -p $app_port $connect_addr\
166	   2>&1 > /dev/null < "$file" &
167	local client_pid=$!
168	sleep 1
169
170	# Capture client/server attributes from MPTCP connection netlink events
171	kill_wait $client_evts_pid
172
173	local client_token
174	local client_port
175	local client_serverside
176	local server_token
177	local server_serverside
178
179	client_token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
180	client_port=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
181	client_serverside=$(sed --unbuffered -n 's/.*\(server_side:\)\([[:digit:]]*\).*$/\2/p;q'\
182				      "$client_evts")
183	kill_wait $server_evts_pid
184	server_token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$server_evts")
185	server_serverside=$(sed --unbuffered -n 's/.*\(server_side:\)\([[:digit:]]*\).*$/\2/p;q'\
186				      "$server_evts")
187	rm -f "$client_evts" "$server_evts" "$file"
188
189	if [ "$client_token" != "" ] && [ "$server_token" != "" ] && [ "$client_serverside" = 0 ] &&
190		   [ "$server_serverside" = 1 ]
191	then
192		stdbuf -o0 -e0 printf "Established IP%s MPTCP Connection ns2 => ns1    \t\t[OK]\n" $is_v6
193	else
194		exit 1
195	fi
196
197	if [ "$is_v6" = "v6" ]
198	then
199		client6_token=$client_token
200		server6_token=$server_token
201		client6_port=$client_port
202		client6_pid=$client_pid
203		server6_pid=$server_pid
204	else
205		client4_token=$client_token
206		server4_token=$server_token
207		client4_port=$client_port
208		client4_pid=$client_pid
209		server4_pid=$server_pid
210	fi
211}
212
213verify_announce_event()
214{
215	local evt=$1
216	local e_type=$2
217	local e_token=$3
218	local e_addr=$4
219	local e_id=$5
220	local e_dport=$6
221	local e_af=$7
222	local type
223	local token
224	local addr
225	local dport
226	local id
227
228	type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
229	token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
230	if [ "$e_af" = "v6" ]
231	then
232		addr=$(sed --unbuffered -n 's/.*\(daddr6:\)\([0-9a-f:.]*\).*$/\2/p;q' "$evt")
233	else
234		addr=$(sed --unbuffered -n 's/.*\(daddr4:\)\([0-9.]*\).*$/\2/p;q' "$evt")
235	fi
236	dport=$(sed --unbuffered -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
237	id=$(sed --unbuffered -n 's/.*\(rem_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
238	if [ "$type" = "$e_type" ] && [ "$token" = "$e_token" ] &&
239		   [ "$addr" = "$e_addr" ] && [ "$dport" = "$e_dport" ] &&
240		   [ "$id" = "$e_id" ]
241	then
242		stdbuf -o0 -e0 printf "[OK]\n"
243		return 0
244	fi
245	stdbuf -o0 -e0 printf "[FAIL]\n"
246	exit 1
247}
248
249test_announce()
250{
251	local evts
252	evts=$(mktemp)
253	# Capture events on the network namespace running the server
254	:>"$evts"
255	ip netns exec "$ns1" ./pm_nl_ctl events >> "$evts" 2>&1 &
256	evts_pid=$!
257	sleep 0.5
258
259	# ADD_ADDR using an invalid token should result in no action
260	local invalid_token=$(( client4_token - 1))
261	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token $invalid_token id\
262	   $client_addr_id dev ns2eth1 > /dev/null 2>&1
263
264	local type
265	type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
266	stdbuf -o0 -e0 printf "ADD_ADDR 10.0.2.2 (ns2) => ns1, invalid token    \t\t"
267	if [ "$type" = "" ]
268	then
269		stdbuf -o0 -e0 printf "[OK]\n"
270	else
271		stdbuf -o0 -e0 printf "[FAIL]\n"
272		exit 1
273	fi
274
275	# ADD_ADDR from the client to server machine reusing the subflow port
276	:>"$evts"
277	ip netns exec "$ns2"\
278	   ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id $client_addr_id dev\
279	   ns2eth1 > /dev/null 2>&1
280	stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.2 (ns2) => ns1, reuse port \t\t" $client_addr_id
281	sleep 0.5
282	verify_announce_event "$evts" "$ANNOUNCED" "$server4_token" "10.0.2.2" "$client_addr_id"\
283			      "$client4_port"
284
285	# ADD_ADDR6 from the client to server machine reusing the subflow port
286	:>"$evts"
287	ip netns exec "$ns2" ./pm_nl_ctl ann\
288	   dead:beef:2::2 token "$client6_token" id $client_addr_id dev ns2eth1 > /dev/null 2>&1
289	stdbuf -o0 -e0 printf "ADD_ADDR6 id:%d dead:beef:2::2 (ns2) => ns1, reuse port\t\t" $client_addr_id
290	sleep 0.5
291	verify_announce_event "$evts" "$ANNOUNCED" "$server6_token" "dead:beef:2::2"\
292			      "$client_addr_id" "$client6_port" "v6"
293
294	# ADD_ADDR from the client to server machine using a new port
295	:>"$evts"
296	client_addr_id=$((client_addr_id+1))
297	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
298	   $client_addr_id dev ns2eth1 port $new4_port > /dev/null 2>&1
299	stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.2 (ns2) => ns1, new port \t\t\t" $client_addr_id
300	sleep 0.5
301	verify_announce_event "$evts" "$ANNOUNCED" "$server4_token" "10.0.2.2"\
302			      "$client_addr_id" "$new4_port"
303
304	kill_wait $evts_pid
305
306	# Capture events on the network namespace running the client
307	:>"$evts"
308	ip netns exec "$ns2" ./pm_nl_ctl events >> "$evts" 2>&1 &
309	evts_pid=$!
310	sleep 0.5
311
312	# ADD_ADDR from the server to client machine reusing the subflow port
313	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
314	   $server_addr_id dev ns1eth2 > /dev/null 2>&1
315	stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.1 (ns1) => ns2, reuse port \t\t" $server_addr_id
316	sleep 0.5
317	verify_announce_event "$evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
318			      "$server_addr_id" "$app4_port"
319
320	# ADD_ADDR6 from the server to client machine reusing the subflow port
321	:>"$evts"
322	ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
323	   $server_addr_id dev ns1eth2 > /dev/null 2>&1
324	stdbuf -o0 -e0 printf "ADD_ADDR6 id:%d dead:beef:2::1 (ns1) => ns2, reuse port\t\t" $server_addr_id
325	sleep 0.5
326	verify_announce_event "$evts" "$ANNOUNCED" "$client6_token" "dead:beef:2::1"\
327			      "$server_addr_id" "$app6_port" "v6"
328
329	# ADD_ADDR from the server to client machine using a new port
330	:>"$evts"
331	server_addr_id=$((server_addr_id+1))
332	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
333	   $server_addr_id dev ns1eth2 port $new4_port > /dev/null 2>&1
334	stdbuf -o0 -e0 printf "ADD_ADDR id:%d 10.0.2.1 (ns1) => ns2, new port \t\t\t" $server_addr_id
335	sleep 0.5
336	verify_announce_event "$evts" "$ANNOUNCED" "$client4_token" "10.0.2.1"\
337			      "$server_addr_id" "$new4_port"
338
339	kill_wait $evts_pid
340	rm -f "$evts"
341}
342
343verify_remove_event()
344{
345	local evt=$1
346	local e_type=$2
347	local e_token=$3
348	local e_id=$4
349	local type
350	local token
351	local id
352
353	type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
354	token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
355	id=$(sed --unbuffered -n 's/.*\(rem_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
356	if [ "$type" = "$e_type" ] && [ "$token" = "$e_token" ] &&
357		   [ "$id" = "$e_id" ]
358	then
359		stdbuf -o0 -e0 printf "[OK]\n"
360		return 0
361	fi
362	stdbuf -o0 -e0 printf "[FAIL]\n"
363	exit 1
364}
365
366test_remove()
367{
368	local evts
369	evts=$(mktemp)
370
371	# Capture events on the network namespace running the server
372	:>"$evts"
373	ip netns exec "$ns1" ./pm_nl_ctl events >> "$evts" 2>&1 &
374	evts_pid=$!
375	sleep 0.5
376
377	# RM_ADDR using an invalid token should result in no action
378	local invalid_token=$(( client4_token - 1 ))
379	ip netns exec "$ns2" ./pm_nl_ctl rem token $invalid_token id\
380	   $client_addr_id > /dev/null 2>&1
381	stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1, invalid token                    \t"\
382	       $client_addr_id
383	local type
384	type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
385	if [ "$type" = "" ]
386	then
387		stdbuf -o0 -e0 printf "[OK]\n"
388	else
389		stdbuf -o0 -e0 printf "[FAIL]\n"
390		exit 1
391	fi
392
393	# RM_ADDR using an invalid addr id should result in no action
394	local invalid_id=$(( client_addr_id + 1 ))
395	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
396	   $invalid_id > /dev/null 2>&1
397	stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1, invalid id                    \t"\
398	       $invalid_id
399	type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
400	if [ "$type" = "" ]
401	then
402		stdbuf -o0 -e0 printf "[OK]\n"
403	else
404		stdbuf -o0 -e0 printf "[FAIL]\n"
405		exit 1
406	fi
407
408	# RM_ADDR from the client to server machine
409	:>"$evts"
410	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
411	   $client_addr_id > /dev/null 2>&1
412	stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1                                \t"\
413	       $client_addr_id
414	sleep 0.5
415	verify_remove_event "$evts" "$REMOVED" "$server4_token" "$client_addr_id"
416
417	# RM_ADDR from the client to server machine
418	:>"$evts"
419	client_addr_id=$(( client_addr_id - 1 ))
420	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client4_token" id\
421	   $client_addr_id > /dev/null 2>&1
422	stdbuf -o0 -e0 printf "RM_ADDR id:%d ns2 => ns1                                \t"\
423	       $client_addr_id
424	sleep 0.5
425	verify_remove_event "$evts" "$REMOVED" "$server4_token" "$client_addr_id"
426
427	# RM_ADDR6 from the client to server machine
428	:>"$evts"
429	ip netns exec "$ns2" ./pm_nl_ctl rem token "$client6_token" id\
430	   $client_addr_id > /dev/null 2>&1
431	stdbuf -o0 -e0 printf "RM_ADDR6 id:%d ns2 => ns1                               \t"\
432	       $client_addr_id
433	sleep 0.5
434	verify_remove_event "$evts" "$REMOVED" "$server6_token" "$client_addr_id"
435
436	kill_wait $evts_pid
437
438	# Capture events on the network namespace running the client
439	:>"$evts"
440	ip netns exec "$ns2" ./pm_nl_ctl events >> "$evts" 2>&1 &
441	evts_pid=$!
442	sleep 0.5
443
444	# RM_ADDR from the server to client machine
445	ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
446	   $server_addr_id > /dev/null 2>&1
447	stdbuf -o0 -e0 printf "RM_ADDR id:%d ns1 => ns2                                \t"\
448	       $server_addr_id
449	sleep 0.5
450	verify_remove_event "$evts" "$REMOVED" "$client4_token" "$server_addr_id"
451
452	# RM_ADDR from the server to client machine
453	:>"$evts"
454	server_addr_id=$(( server_addr_id - 1 ))
455	ip netns exec "$ns1" ./pm_nl_ctl rem token "$server4_token" id\
456	   $server_addr_id > /dev/null 2>&1
457	stdbuf -o0 -e0 printf "RM_ADDR id:%d ns1 => ns2                                \t" $server_addr_id
458	sleep 0.5
459	verify_remove_event "$evts" "$REMOVED" "$client4_token" "$server_addr_id"
460
461	# RM_ADDR6 from the server to client machine
462	:>"$evts"
463	ip netns exec "$ns1" ./pm_nl_ctl rem token "$server6_token" id\
464	   $server_addr_id > /dev/null 2>&1
465	stdbuf -o0 -e0 printf "RM_ADDR6 id:%d ns1 => ns2                               \t" $server_addr_id
466	sleep 0.5
467	verify_remove_event "$evts" "$REMOVED" "$client6_token" "$server_addr_id"
468
469	kill_wait $evts_pid
470	rm -f "$evts"
471}
472
473verify_subflow_events()
474{
475	local evt=$1
476	local e_type=$2
477	local e_token=$3
478	local e_family=$4
479	local e_saddr=$5
480	local e_daddr=$6
481	local e_dport=$7
482	local e_locid=$8
483	local e_remid=$9
484	shift 2
485	local e_from=$8
486	local e_to=$9
487	local type
488	local token
489	local family
490	local saddr
491	local daddr
492	local dport
493	local locid
494	local remid
495
496	if [ "$e_type" = "$SUB_ESTABLISHED" ]
497	then
498		if [ "$e_family" = "$AF_INET6" ]
499		then
500			stdbuf -o0 -e0 printf "CREATE_SUBFLOW6 %s (%s) => %s (%s)    "\
501			       "$e_saddr" "$e_from" "$e_daddr" "$e_to"
502		else
503			stdbuf -o0 -e0 printf "CREATE_SUBFLOW %s (%s) => %s (%s)         \t"\
504			       "$e_saddr" "$e_from" "$e_daddr" "$e_to"
505		fi
506	else
507		if [ "$e_family" = "$AF_INET6" ]
508		then
509			stdbuf -o0 -e0 printf "DESTROY_SUBFLOW6 %s (%s) => %s (%s)   "\
510			       "$e_saddr" "$e_from" "$e_daddr" "$e_to"
511		else
512			stdbuf -o0 -e0 printf "DESTROY_SUBFLOW %s (%s) => %s (%s)         \t"\
513			       "$e_saddr" "$e_from" "$e_daddr" "$e_to"
514		fi
515	fi
516
517	type=$(sed --unbuffered -n 's/.*\(type:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
518	token=$(sed --unbuffered -n 's/.*\(token:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
519	family=$(sed --unbuffered -n 's/.*\(family:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
520	dport=$(sed --unbuffered -n 's/.*\(dport:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
521	locid=$(sed --unbuffered -n 's/.*\(loc_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
522	remid=$(sed --unbuffered -n 's/.*\(rem_id:\)\([[:digit:]]*\).*$/\2/p;q' "$evt")
523	if [ "$family" = "$AF_INET6" ]
524	then
525		saddr=$(sed --unbuffered -n 's/.*\(saddr6:\)\([0-9a-f:.]*\).*$/\2/p;q' "$evt")
526		daddr=$(sed --unbuffered -n 's/.*\(daddr6:\)\([0-9a-f:.]*\).*$/\2/p;q' "$evt")
527	else
528		saddr=$(sed --unbuffered -n 's/.*\(saddr4:\)\([0-9.]*\).*$/\2/p;q' "$evt")
529		daddr=$(sed --unbuffered -n 's/.*\(daddr4:\)\([0-9.]*\).*$/\2/p;q' "$evt")
530	fi
531
532	if [ "$type" = "$e_type" ] && [ "$token" = "$e_token" ] &&
533		   [ "$daddr" = "$e_daddr" ] && [ "$e_dport" = "$dport" ] &&
534		   [ "$family" = "$e_family" ] && [ "$saddr" = "$e_saddr" ] &&
535		   [ "$e_locid" = "$locid" ] && [ "$e_remid" = "$remid" ]
536	then
537		stdbuf -o0 -e0 printf "[OK]\n"
538		return 0
539	fi
540	stdbuf -o0 -e0 printf "[FAIL]\n"
541	exit 1
542}
543
544test_subflows()
545{
546	local evts
547	evts=$(mktemp)
548	# Capture events on the network namespace running the server
549	:>"$evts"
550	ip netns exec "$ns1" ./pm_nl_ctl events >> "$evts" 2>&1 &
551	evts_pid=$!
552	sleep 0.5
553
554	# Attempt to add a listener at 10.0.2.2:<subflow-port>
555	ip netns exec "$ns2" ./pm_nl_ctl listen 10.0.2.2\
556	   "$client4_port" > /dev/null 2>&1 &
557	local listener_pid=$!
558
559	# ADD_ADDR from client to server machine reusing the subflow port
560	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
561	   $client_addr_id > /dev/null 2>&1
562	sleep 0.5
563
564	# CREATE_SUBFLOW from server to client machine
565	:>"$evts"
566	ip netns exec "$ns1" ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2\
567	   rport "$client4_port" token "$server4_token" > /dev/null 2>&1
568	sleep 0.5
569	verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$server4_token" "$AF_INET" "10.0.2.1"\
570			      "10.0.2.2" "$client4_port" "23" "$client_addr_id" "ns1" "ns2"
571
572	# Delete the listener from the client ns, if one was created
573	kill_wait $listener_pid
574
575	local sport
576	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
577
578	# DESTROY_SUBFLOW from server to client machine
579	:>"$evts"
580	ip netns exec "$ns1" ./pm_nl_ctl dsf lip 10.0.2.1 lport "$sport" rip 10.0.2.2 rport\
581	   "$client4_port" token "$server4_token" > /dev/null 2>&1
582	sleep 0.5
583	verify_subflow_events "$evts" "$SUB_CLOSED" "$server4_token" "$AF_INET" "10.0.2.1"\
584			      "10.0.2.2" "$client4_port" "23" "$client_addr_id" "ns1" "ns2"
585
586	# RM_ADDR from client to server machine
587	ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
588	   "$client4_token" > /dev/null 2>&1
589	sleep 0.5
590
591	# Attempt to add a listener at dead:beef:2::2:<subflow-port>
592	ip netns exec "$ns2" ./pm_nl_ctl listen dead:beef:2::2\
593	   "$client6_port" > /dev/null 2>&1 &
594	listener_pid=$!
595
596	# ADD_ADDR6 from client to server machine reusing the subflow port
597	:>"$evts"
598	ip netns exec "$ns2" ./pm_nl_ctl ann dead:beef:2::2 token "$client6_token" id\
599	   $client_addr_id > /dev/null 2>&1
600	sleep 0.5
601
602	# CREATE_SUBFLOW6 from server to client machine
603	:>"$evts"
604	ip netns exec "$ns1" ./pm_nl_ctl csf lip dead:beef:2::1 lid 23 rip\
605	   dead:beef:2::2 rport "$client6_port" token "$server6_token" > /dev/null 2>&1
606	sleep 0.5
607	verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$server6_token" "$AF_INET6"\
608			      "dead:beef:2::1" "dead:beef:2::2" "$client6_port" "23"\
609			      "$client_addr_id" "ns1" "ns2"
610
611	# Delete the listener from the client ns, if one was created
612	kill_wait $listener_pid
613
614	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
615
616	# DESTROY_SUBFLOW6 from server to client machine
617	:>"$evts"
618	ip netns exec "$ns1" ./pm_nl_ctl dsf lip dead:beef:2::1 lport "$sport" rip\
619	   dead:beef:2::2 rport "$client6_port" token "$server6_token" > /dev/null 2>&1
620	sleep 0.5
621	verify_subflow_events "$evts" "$SUB_CLOSED" "$server6_token" "$AF_INET6"\
622			      "dead:beef:2::1" "dead:beef:2::2" "$client6_port" "23"\
623			      "$client_addr_id" "ns1" "ns2"
624
625	# RM_ADDR from client to server machine
626	ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
627	   "$client6_token" > /dev/null 2>&1
628	sleep 0.5
629
630	# Attempt to add a listener at 10.0.2.2:<new-port>
631	ip netns exec "$ns2" ./pm_nl_ctl listen 10.0.2.2\
632	   $new4_port > /dev/null 2>&1 &
633	listener_pid=$!
634
635	# ADD_ADDR from client to server machine using a new port
636	:>"$evts"
637	ip netns exec "$ns2" ./pm_nl_ctl ann 10.0.2.2 token "$client4_token" id\
638	   $client_addr_id port $new4_port > /dev/null 2>&1
639	sleep 0.5
640
641	# CREATE_SUBFLOW from server to client machine
642	:>"$evts"
643	ip netns exec "$ns1" ./pm_nl_ctl csf lip 10.0.2.1 lid 23 rip 10.0.2.2 rport\
644	   $new4_port token "$server4_token" > /dev/null 2>&1
645	sleep 0.5
646	verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$server4_token" "$AF_INET"\
647			      "10.0.2.1" "10.0.2.2" "$new4_port" "23"\
648			      "$client_addr_id" "ns1" "ns2"
649
650	# Delete the listener from the client ns, if one was created
651	kill_wait $listener_pid
652
653	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
654
655	# DESTROY_SUBFLOW from server to client machine
656	:>"$evts"
657	ip netns exec "$ns1" ./pm_nl_ctl dsf lip 10.0.2.1 lport "$sport" rip 10.0.2.2 rport\
658	   $new4_port token "$server4_token" > /dev/null 2>&1
659	sleep 0.5
660	verify_subflow_events "$evts" "$SUB_CLOSED" "$server4_token" "$AF_INET" "10.0.2.1"\
661			      "10.0.2.2" "$new4_port" "23" "$client_addr_id" "ns1" "ns2"
662
663	# RM_ADDR from client to server machine
664	ip netns exec "$ns2" ./pm_nl_ctl rem id $client_addr_id token\
665	   "$client4_token" > /dev/null 2>&1
666
667	kill_wait $evts_pid
668
669	# Capture events on the network namespace running the client
670	:>"$evts"
671	ip netns exec "$ns2" ./pm_nl_ctl events >> "$evts" 2>&1 &
672	evts_pid=$!
673	sleep 0.5
674
675	# Attempt to add a listener at 10.0.2.1:<subflow-port>
676	ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
677	   $app4_port > /dev/null 2>&1 &
678	listener_pid=$!
679
680	# ADD_ADDR from server to client machine reusing the subflow port
681	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
682	   $server_addr_id > /dev/null 2>&1
683	sleep 0.5
684
685	# CREATE_SUBFLOW from client to server machine
686	:>"$evts"
687	ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
688	   $app4_port token "$client4_token" > /dev/null 2>&1
689	sleep 0.5
690	verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$client4_token" "$AF_INET" "10.0.2.2"\
691			      "10.0.2.1" "$app4_port" "23" "$server_addr_id" "ns2" "ns1"
692
693	# Delete the listener from the server ns, if one was created
694	kill_wait $listener_pid
695
696	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
697
698	# DESTROY_SUBFLOW from client to server machine
699	:>"$evts"
700	ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
701	   $app4_port token "$client4_token" > /dev/null 2>&1
702	sleep 0.5
703	verify_subflow_events "$evts" "$SUB_CLOSED" "$client4_token" "$AF_INET" "10.0.2.2"\
704			      "10.0.2.1" "$app4_port" "23" "$server_addr_id" "ns2" "ns1"
705
706	# RM_ADDR from server to client machine
707	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
708	   "$server4_token" > /dev/null 2>&1
709	sleep 0.5
710
711	# Attempt to add a listener at dead:beef:2::1:<subflow-port>
712	ip netns exec "$ns1" ./pm_nl_ctl listen dead:beef:2::1\
713	   $app6_port > /dev/null 2>&1 &
714	listener_pid=$!
715
716	# ADD_ADDR6 from server to client machine reusing the subflow port
717	:>"$evts"
718	ip netns exec "$ns1" ./pm_nl_ctl ann dead:beef:2::1 token "$server6_token" id\
719	   $server_addr_id > /dev/null 2>&1
720	sleep 0.5
721
722	# CREATE_SUBFLOW6 from client to server machine
723	:>"$evts"
724	ip netns exec "$ns2" ./pm_nl_ctl csf lip dead:beef:2::2 lid 23 rip\
725	   dead:beef:2::1 rport $app6_port token "$client6_token" > /dev/null 2>&1
726	sleep 0.5
727	verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$client6_token"\
728			      "$AF_INET6" "dead:beef:2::2"\
729			      "dead:beef:2::1" "$app6_port" "23"\
730			      "$server_addr_id" "ns2" "ns1"
731
732	# Delete the listener from the server ns, if one was created
733	kill_wait $listener_pid
734
735	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
736
737	# DESTROY_SUBFLOW6 from client to server machine
738	:>"$evts"
739	ip netns exec "$ns2" ./pm_nl_ctl dsf lip dead:beef:2::2 lport "$sport" rip\
740	   dead:beef:2::1 rport $app6_port token "$client6_token" > /dev/null 2>&1
741	sleep 0.5
742	verify_subflow_events "$evts" "$SUB_CLOSED" "$client6_token" "$AF_INET6" "dead:beef:2::2"\
743			      "dead:beef:2::1" "$app6_port" "23" "$server_addr_id" "ns2" "ns1"
744
745	# RM_ADDR6 from server to client machine
746	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
747	   "$server6_token" > /dev/null 2>&1
748	sleep 0.5
749
750	# Attempt to add a listener at 10.0.2.1:<new-port>
751	ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
752	   $new4_port > /dev/null 2>&1 &
753	listener_pid=$!
754
755	# ADD_ADDR from server to client machine using a new port
756	:>"$evts"
757	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server4_token" id\
758	   $server_addr_id port $new4_port > /dev/null 2>&1
759	sleep 0.5
760
761	# CREATE_SUBFLOW from client to server machine
762	:>"$evts"
763	ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
764	   $new4_port token "$client4_token" > /dev/null 2>&1
765	sleep 0.5
766	verify_subflow_events "$evts" "$SUB_ESTABLISHED" "$client4_token" "$AF_INET"\
767			      "10.0.2.2" "10.0.2.1" "$new4_port" "23" "$server_addr_id" "ns2" "ns1"
768
769	# Delete the listener from the server ns, if one was created
770	kill_wait $listener_pid
771
772	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$evts")
773
774	# DESTROY_SUBFLOW from client to server machine
775	:>"$evts"
776	ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
777	   $new4_port token "$client4_token" > /dev/null 2>&1
778	sleep 0.5
779	verify_subflow_events "$evts" "$SUB_CLOSED" "$client4_token" "$AF_INET" "10.0.2.2"\
780			      "10.0.2.1" "$new4_port" "23" "$server_addr_id" "ns2" "ns1"
781
782	# RM_ADDR from server to client machine
783	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
784	   "$server4_token" > /dev/null 2>&1
785
786	kill_wait $evts_pid
787	rm -f "$evts"
788}
789
790test_subflows_v4_v6_mix()
791{
792	local client_evts
793	client_evts=$(mktemp)
794	# Capture events on the network namespace running the client
795	:>"$client_evts"
796	ip netns exec "$ns2" ./pm_nl_ctl events >> "$client_evts" 2>&1 &
797	evts_pid=$!
798	sleep 0.5
799
800	# Attempt to add a listener at 10.0.2.1:<subflow-port>
801	ip netns exec "$ns1" ./pm_nl_ctl listen 10.0.2.1\
802	   $app6_port > /dev/null 2>&1 &
803	local listener_pid=$!
804
805	# ADD_ADDR4 from server to client machine reusing the subflow port on
806	# the established v6 connection
807	:>"$client_evts"
808	ip netns exec "$ns1" ./pm_nl_ctl ann 10.0.2.1 token "$server6_token" id\
809	   $server_addr_id dev ns1eth2 > /dev/null 2>&1
810	stdbuf -o0 -e0 printf "ADD_ADDR4 id:%d 10.0.2.1 (ns1) => ns2, reuse port\t\t" $server_addr_id
811	sleep 0.5
812	verify_announce_event "$client_evts" "$ANNOUNCED" "$client6_token" "10.0.2.1"\
813			      "$server_addr_id" "$app6_port"
814
815	# CREATE_SUBFLOW from client to server machine
816	:>"$client_evts"
817	ip netns exec "$ns2" ./pm_nl_ctl csf lip 10.0.2.2 lid 23 rip 10.0.2.1 rport\
818	   $app6_port token "$client6_token" > /dev/null 2>&1
819	sleep 0.5
820	verify_subflow_events "$client_evts" "$SUB_ESTABLISHED" "$client6_token"\
821			      "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
822			      "$server_addr_id" "ns2" "ns1"
823
824	# Delete the listener from the server ns, if one was created
825	kill_wait $listener_pid
826
827	sport=$(sed --unbuffered -n 's/.*\(sport:\)\([[:digit:]]*\).*$/\2/p;q' "$client_evts")
828
829	# DESTROY_SUBFLOW from client to server machine
830	:>"$client_evts"
831	ip netns exec "$ns2" ./pm_nl_ctl dsf lip 10.0.2.2 lport "$sport" rip 10.0.2.1 rport\
832	   $app6_port token "$client6_token" > /dev/null 2>&1
833	sleep 0.5
834	verify_subflow_events "$client_evts" "$SUB_CLOSED" "$client6_token" \
835			      "$AF_INET" "10.0.2.2" "10.0.2.1" "$app6_port" "23"\
836			      "$server_addr_id" "ns2" "ns1"
837
838	# RM_ADDR from server to client machine
839	ip netns exec "$ns1" ./pm_nl_ctl rem id $server_addr_id token\
840	   "$server6_token" > /dev/null 2>&1
841	sleep 0.5
842
843	kill_wait $evts_pid
844	rm -f "$client_evts"
845}
846
847test_prio()
848{
849	local count
850
851	# Send MP_PRIO signal from client to server machine
852	ip netns exec "$ns2" ./pm_nl_ctl set 10.0.1.2 port "$client4_port" flags backup token "$client4_token" rip 10.0.1.1 rport "$app4_port"
853	sleep 0.5
854
855	# Check TX
856	stdbuf -o0 -e0 printf "MP_PRIO TX                                                 \t"
857	count=$(ip netns exec "$ns2" nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}')
858	[ -z "$count" ] && count=0
859	if [ $count != 1 ]; then
860		stdbuf -o0 -e0 printf "[FAIL]\n"
861		exit 1
862	else
863		stdbuf -o0 -e0 printf "[OK]\n"
864	fi
865
866	# Check RX
867	stdbuf -o0 -e0 printf "MP_PRIO RX                                                 \t"
868	count=$(ip netns exec "$ns1" nstat -as | grep MPTcpExtMPPrioRx | awk '{print $2}')
869	[ -z "$count" ] && count=0
870	if [ $count != 1 ]; then
871		stdbuf -o0 -e0 printf "[FAIL]\n"
872		exit 1
873	else
874		stdbuf -o0 -e0 printf "[OK]\n"
875	fi
876}
877
878make_connection
879make_connection "v6"
880test_announce
881test_remove
882test_subflows
883test_subflows_v4_v6_mix
884test_prio
885
886exit 0
887