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