162306a36Sopenharmony_ci#!/bin/bash 262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci. "$(dirname "${0}")/mptcp_lib.sh" 562306a36Sopenharmony_ci 662306a36Sopenharmony_cisec=$(date +%s) 762306a36Sopenharmony_cirndh=$(printf %x $sec)-$(mktemp -u XXXXXX) 862306a36Sopenharmony_cins1="ns1-$rndh" 962306a36Sopenharmony_cins2="ns2-$rndh" 1062306a36Sopenharmony_cins3="ns3-$rndh" 1162306a36Sopenharmony_cicapture=false 1262306a36Sopenharmony_ciksft_skip=4 1362306a36Sopenharmony_citimeout_poll=30 1462306a36Sopenharmony_citimeout_test=$((timeout_poll * 2 + 1)) 1562306a36Sopenharmony_citest_cnt=1 1662306a36Sopenharmony_ciret=0 1762306a36Sopenharmony_cibail=0 1862306a36Sopenharmony_cislack=50 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciusage() { 2162306a36Sopenharmony_ci echo "Usage: $0 [ -b ] [ -c ] [ -d ]" 2262306a36Sopenharmony_ci echo -e "\t-b: bail out after first error, otherwise runs al testcases" 2362306a36Sopenharmony_ci echo -e "\t-c: capture packets for each test using tcpdump (default: no capture)" 2462306a36Sopenharmony_ci echo -e "\t-d: debug this script" 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cicleanup() 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci rm -f "$cout" "$sout" 3062306a36Sopenharmony_ci rm -f "$large" "$small" 3162306a36Sopenharmony_ci rm -f "$capout" 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci local netns 3462306a36Sopenharmony_ci for netns in "$ns1" "$ns2" "$ns3";do 3562306a36Sopenharmony_ci ip netns del $netns 3662306a36Sopenharmony_ci done 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cimptcp_lib_check_mptcp 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciip -Version > /dev/null 2>&1 4262306a36Sopenharmony_ciif [ $? -ne 0 ];then 4362306a36Sopenharmony_ci echo "SKIP: Could not run test without ip tool" 4462306a36Sopenharmony_ci exit $ksft_skip 4562306a36Sopenharmony_cifi 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci# "$ns1" ns2 ns3 4862306a36Sopenharmony_ci# ns1eth1 ns2eth1 ns2eth3 ns3eth1 4962306a36Sopenharmony_ci# netem 5062306a36Sopenharmony_ci# ns1eth2 ns2eth2 5162306a36Sopenharmony_ci# netem 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cisetup() 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci large=$(mktemp) 5662306a36Sopenharmony_ci small=$(mktemp) 5762306a36Sopenharmony_ci sout=$(mktemp) 5862306a36Sopenharmony_ci cout=$(mktemp) 5962306a36Sopenharmony_ci capout=$(mktemp) 6062306a36Sopenharmony_ci size=$((2 * 2048 * 4096)) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci dd if=/dev/zero of=$small bs=4096 count=20 >/dev/null 2>&1 6362306a36Sopenharmony_ci dd if=/dev/zero of=$large bs=4096 count=$((size / 4096)) >/dev/null 2>&1 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci trap cleanup EXIT 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci for i in "$ns1" "$ns2" "$ns3";do 6862306a36Sopenharmony_ci ip netns add $i || exit $ksft_skip 6962306a36Sopenharmony_ci ip -net $i link set lo up 7062306a36Sopenharmony_ci ip netns exec $i sysctl -q net.ipv4.conf.all.rp_filter=0 7162306a36Sopenharmony_ci ip netns exec $i sysctl -q net.ipv4.conf.default.rp_filter=0 7262306a36Sopenharmony_ci done 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ip link add ns1eth1 netns "$ns1" type veth peer name ns2eth1 netns "$ns2" 7562306a36Sopenharmony_ci ip link add ns1eth2 netns "$ns1" type veth peer name ns2eth2 netns "$ns2" 7662306a36Sopenharmony_ci ip link add ns2eth3 netns "$ns2" type veth peer name ns3eth1 netns "$ns3" 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci ip -net "$ns1" addr add 10.0.1.1/24 dev ns1eth1 7962306a36Sopenharmony_ci ip -net "$ns1" addr add dead:beef:1::1/64 dev ns1eth1 nodad 8062306a36Sopenharmony_ci ip -net "$ns1" link set ns1eth1 up mtu 1500 8162306a36Sopenharmony_ci ip -net "$ns1" route add default via 10.0.1.2 8262306a36Sopenharmony_ci ip -net "$ns1" route add default via dead:beef:1::2 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci ip -net "$ns1" addr add 10.0.2.1/24 dev ns1eth2 8562306a36Sopenharmony_ci ip -net "$ns1" addr add dead:beef:2::1/64 dev ns1eth2 nodad 8662306a36Sopenharmony_ci ip -net "$ns1" link set ns1eth2 up mtu 1500 8762306a36Sopenharmony_ci ip -net "$ns1" route add default via 10.0.2.2 metric 101 8862306a36Sopenharmony_ci ip -net "$ns1" route add default via dead:beef:2::2 metric 101 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci ip netns exec "$ns1" ./pm_nl_ctl limits 1 1 9162306a36Sopenharmony_ci ip netns exec "$ns1" ./pm_nl_ctl add 10.0.2.1 dev ns1eth2 flags subflow 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci ip -net "$ns2" addr add 10.0.1.2/24 dev ns2eth1 9462306a36Sopenharmony_ci ip -net "$ns2" addr add dead:beef:1::2/64 dev ns2eth1 nodad 9562306a36Sopenharmony_ci ip -net "$ns2" link set ns2eth1 up mtu 1500 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci ip -net "$ns2" addr add 10.0.2.2/24 dev ns2eth2 9862306a36Sopenharmony_ci ip -net "$ns2" addr add dead:beef:2::2/64 dev ns2eth2 nodad 9962306a36Sopenharmony_ci ip -net "$ns2" link set ns2eth2 up mtu 1500 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci ip -net "$ns2" addr add 10.0.3.2/24 dev ns2eth3 10262306a36Sopenharmony_ci ip -net "$ns2" addr add dead:beef:3::2/64 dev ns2eth3 nodad 10362306a36Sopenharmony_ci ip -net "$ns2" link set ns2eth3 up mtu 1500 10462306a36Sopenharmony_ci ip netns exec "$ns2" sysctl -q net.ipv4.ip_forward=1 10562306a36Sopenharmony_ci ip netns exec "$ns2" sysctl -q net.ipv6.conf.all.forwarding=1 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci ip -net "$ns3" addr add 10.0.3.3/24 dev ns3eth1 10862306a36Sopenharmony_ci ip -net "$ns3" addr add dead:beef:3::3/64 dev ns3eth1 nodad 10962306a36Sopenharmony_ci ip -net "$ns3" link set ns3eth1 up mtu 1500 11062306a36Sopenharmony_ci ip -net "$ns3" route add default via 10.0.3.2 11162306a36Sopenharmony_ci ip -net "$ns3" route add default via dead:beef:3::2 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ip netns exec "$ns3" ./pm_nl_ctl limits 1 1 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci # debug build can slow down measurably the test program 11662306a36Sopenharmony_ci # we use quite tight time limit on the run-time, to ensure 11762306a36Sopenharmony_ci # maximum B/W usage. 11862306a36Sopenharmony_ci # Use kmemleak/lockdep/kasan/prove_locking presence as a rough 11962306a36Sopenharmony_ci # estimate for this being a debug kernel and increase the 12062306a36Sopenharmony_ci # maximum run-time accordingly. Observed run times for CI builds 12162306a36Sopenharmony_ci # running selftests, including kbuild, were used to determine the 12262306a36Sopenharmony_ci # amount of time to add. 12362306a36Sopenharmony_ci grep -q ' kmemleak_init$\| lockdep_init$\| kasan_init$\| prove_locking$' /proc/kallsyms && slack=$((slack+550)) 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci# $1: ns, $2: port 12762306a36Sopenharmony_ciwait_local_port_listen() 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci local listener_ns="${1}" 13062306a36Sopenharmony_ci local port="${2}" 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci local port_hex i 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci port_hex="$(printf "%04X" "${port}")" 13562306a36Sopenharmony_ci for i in $(seq 10); do 13662306a36Sopenharmony_ci ip netns exec "${listener_ns}" cat /proc/net/tcp* | \ 13762306a36Sopenharmony_ci awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" && 13862306a36Sopenharmony_ci break 13962306a36Sopenharmony_ci sleep 0.1 14062306a36Sopenharmony_ci done 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cido_transfer() 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci local cin=$1 14662306a36Sopenharmony_ci local sin=$2 14762306a36Sopenharmony_ci local max_time=$3 14862306a36Sopenharmony_ci local port 14962306a36Sopenharmony_ci port=$((10000+$test_cnt)) 15062306a36Sopenharmony_ci test_cnt=$((test_cnt+1)) 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci :> "$cout" 15362306a36Sopenharmony_ci :> "$sout" 15462306a36Sopenharmony_ci :> "$capout" 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if $capture; then 15762306a36Sopenharmony_ci local capuser 15862306a36Sopenharmony_ci if [ -z $SUDO_USER ] ; then 15962306a36Sopenharmony_ci capuser="" 16062306a36Sopenharmony_ci else 16162306a36Sopenharmony_ci capuser="-Z $SUDO_USER" 16262306a36Sopenharmony_ci fi 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci local capfile="${rndh}-${port}" 16562306a36Sopenharmony_ci local capopt="-i any -s 65535 -B 32768 ${capuser}" 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci ip netns exec ${ns3} tcpdump ${capopt} -w "${capfile}-listener.pcap" >> "${capout}" 2>&1 & 16862306a36Sopenharmony_ci local cappid_listener=$! 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci ip netns exec ${ns1} tcpdump ${capopt} -w "${capfile}-connector.pcap" >> "${capout}" 2>&1 & 17162306a36Sopenharmony_ci local cappid_connector=$! 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci sleep 1 17462306a36Sopenharmony_ci fi 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci timeout ${timeout_test} \ 17762306a36Sopenharmony_ci ip netns exec ${ns3} \ 17862306a36Sopenharmony_ci ./mptcp_connect -jt ${timeout_poll} -l -p $port -T $max_time \ 17962306a36Sopenharmony_ci 0.0.0.0 < "$sin" > "$sout" & 18062306a36Sopenharmony_ci local spid=$! 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci wait_local_port_listen "${ns3}" "${port}" 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci timeout ${timeout_test} \ 18562306a36Sopenharmony_ci ip netns exec ${ns1} \ 18662306a36Sopenharmony_ci ./mptcp_connect -jt ${timeout_poll} -p $port -T $max_time \ 18762306a36Sopenharmony_ci 10.0.3.3 < "$cin" > "$cout" & 18862306a36Sopenharmony_ci local cpid=$! 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci wait $cpid 19162306a36Sopenharmony_ci local retc=$? 19262306a36Sopenharmony_ci wait $spid 19362306a36Sopenharmony_ci local rets=$? 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if $capture; then 19662306a36Sopenharmony_ci sleep 1 19762306a36Sopenharmony_ci kill ${cappid_listener} 19862306a36Sopenharmony_ci kill ${cappid_connector} 19962306a36Sopenharmony_ci fi 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci cmp $sin $cout > /dev/null 2>&1 20262306a36Sopenharmony_ci local cmps=$? 20362306a36Sopenharmony_ci cmp $cin $sout > /dev/null 2>&1 20462306a36Sopenharmony_ci local cmpc=$? 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci printf "%-16s" " max $max_time " 20762306a36Sopenharmony_ci if [ $retc -eq 0 ] && [ $rets -eq 0 ] && \ 20862306a36Sopenharmony_ci [ $cmpc -eq 0 ] && [ $cmps -eq 0 ]; then 20962306a36Sopenharmony_ci echo "[ OK ]" 21062306a36Sopenharmony_ci cat "$capout" 21162306a36Sopenharmony_ci return 0 21262306a36Sopenharmony_ci fi 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci echo " [ fail ]" 21562306a36Sopenharmony_ci echo "client exit code $retc, server $rets" 1>&2 21662306a36Sopenharmony_ci echo -e "\nnetns ${ns3} socket stat for $port:" 1>&2 21762306a36Sopenharmony_ci ip netns exec ${ns3} ss -nita 1>&2 -o "sport = :$port" 21862306a36Sopenharmony_ci echo -e "\nnetns ${ns1} socket stat for $port:" 1>&2 21962306a36Sopenharmony_ci ip netns exec ${ns1} ss -nita 1>&2 -o "dport = :$port" 22062306a36Sopenharmony_ci ls -l $sin $cout 22162306a36Sopenharmony_ci ls -l $cin $sout 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci cat "$capout" 22462306a36Sopenharmony_ci return 1 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cirun_test() 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci local rate1=$1 23062306a36Sopenharmony_ci local rate2=$2 23162306a36Sopenharmony_ci local delay1=$3 23262306a36Sopenharmony_ci local delay2=$4 23362306a36Sopenharmony_ci local lret 23462306a36Sopenharmony_ci local dev 23562306a36Sopenharmony_ci shift 4 23662306a36Sopenharmony_ci local msg=$* 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci [ $delay1 -gt 0 ] && delay1="delay $delay1" || delay1="" 23962306a36Sopenharmony_ci [ $delay2 -gt 0 ] && delay2="delay $delay2" || delay2="" 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci for dev in ns1eth1 ns1eth2; do 24262306a36Sopenharmony_ci tc -n $ns1 qdisc del dev $dev root >/dev/null 2>&1 24362306a36Sopenharmony_ci done 24462306a36Sopenharmony_ci for dev in ns2eth1 ns2eth2; do 24562306a36Sopenharmony_ci tc -n $ns2 qdisc del dev $dev root >/dev/null 2>&1 24662306a36Sopenharmony_ci done 24762306a36Sopenharmony_ci tc -n $ns1 qdisc add dev ns1eth1 root netem rate ${rate1}mbit $delay1 24862306a36Sopenharmony_ci tc -n $ns1 qdisc add dev ns1eth2 root netem rate ${rate2}mbit $delay2 24962306a36Sopenharmony_ci tc -n $ns2 qdisc add dev ns2eth1 root netem rate ${rate1}mbit $delay1 25062306a36Sopenharmony_ci tc -n $ns2 qdisc add dev ns2eth2 root netem rate ${rate2}mbit $delay2 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci # time is measured in ms, account for transfer size, aggregated link speed 25362306a36Sopenharmony_ci # and header overhead (10%) 25462306a36Sopenharmony_ci # ms byte -> bit 10% mbit -> kbit -> bit 10% 25562306a36Sopenharmony_ci local time=$((1000 * size * 8 * 10 / ((rate1 + rate2) * 1000 * 1000 * 9) )) 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci # mptcp_connect will do some sleeps to allow the mp_join handshake 25862306a36Sopenharmony_ci # completion (see mptcp_connect): 200ms on each side, add some slack 25962306a36Sopenharmony_ci time=$((time + 400 + slack)) 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci printf "%-60s" "$msg" 26262306a36Sopenharmony_ci do_transfer $small $large $time 26362306a36Sopenharmony_ci lret=$? 26462306a36Sopenharmony_ci mptcp_lib_result_code "${lret}" "${msg}" 26562306a36Sopenharmony_ci if [ $lret -ne 0 ]; then 26662306a36Sopenharmony_ci ret=$lret 26762306a36Sopenharmony_ci [ $bail -eq 0 ] || exit $ret 26862306a36Sopenharmony_ci fi 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci msg+=" - reverse direction" 27162306a36Sopenharmony_ci printf "%-60s" "${msg}" 27262306a36Sopenharmony_ci do_transfer $large $small $time 27362306a36Sopenharmony_ci lret=$? 27462306a36Sopenharmony_ci mptcp_lib_result_code "${lret}" "${msg}" 27562306a36Sopenharmony_ci if [ $lret -ne 0 ]; then 27662306a36Sopenharmony_ci ret=$lret 27762306a36Sopenharmony_ci [ $bail -eq 0 ] || exit $ret 27862306a36Sopenharmony_ci fi 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ciwhile getopts "bcdh" option;do 28262306a36Sopenharmony_ci case "$option" in 28362306a36Sopenharmony_ci "h") 28462306a36Sopenharmony_ci usage $0 28562306a36Sopenharmony_ci exit 0 28662306a36Sopenharmony_ci ;; 28762306a36Sopenharmony_ci "b") 28862306a36Sopenharmony_ci bail=1 28962306a36Sopenharmony_ci ;; 29062306a36Sopenharmony_ci "c") 29162306a36Sopenharmony_ci capture=true 29262306a36Sopenharmony_ci ;; 29362306a36Sopenharmony_ci "d") 29462306a36Sopenharmony_ci set -x 29562306a36Sopenharmony_ci ;; 29662306a36Sopenharmony_ci "?") 29762306a36Sopenharmony_ci usage $0 29862306a36Sopenharmony_ci exit 1 29962306a36Sopenharmony_ci ;; 30062306a36Sopenharmony_ci esac 30162306a36Sopenharmony_cidone 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cisetup 30462306a36Sopenharmony_cirun_test 10 10 0 0 "balanced bwidth" 30562306a36Sopenharmony_cirun_test 10 10 1 25 "balanced bwidth with unbalanced delay" 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci# we still need some additional infrastructure to pass the following test-cases 30862306a36Sopenharmony_cirun_test 10 3 0 0 "unbalanced bwidth" 30962306a36Sopenharmony_cirun_test 10 3 1 25 "unbalanced bwidth with unbalanced delay" 31062306a36Sopenharmony_cirun_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay" 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cimptcp_lib_result_print_all_tap 31362306a36Sopenharmony_ciexit $ret 314