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