xref: /linux/tools/testing/selftests/net/mptcp/pm_netlink.sh (revision c9b581e619d258c827ea35e9a8bcf8f0c5c9f034)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4. "$(dirname "${0}")/mptcp_lib.sh"
5
6ret=0
7
8usage() {
9	echo "Usage: $0 [ -i ] [ -h ]"
10	echo -e "\t-i: use 'ip mptcp' instead of 'pm_nl_ctl'"
11	echo -e "\t-h: help"
12}
13
14optstring=hi
15while getopts "$optstring" option;do
16	case "$option" in
17	"h")
18		usage "$0"
19		exit ${KSFT_PASS}
20		;;
21	"i")
22		mptcp_lib_set_ip_mptcp
23		;;
24	"?")
25		usage "$0"
26		exit ${KSFT_FAIL}
27		;;
28	esac
29done
30
31ns1=""
32err=$(mktemp)
33
34# This function is used in the cleanup trap
35#shellcheck disable=SC2317,SC2329
36cleanup()
37{
38	rm -f "${err}"
39	mptcp_lib_ns_exit "${ns1}"
40}
41
42mptcp_lib_check_mptcp
43mptcp_lib_check_tools ip
44
45trap cleanup EXIT
46
47mptcp_lib_ns_init ns1
48
49format_limits() {
50	local accept="${1}"
51	local subflows="${2}"
52
53	if mptcp_lib_is_ip_mptcp; then
54		# with a space at the end
55		printf "add_addr_accepted %d subflows %d \n" "${accept}" "${subflows}"
56	else
57		printf "accept %d\nsubflows %d\n" "${accept}" "${subflows}"
58	fi
59}
60
61get_limits() {
62	if mptcp_lib_is_ip_mptcp; then
63		ip -n "${ns1}" mptcp limits
64	else
65		ip netns exec "${ns1}" ./pm_nl_ctl limits
66	fi
67}
68
69get_limits_nb() {
70	if mptcp_lib_is_ip_mptcp; then
71		ip -n "${ns1}" mptcp limits | awk '{ print $2" "$4 }'
72	else
73		ip netns exec "${ns1}" ./pm_nl_ctl limits | \
74			awk '{ printf "%s ", $2 }'
75	fi
76}
77
78format_endpoints() {
79	mptcp_lib_pm_nl_format_endpoints "${@}"
80}
81
82# This function is invoked indirectly
83#shellcheck disable=SC2317,SC2329
84get_endpoint() {
85	mptcp_lib_pm_nl_get_endpoint "${ns1}" "${@}"
86}
87
88change_address() {
89	local addr=${1}
90	local flags=${2}
91
92	if mptcp_lib_is_ip_mptcp; then
93		ip -n "${ns1}" mptcp endpoint change "${addr}" "${flags}"
94	else
95		ip netns exec "${ns1}" ./pm_nl_ctl set "${addr}" flags "${flags}"
96	fi
97}
98
99set_limits()
100{
101	mptcp_lib_pm_nl_set_limits "${ns1}" "${@}"
102}
103
104add_endpoint()
105{
106	mptcp_lib_pm_nl_add_endpoint "${ns1}" "${@}"
107}
108
109del_endpoint()
110{
111	mptcp_lib_pm_nl_del_endpoint "${ns1}" "${@}"
112}
113
114flush_endpoint()
115{
116	mptcp_lib_pm_nl_flush_endpoint "${ns1}"
117}
118
119show_endpoints()
120{
121	mptcp_lib_pm_nl_show_endpoints "${ns1}"
122}
123
124change_endpoint()
125{
126	mptcp_lib_pm_nl_change_endpoint "${ns1}" "${@}"
127}
128
129check()
130{
131	local cmd="$1"
132	local expected="$2"
133	local msg="$3"
134	local exp_error="$4"
135	local rc=0
136
137	mptcp_lib_print_title "$msg"
138	mptcp_lib_check_output "${err}" "${cmd}" "${expected}" "${exp_error}" ||
139		rc=${?}
140	if [ ${rc} -eq 2 ]; then
141		mptcp_lib_result_fail "${msg} # error ${rc}"
142		ret=${KSFT_FAIL}
143	elif [ ${rc} -eq 0 ]; then
144		mptcp_lib_print_ok "[ OK ]"
145		mptcp_lib_result_pass "${msg}"
146	elif [ ${rc} -eq 1 ]; then
147		mptcp_lib_result_fail "${msg} # different output"
148		ret=${KSFT_FAIL}
149	fi
150}
151
152mptcp_lib_subtests_last_ts_reset
153
154check "show_endpoints" "" "defaults addr list"
155
156default_limits="$(get_limits)"
157if mptcp_lib_expect_all_features; then
158	check "get_limits" "$(format_limits 0 2)" "defaults limits"
159fi
160
161add_endpoint 10.0.1.1
162add_endpoint 10.0.1.2 flags subflow dev lo
163add_endpoint 10.0.1.3 flags signal,backup
164check "get_endpoint 1" "$(format_endpoints "1,10.0.1.1")" "simple add/get addr"
165
166check "show_endpoints" \
167	"$(format_endpoints "1,10.0.1.1" \
168			    "2,10.0.1.2,subflow,lo" \
169			    "3,10.0.1.3,signal backup")" "dump addrs"
170
171del_endpoint 2
172check "get_endpoint 2" "" "simple del addr" 1
173check "show_endpoints" \
174	"$(format_endpoints "1,10.0.1.1" \
175			    "3,10.0.1.3,signal backup")" "dump addrs after del"
176add_endpoint 10.0.1.2 id 2
177
178add_endpoint 10.0.1.3 2>/dev/null
179check "get_endpoint 4" "" "duplicate addr" 1
180
181add_endpoint 10.0.1.4 flags signal
182check "get_endpoint 4" "$(format_endpoints "4,10.0.1.4,signal")" "id addr increment"
183
184read -r -a default_limits_nb <<< "$(get_limits_nb)"
185# limits have been increased: from 8 to 64 for subflows/add_addr & 255 for endp
186if mptcp_lib_expect_all_features || set_limits 9 9 2>/dev/null; then
187	max_endp=255
188	max_limits=64
189else
190	max_endp=8
191	max_limits=8
192fi
193set_limits "${default_limits_nb[@]}"
194
195for i in $(seq 5 ${max_endp}); do
196	add_endpoint "10.0.0.${i}" id "${i}"
197done
198check "get_endpoint ${max_endp}" \
199	"$(format_endpoints "${max_endp},10.0.0.${max_endp}")" "id limit"
200
201if add_endpoint '10.0.0.1' &>/dev/null; then
202	hardlimit="no error"
203else
204	hardlimit="error"
205fi
206check "echo ${hardlimit}" "error" "above hard addr limit"
207
208flush_endpoint
209check "show_endpoints" "" "flush addrs"
210
211# "unknown" flag is only supported by pm_nl_ctl
212if ! mptcp_lib_is_ip_mptcp; then
213	add_endpoint 10.0.1.1 flags unknown
214	check "show_endpoints" "$(format_endpoints "1,10.0.1.1")" \
215	      "ignore unknown flags"
216	flush_endpoint
217fi
218
219set_limits $((max_limits + 1)) 1 2>/dev/null
220check "get_limits" "${default_limits}" "rcv addrs above hard limit"
221
222set_limits 1 $((max_limits + 1)) 2>/dev/null
223check "get_limits" "${default_limits}" "subflows above hard limit"
224
225set_limits ${max_limits} ${max_limits}
226flush_endpoint  ## to make sure it doesn't affect the limits
227check "get_limits" "$(format_limits ${max_limits} ${max_limits})" "set limits"
228
229flush_endpoint
230add_endpoint 10.0.1.1
231add_endpoint 10.0.1.2
232add_endpoint 10.0.1.3 id 100
233add_endpoint 10.0.1.4
234add_endpoint 10.0.1.5 id 254
235add_endpoint 10.0.1.6
236add_endpoint 10.0.1.7
237add_endpoint 10.0.1.8
238check "show_endpoints" \
239	"$(format_endpoints "1,10.0.1.1" \
240			    "2,10.0.1.2" \
241			    "3,10.0.1.7" \
242			    "4,10.0.1.8" \
243			    "100,10.0.1.3" \
244			    "101,10.0.1.4" \
245			    "254,10.0.1.5" \
246			    "255,10.0.1.6")" "set ids"
247
248flush_endpoint
249add_endpoint 10.0.0.1
250add_endpoint 10.0.0.2 id 254
251add_endpoint 10.0.0.3
252add_endpoint 10.0.0.4
253add_endpoint 10.0.0.5 id 253
254add_endpoint 10.0.0.6
255add_endpoint 10.0.0.7
256add_endpoint 10.0.0.8
257check "show_endpoints" \
258	"$(format_endpoints "1,10.0.0.1" \
259			    "2,10.0.0.4" \
260			    "3,10.0.0.6" \
261			    "4,10.0.0.7" \
262			    "5,10.0.0.8" \
263			    "253,10.0.0.5" \
264			    "254,10.0.0.2" \
265			    "255,10.0.0.3")" "wrap-around ids"
266
267flush_endpoint
268add_endpoint 10.0.1.1 flags subflow
269change_address 10.0.1.1 backup
270check "show_endpoints" "$(format_endpoints "1,10.0.1.1,subflow backup")" \
271	"set flags (backup)"
272change_address 10.0.1.1 nobackup
273check "show_endpoints" "$(format_endpoints "1,10.0.1.1,subflow")" \
274	"          (nobackup)"
275
276# fullmesh support has been added later
277change_endpoint 1 fullmesh 2>/dev/null
278if show_endpoints | grep -q "fullmesh" ||
279   mptcp_lib_expect_all_features; then
280	check "show_endpoints" "$(format_endpoints "1,10.0.1.1,subflow fullmesh")" \
281		"          (fullmesh)"
282	change_endpoint 1 nofullmesh
283	check "show_endpoints" "$(format_endpoints "1,10.0.1.1,subflow")" \
284		"          (nofullmesh)"
285	change_endpoint 1 backup,fullmesh
286	check "show_endpoints" "$(format_endpoints "1,10.0.1.1,subflow backup fullmesh")" \
287		"          (backup,fullmesh)"
288else
289	for st in fullmesh nofullmesh backup,fullmesh; do
290		st="          (${st})"
291		mptcp_lib_print_title "${st}"
292		mptcp_lib_pr_skip
293		mptcp_lib_result_skip "${st}"
294	done
295fi
296
297mptcp_lib_result_print_all_tap
298exit $ret
299