Merge tag 'nfs-for-6.10-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-block.git] / tools / testing / selftests / net / mptcp / simult_flows.sh
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
11 ns1=""
12 ns2=""
13 ns3=""
14 capture=false
15 timeout_poll=30
16 timeout_test=$((timeout_poll * 2 + 1))
17 # a bit more space: because we have more to display
18 MPTCP_LIB_TEST_FORMAT="%02u %-60s"
19 ret=0
20 bail=0
21 slack=50
22 large=""
23 small=""
24 sout=""
25 cout=""
26 capout=""
27 size=0
28
29 usage() {
30         echo "Usage: $0 [ -b ] [ -c ] [ -d ] [ -i]"
31         echo -e "\t-b: bail out after first error, otherwise runs al testcases"
32         echo -e "\t-c: capture packets for each test using tcpdump (default: no capture)"
33         echo -e "\t-d: debug this script"
34         echo -e "\t-i: use 'ip mptcp' instead of 'pm_nl_ctl'"
35 }
36
37 # This function is used in the cleanup trap
38 #shellcheck disable=SC2317
39 cleanup()
40 {
41         rm -f "$cout" "$sout"
42         rm -f "$large" "$small"
43         rm -f "$capout"
44
45         mptcp_lib_ns_exit "${ns1}" "${ns2}" "${ns3}"
46 }
47
48 mptcp_lib_check_mptcp
49 mptcp_lib_check_tools ip tc
50
51 #  "$ns1"              ns2                    ns3
52 #     ns1eth1    ns2eth1   ns2eth3      ns3eth1
53 #            netem
54 #     ns1eth2    ns2eth2
55 #            netem
56
57 setup()
58 {
59         large=$(mktemp)
60         small=$(mktemp)
61         sout=$(mktemp)
62         cout=$(mktemp)
63         capout=$(mktemp)
64         size=$((2 * 2048 * 4096))
65
66         dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1
67         dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1
68
69         trap cleanup EXIT
70
71         mptcp_lib_ns_init ns1 ns2 ns3
72
73         ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2"
74         ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth2 netns "$ns2"
75         ip link add ns2eth3 netns "$ns2" type veth peer name ns3eth1 netns "$ns3"
76
77         ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth1
78         ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth1 nodad
79         ip -net "$ns1" link set ns1eth1 up mtu 1500
80         ip -net "$ns1" route add default via 10.0.1.2
81         ip -net "$ns1" route add default via dead:beef:1::2
82
83         ip -net "$ns1" addr add 10.0.2.1/24 dev ns1eth2
84         ip -net "$ns1" addr add dead:beef:2::1/64 dev ns1eth2 nodad
85         ip -net "$ns1" link set ns1eth2 up mtu 1500
86         ip -net "$ns1" route add default via 10.0.2.2 metric 101
87         ip -net "$ns1" route add default via dead:beef:2::2 metric 101
88
89         mptcp_lib_pm_nl_set_limits "${ns1}" 1 1
90         mptcp_lib_pm_nl_add_endpoint "${ns1}" 10.0.2.1 dev ns1eth2 flags subflow
91
92         ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1
93         ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad
94         ip -net "$ns2" link set ns2eth1 up mtu 1500
95
96         ip -net "$ns2" addr add 10.0.2.2/24 dev ns2eth2
97         ip -net "$ns2" addr add dead:beef:2::2/64 dev ns2eth2 nodad
98         ip -net "$ns2" link set ns2eth2 up mtu 1500
99
100         ip -net "$ns2" addr add 10.0.3.2/24 dev ns2eth3
101         ip -net "$ns2" addr add dead:beef:3::2/64 dev ns2eth3 nodad
102         ip -net "$ns2" link set ns2eth3 up mtu 1500
103         ip netns exec "$ns2" sysctl -q net.ipv4.ip_forward=1
104         ip netns exec "$ns2" sysctl -q net.ipv6.conf.all.forwarding=1
105
106         ip -net "$ns3" addr add 10.0.3.3/24 dev ns3eth1
107         ip -net "$ns3" addr add dead:beef:3::3/64 dev ns3eth1 nodad
108         ip -net "$ns3" link set ns3eth1 up mtu 1500
109         ip -net "$ns3" route add default via 10.0.3.2
110         ip -net "$ns3" route add default via dead:beef:3::2
111
112         mptcp_lib_pm_nl_set_limits "${ns3}" 1 1
113
114         # debug build can slow down measurably the test program
115         # we use quite tight time limit on the run-time, to ensure
116         # maximum B/W usage.
117         # Use kmemleak/lockdep/kasan/prove_locking presence as a rough
118         # estimate for this being a debug kernel and increase the
119         # maximum run-time accordingly. Observed run times for CI builds
120         # running selftests, including kbuild, were used to determine the
121         # amount of time to add.
122         grep -q ' kmemleak_init$\| lockdep_init$\| kasan_init$\| prove_locking$' /proc/kallsyms && slack=$((slack+550))
123 }
124
125 do_transfer()
126 {
127         local cin=$1
128         local sin=$2
129         local max_time=$3
130         local port
131         port=$((10000+MPTCP_LIB_TEST_COUNTER))
132
133         :> "$cout"
134         :> "$sout"
135         :> "$capout"
136
137         if $capture; then
138                 local capuser
139                 local rndh="${ns1:4}"
140                 if [ -z $SUDO_USER ] ; then
141                         capuser=""
142                 else
143                         capuser="-Z $SUDO_USER"
144                 fi
145
146                 local capfile="${rndh}-${port}"
147                 local capopt="-i any -s 65535 -B 32768 ${capuser}"
148
149                 ip netns exec ${ns3}  tcpdump ${capopt} -w "${capfile}-listener.pcap"  >> "${capout}" 2>&1 &
150                 local cappid_listener=$!
151
152                 ip netns exec ${ns1} tcpdump ${capopt} -w "${capfile}-connector.pcap" >> "${capout}" 2>&1 &
153                 local cappid_connector=$!
154
155                 sleep 1
156         fi
157
158         timeout ${timeout_test} \
159                 ip netns exec ${ns3} \
160                         ./mptcp_connect -jt ${timeout_poll} -l -p $port -T $max_time \
161                                 0.0.0.0 < "$sin" > "$sout" &
162         local spid=$!
163
164         mptcp_lib_wait_local_port_listen "${ns3}" "${port}"
165
166         timeout ${timeout_test} \
167                 ip netns exec ${ns1} \
168                         ./mptcp_connect -jt ${timeout_poll} -p $port -T $max_time \
169                                 10.0.3.3 < "$cin" > "$cout" &
170         local cpid=$!
171
172         wait $cpid
173         local retc=$?
174         wait $spid
175         local rets=$?
176
177         if $capture; then
178                 sleep 1
179                 kill ${cappid_listener}
180                 kill ${cappid_connector}
181         fi
182
183         cmp $sin $cout > /dev/null 2>&1
184         local cmps=$?
185         cmp $cin $sout > /dev/null 2>&1
186         local cmpc=$?
187
188         printf "%-16s" " max $max_time "
189         if [ $retc -eq 0 ] && [ $rets -eq 0 ] && \
190            [ $cmpc -eq 0 ] && [ $cmps -eq 0 ]; then
191                 mptcp_lib_pr_ok
192                 cat "$capout"
193                 return 0
194         fi
195
196         mptcp_lib_pr_fail
197         echo "client exit code $retc, server $rets" 1>&2
198         echo -e "\nnetns ${ns3} socket stat for $port:" 1>&2
199         ip netns exec ${ns3} ss -nita 1>&2 -o "sport = :$port"
200         echo -e "\nnetns ${ns1} socket stat for $port:" 1>&2
201         ip netns exec ${ns1} ss -nita 1>&2 -o "dport = :$port"
202         ls -l $sin $cout
203         ls -l $cin $sout
204
205         cat "$capout"
206         return 1
207 }
208
209 run_test()
210 {
211         local rate1=$1
212         local rate2=$2
213         local delay1=$3
214         local delay2=$4
215         local lret
216         local dev
217         shift 4
218         local msg=$*
219
220         [ $delay1 -gt 0 ] && delay1="delay ${delay1}ms" || delay1=""
221         [ $delay2 -gt 0 ] && delay2="delay ${delay2}ms" || delay2=""
222
223         for dev in ns1eth1 ns1eth2; do
224                 tc -n $ns1 qdisc del dev $dev root >/dev/null 2>&1
225         done
226         for dev in ns2eth1 ns2eth2; do
227                 tc -n $ns2 qdisc del dev $dev root >/dev/null 2>&1
228         done
229         tc -n $ns1 qdisc add dev ns1eth1 root netem rate ${rate1}mbit $delay1
230         tc -n $ns1 qdisc add dev ns1eth2 root netem rate ${rate2}mbit $delay2
231         tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1
232         tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2
233
234         # time is measured in ms, account for transfer size, aggregated link speed
235         # and header overhead (10%)
236         #              ms    byte -> bit   10%        mbit      -> kbit -> bit  10%
237         local time=$((1000 * size  *  8  * 10 / ((rate1 + rate2) * 1000 * 1000 * 9) ))
238
239         # mptcp_connect will do some sleeps to allow the mp_join handshake
240         # completion (see mptcp_connect): 200ms on each side, add some slack
241         time=$((time + 400 + slack))
242
243         mptcp_lib_print_title "$msg"
244         do_transfer $small $large $time
245         lret=$?
246         mptcp_lib_result_code "${lret}" "${msg}"
247         if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then
248                 ret=$lret
249                 [ $bail -eq 0 ] || exit $ret
250         fi
251
252         msg+=" - reverse direction"
253         mptcp_lib_print_title "${msg}"
254         do_transfer $large $small $time
255         lret=$?
256         mptcp_lib_result_code "${lret}" "${msg}"
257         if [ $lret -ne 0 ] && ! mptcp_lib_subtest_is_flaky; then
258                 ret=$lret
259                 [ $bail -eq 0 ] || exit $ret
260         fi
261 }
262
263 while getopts "bcdhi" option;do
264         case "$option" in
265         "h")
266                 usage $0
267                 exit ${KSFT_PASS}
268                 ;;
269         "b")
270                 bail=1
271                 ;;
272         "c")
273                 capture=true
274                 ;;
275         "d")
276                 set -x
277                 ;;
278         "i")
279                 mptcp_lib_set_ip_mptcp
280                 ;;
281         "?")
282                 usage $0
283                 exit ${KSFT_FAIL}
284                 ;;
285         esac
286 done
287
288 setup
289 run_test 10 10 0 0 "balanced bwidth"
290 run_test 10 10 1 25 "balanced bwidth with unbalanced delay"
291
292 # we still need some additional infrastructure to pass the following test-cases
293 MPTCP_LIB_SUBTEST_FLAKY=1 run_test 10 3 0 0 "unbalanced bwidth"
294 run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay"
295 run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay"
296
297 mptcp_lib_result_print_all_tap
298 exit $ret