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. "$(dirname "${0}")/mptcp_lib.sh"
5
6sec=$(date +%s)
7rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
8ns="ns1-$rndh"
9ksft_skip=4
10test_cnt=1
11timeout_poll=100
12timeout_test=$((timeout_poll * 2 + 1))
13ret=0
14
15flush_pids()
16{
17 # mptcp_connect in join mode will sleep a bit before completing,
18 # give it some time
19 sleep 1.1
20
21 ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGUSR1 &>/dev/null
22
23 for _ in $(seq 10); do
24 [ -z "$(ip netns pids "${ns}")" ] && break
25 sleep 0.1
26 done
27}
28
29cleanup()
30{
31 ip netns pids "${ns}" | xargs --no-run-if-empty kill -SIGKILL &>/dev/null
32
33 ip netns del $ns
34}
35
36mptcp_lib_check_mptcp
37
38ip -Version > /dev/null 2>&1
39if [ $? -ne 0 ];then
40 echo "SKIP: Could not run test without ip tool"
41 exit $ksft_skip
42fi
43ss -h | grep -q MPTCP
44if [ $? -ne 0 ];then
45 echo "SKIP: ss tool does not support MPTCP"
46 exit $ksft_skip
47fi
48
49get_msk_inuse()
50{
51 ip netns exec $ns cat /proc/net/protocols | awk '$1~/^MPTCP$/{print $3}'
52}
53
54__chk_nr()
55{
56 local command="$1"
57 local expected=$2
58 local msg="$3"
59 local skip="${4:-SKIP}"
60 local nr
61
62 nr=$(eval $command)
63
64 printf "%-50s" "$msg"
65 if [ $nr != $expected ]; then
66 if [ $nr = "$skip" ] && ! mptcp_lib_expect_all_features; then
67 echo "[ skip ] Feature probably not supported"
68 mptcp_lib_result_skip "${msg}"
69 else
70 echo "[ fail ] expected $expected found $nr"
71 mptcp_lib_result_fail "${msg}"
72 ret=$test_cnt
73 fi
74 else
75 echo "[ ok ]"
76 mptcp_lib_result_pass "${msg}"
77 fi
78 test_cnt=$((test_cnt+1))
79}
80
81__chk_msk_nr()
82{
83 local condition=$1
84 shift 1
85
86 __chk_nr "ss -inmHMN $ns | $condition" "$@"
87}
88
89chk_msk_nr()
90{
91 __chk_msk_nr "grep -c token:" "$@"
92}
93
94wait_msk_nr()
95{
96 local condition="grep -c token:"
97 local expected=$1
98 local timeout=20
99 local msg nr
100 local max=0
101 local i=0
102
103 shift 1
104 msg=$*
105
106 while [ $i -lt $timeout ]; do
107 nr=$(ss -inmHMN $ns | $condition)
108 [ $nr == $expected ] && break;
109 [ $nr -gt $max ] && max=$nr
110 i=$((i + 1))
111 sleep 1
112 done
113
114 printf "%-50s" "$msg"
115 if [ $i -ge $timeout ]; then
116 echo "[ fail ] timeout while expecting $expected max $max last $nr"
117 mptcp_lib_result_fail "${msg} # timeout"
118 ret=$test_cnt
119 elif [ $nr != $expected ]; then
120 echo "[ fail ] expected $expected found $nr"
121 mptcp_lib_result_fail "${msg} # unexpected result"
122 ret=$test_cnt
123 else
124 echo "[ ok ]"
125 mptcp_lib_result_pass "${msg}"
126 fi
127 test_cnt=$((test_cnt+1))
128}
129
130chk_msk_fallback_nr()
131{
132 __chk_msk_nr "grep -c fallback" "$@"
133}
134
135chk_msk_remote_key_nr()
136{
137 __chk_msk_nr "grep -c remote_key" "$@"
138}
139
140__chk_listen()
141{
142 local filter="$1"
143 local expected=$2
144 local msg="$3"
145
146 __chk_nr "ss -N $ns -Ml '$filter' | grep -c LISTEN" "$expected" "$msg" 0
147}
148
149chk_msk_listen()
150{
151 lport=$1
152
153 # destination port search should always return empty list
154 __chk_listen "dport $lport" 0 "listen match for dport $lport"
155
156 # should return 'our' mptcp listen socket
157 __chk_listen "sport $lport" 1 "listen match for sport $lport"
158
159 __chk_listen "src inet:0.0.0.0:$lport" 1 "listen match for saddr and sport"
160
161 __chk_listen "" 1 "all listen sockets"
162
163 nr=$(ss -Ml $filter | wc -l)
164}
165
166chk_msk_inuse()
167{
168 local expected=$1
169 local msg="$2"
170 local listen_nr
171
172 listen_nr=$(ss -N "${ns}" -Ml | grep -c LISTEN)
173 expected=$((expected + listen_nr))
174
175 for _ in $(seq 10); do
176 if [ $(get_msk_inuse) -eq $expected ];then
177 break
178 fi
179 sleep 0.1
180 done
181
182 __chk_nr get_msk_inuse $expected "$msg" 0
183}
184
185# $1: ns, $2: port
186wait_local_port_listen()
187{
188 local listener_ns="${1}"
189 local port="${2}"
190
191 local port_hex i
192
193 port_hex="$(printf "%04X" "${port}")"
194 for i in $(seq 10); do
195 ip netns exec "${listener_ns}" cat /proc/net/tcp | \
196 awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
197 break
198 sleep 0.1
199 done
200}
201
202wait_connected()
203{
204 local listener_ns="${1}"
205 local port="${2}"
206
207 local port_hex i
208
209 port_hex="$(printf "%04X" "${port}")"
210 for i in $(seq 10); do
211 ip netns exec ${listener_ns} grep -q " 0100007F:${port_hex} " /proc/net/tcp && break
212 sleep 0.1
213 done
214}
215
216trap cleanup EXIT
217ip netns add $ns
218ip -n $ns link set dev lo up
219
220echo "a" | \
221 timeout ${timeout_test} \
222 ip netns exec $ns \
223 ./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \
224 0.0.0.0 >/dev/null &
225wait_local_port_listen $ns 10000
226chk_msk_nr 0 "no msk on netns creation"
227chk_msk_listen 10000
228
229echo "b" | \
230 timeout ${timeout_test} \
231 ip netns exec $ns \
232 ./mptcp_connect -p 10000 -r 0 -t ${timeout_poll} -w 20 \
233 127.0.0.1 >/dev/null &
234wait_connected $ns 10000
235chk_msk_nr 2 "after MPC handshake "
236chk_msk_remote_key_nr 2 "....chk remote_key"
237chk_msk_fallback_nr 0 "....chk no fallback"
238chk_msk_inuse 2 "....chk 2 msk in use"
239flush_pids
240
241chk_msk_inuse 0 "....chk 0 msk in use after flush"
242
243echo "a" | \
244 timeout ${timeout_test} \
245 ip netns exec $ns \
246 ./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \
247 0.0.0.0 >/dev/null &
248wait_local_port_listen $ns 10001
249echo "b" | \
250 timeout ${timeout_test} \
251 ip netns exec $ns \
252 ./mptcp_connect -p 10001 -r 0 -t ${timeout_poll} -w 20 \
253 127.0.0.1 >/dev/null &
254wait_connected $ns 10001
255chk_msk_fallback_nr 1 "check fallback"
256chk_msk_inuse 1 "....chk 1 msk in use"
257flush_pids
258
259chk_msk_inuse 0 "....chk 0 msk in use after flush"
260
261NR_CLIENTS=100
262for I in `seq 1 $NR_CLIENTS`; do
263 echo "a" | \
264 timeout ${timeout_test} \
265 ip netns exec $ns \
266 ./mptcp_connect -p $((I+10001)) -l -w 20 \
267 -t ${timeout_poll} 0.0.0.0 >/dev/null &
268done
269wait_local_port_listen $ns $((NR_CLIENTS + 10001))
270
271for I in `seq 1 $NR_CLIENTS`; do
272 echo "b" | \
273 timeout ${timeout_test} \
274 ip netns exec $ns \
275 ./mptcp_connect -p $((I+10001)) -w 20 \
276 -t ${timeout_poll} 127.0.0.1 >/dev/null &
277done
278
279wait_msk_nr $((NR_CLIENTS*2)) "many msk socket present"
280chk_msk_inuse $((NR_CLIENTS*2)) "....chk many msk in use"
281flush_pids
282
283chk_msk_inuse 0 "....chk 0 msk in use after flush"
284
285mptcp_lib_result_print_all_tap
286exit $ret