Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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. "$(dirname "${0}")/mptcp_lib.sh"
10
11ret=0
12sin=""
13sout=""
14cin=""
15cout=""
16timeout_poll=30
17timeout_test=$((timeout_poll * 2 + 1))
18iptables="iptables"
19ip6tables="ip6tables"
20
21ns1=""
22ns2=""
23ns_sbox=""
24
25usage() {
26 echo "Usage: $0 [ -i ] [ -h ]"
27 echo -e "\t-i: use 'ip mptcp' instead of 'pm_nl_ctl'"
28 echo -e "\t-h: help"
29}
30
31while getopts "hi" option;do
32 case "$option" in
33 "h")
34 usage "$0"
35 exit ${KSFT_PASS}
36 ;;
37 "i")
38 mptcp_lib_set_ip_mptcp
39 ;;
40 "?")
41 usage "$0"
42 exit ${KSFT_FAIL}
43 ;;
44 esac
45done
46
47add_mark_rules()
48{
49 local ns=$1
50 local m=$2
51
52 local t
53 for t in ${iptables} ${ip6tables}; do
54 # just to debug: check we have multiple subflows connection requests
55 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT
56
57 # RST packets might be handled by a internal dummy socket
58 ip netns exec $ns $t -A OUTPUT -p tcp --tcp-flags RST RST -m mark --mark 0 -j ACCEPT
59
60 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark $m -j ACCEPT
61 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark 0 -j DROP
62 done
63}
64
65init()
66{
67 mptcp_lib_ns_init ns1 ns2 ns_sbox
68
69 local i
70 for i in $(seq 1 4); do
71 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2"
72 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i
73 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad
74 ip -net "$ns1" link set ns1eth$i up
75
76 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i
77 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad
78 ip -net "$ns2" link set ns2eth$i up
79
80 # let $ns2 reach any $ns1 address from any interface
81 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i
82
83 mptcp_lib_pm_nl_add_endpoint "${ns1}" "10.0.${i}.1" flags signal
84 mptcp_lib_pm_nl_add_endpoint "${ns1}" "dead:beef:${i}::1" flags signal
85
86 mptcp_lib_pm_nl_add_endpoint "${ns2}" "10.0.${i}.2" flags signal
87 mptcp_lib_pm_nl_add_endpoint "${ns2}" "dead:beef:${i}::2" flags signal
88 done
89
90 mptcp_lib_pm_nl_set_limits "${ns1}" 8 8
91 mptcp_lib_pm_nl_set_limits "${ns2}" 8 8
92
93 add_mark_rules $ns1 1
94 add_mark_rules $ns2 2
95}
96
97# This function is used in the cleanup trap
98#shellcheck disable=SC2317
99cleanup()
100{
101 mptcp_lib_ns_exit "${ns1}" "${ns2}" "${ns_sbox}"
102 rm -f "$cin" "$cout"
103 rm -f "$sin" "$sout"
104}
105
106mptcp_lib_check_mptcp
107mptcp_lib_check_kallsyms
108mptcp_lib_check_tools ip "${iptables}" "${ip6tables}"
109
110check_mark()
111{
112 local ns=$1
113 local af=$2
114
115 local tables=${iptables}
116
117 if [ $af -eq 6 ];then
118 tables=${ip6tables}
119 fi
120
121 local counters values
122 counters=$(ip netns exec $ns $tables -v -L OUTPUT | grep DROP)
123 values=${counters%DROP*}
124
125 local v
126 for v in $values; do
127 if [ $v -ne 0 ]; then
128 mptcp_lib_pr_fail "got $tables $values in ns $ns," \
129 "not 0 - not all expected packets marked"
130 ret=${KSFT_FAIL}
131 return 1
132 fi
133 done
134
135 return 0
136}
137
138print_title()
139{
140 mptcp_lib_print_title "${@}"
141}
142
143do_transfer()
144{
145 local listener_ns="$1"
146 local connector_ns="$2"
147 local cl_proto="$3"
148 local srv_proto="$4"
149 local connect_addr="$5"
150
151 local port=12001
152
153 :> "$cout"
154 :> "$sout"
155
156 local mptcp_connect="./mptcp_connect -r 20"
157
158 local local_addr ip
159 if mptcp_lib_is_v6 "${connect_addr}"; then
160 local_addr="::"
161 ip=ipv6
162 else
163 local_addr="0.0.0.0"
164 ip=ipv4
165 fi
166
167 cmsg="TIMESTAMPNS"
168 if mptcp_lib_kallsyms_has "mptcp_ioctl$"; then
169 cmsg+=",TCPINQ"
170 fi
171
172 timeout ${timeout_test} \
173 ip netns exec ${listener_ns} \
174 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c "${cmsg}" \
175 ${local_addr} < "$sin" > "$sout" &
176 local spid=$!
177
178 sleep 1
179
180 timeout ${timeout_test} \
181 ip netns exec ${connector_ns} \
182 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c "${cmsg}" \
183 $connect_addr < "$cin" > "$cout" &
184
185 local cpid=$!
186
187 wait $cpid
188 local retc=$?
189 wait $spid
190 local rets=$?
191
192 print_title "Transfer ${ip:2}"
193 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
194 mptcp_lib_pr_fail "client exit code $retc, server $rets"
195 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2
196 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port"
197
198 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2
199 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port"
200
201 mptcp_lib_result_fail "transfer ${ip}"
202
203 ret=${KSFT_FAIL}
204 return 1
205 fi
206 if ! mptcp_lib_check_transfer $cin $sout "file received by server"; then
207 rets=1
208 else
209 mptcp_lib_pr_ok
210 fi
211 mptcp_lib_result_code "${rets}" "transfer ${ip}"
212
213 print_title "Mark ${ip:2}"
214 if [ $local_addr = "::" ];then
215 check_mark $listener_ns 6 || retc=1
216 check_mark $connector_ns 6 || retc=1
217 else
218 check_mark $listener_ns 4 || retc=1
219 check_mark $connector_ns 4 || retc=1
220 fi
221
222 mptcp_lib_result_code "${retc}" "mark ${ip}"
223
224 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then
225 mptcp_lib_pr_ok
226 return 0
227 fi
228 mptcp_lib_pr_fail
229
230 return 1
231}
232
233make_file()
234{
235 local name=$1
236 local who=$2
237 local size=$3
238
239 mptcp_lib_make_file $name 1024 $size
240
241 echo "Created $name (size $size KB) containing data sent by $who"
242}
243
244do_mptcp_sockopt_tests()
245{
246 local lret=0
247
248 if ! mptcp_lib_kallsyms_has "mptcp_diag_fill_info$"; then
249 mptcp_lib_pr_skip "MPTCP sockopt not supported"
250 mptcp_lib_result_skip "sockopt"
251 return
252 fi
253
254 ip netns exec "$ns_sbox" ./mptcp_sockopt
255 lret=$?
256
257 print_title "SOL_MPTCP sockopt v4"
258 if [ $lret -ne 0 ]; then
259 mptcp_lib_pr_fail
260 mptcp_lib_result_fail "sockopt v4"
261 ret=$lret
262 return
263 fi
264 mptcp_lib_pr_ok
265 mptcp_lib_result_pass "sockopt v4"
266
267 ip netns exec "$ns_sbox" ./mptcp_sockopt -6
268 lret=$?
269
270 print_title "SOL_MPTCP sockopt v6"
271 if [ $lret -ne 0 ]; then
272 mptcp_lib_pr_fail
273 mptcp_lib_result_fail "sockopt v6"
274 ret=$lret
275 return
276 fi
277 mptcp_lib_pr_ok
278 mptcp_lib_result_pass "sockopt v6"
279}
280
281run_tests()
282{
283 local listener_ns="$1"
284 local connector_ns="$2"
285 local connect_addr="$3"
286 local lret=0
287
288 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr}
289
290 lret=$?
291
292 if [ $lret -ne 0 ]; then
293 ret=$lret
294 return
295 fi
296}
297
298do_tcpinq_test()
299{
300 print_title "TCP_INQ cmsg/ioctl $*"
301 ip netns exec "$ns_sbox" ./mptcp_inq "$@"
302 local lret=$?
303 if [ $lret -ne 0 ];then
304 ret=$lret
305 mptcp_lib_pr_fail
306 mptcp_lib_result_fail "TCP_INQ: $*"
307 return $lret
308 fi
309
310 mptcp_lib_pr_ok
311 mptcp_lib_result_pass "TCP_INQ: $*"
312 return $lret
313}
314
315do_tcpinq_tests()
316{
317 local lret=0
318
319 if ! mptcp_lib_kallsyms_has "mptcp_ioctl$"; then
320 mptcp_lib_pr_skip "TCP_INQ not supported"
321 mptcp_lib_result_skip "TCP_INQ"
322 return
323 fi
324
325 local args
326 for args in "-t tcp" "-r tcp"; do
327 do_tcpinq_test $args
328 lret=$?
329 if [ $lret -ne 0 ] ; then
330 return $lret
331 fi
332 do_tcpinq_test -6 $args
333 lret=$?
334 if [ $lret -ne 0 ] ; then
335 return $lret
336 fi
337 done
338
339 do_tcpinq_test -r tcp -t tcp
340
341 return $?
342}
343
344sin=$(mktemp)
345sout=$(mktemp)
346cin=$(mktemp)
347cout=$(mktemp)
348init
349make_file "$cin" "client" 1
350make_file "$sin" "server" 1
351trap cleanup EXIT
352
353run_tests $ns1 $ns2 10.0.1.1
354run_tests $ns1 $ns2 dead:beef:1::1
355
356do_mptcp_sockopt_tests
357do_tcpinq_tests
358
359mptcp_lib_result_print_all_tap
360exit $ret