1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4. "$(dirname "${0}")/mptcp_lib.sh" 5 6ret=0 7sin="" 8sout="" 9cin="" 10cout="" 11ksft_skip=4 12timeout_poll=30 13timeout_test=$((timeout_poll * 2 + 1)) 14mptcp_connect="" 15do_all_tests=1 16iptables="iptables" 17ip6tables="ip6tables" 18 19add_mark_rules() 20{ 21 local ns=$1 22 local m=$2 23 24 for t in ${iptables} ${ip6tables}; do 25 # just to debug: check we have multiple subflows connection requests 26 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT 27 28 # RST packets might be handled by a internal dummy socket 29 ip netns exec $ns $t -A OUTPUT -p tcp --tcp-flags RST RST -m mark --mark 0 -j ACCEPT 30 31 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark $m -j ACCEPT 32 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark 0 -j DROP 33 done 34} 35 36init() 37{ 38 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) 39 40 ns1="ns1-$rndh" 41 ns2="ns2-$rndh" 42 43 for netns in "$ns1" "$ns2";do 44 ip netns add $netns || exit $ksft_skip 45 ip -net $netns link set lo up 46 ip netns exec $netns sysctl -q net.mptcp.enabled=1 47 ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0 48 ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0 49 done 50 51 for i in `seq 1 4`; do 52 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2" 53 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i 54 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad 55 ip -net "$ns1" link set ns1eth$i up 56 57 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i 58 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad 59 ip -net "$ns2" link set ns2eth$i up 60 61 # let $ns2 reach any $ns1 address from any interface 62 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i 63 64 ip netns exec $ns1 ./pm_nl_ctl add 10.0.$i.1 flags signal 65 ip netns exec $ns1 ./pm_nl_ctl add dead:beef:$i::1 flags signal 66 67 ip netns exec $ns2 ./pm_nl_ctl add 10.0.$i.2 flags signal 68 ip netns exec $ns2 ./pm_nl_ctl add dead:beef:$i::2 flags signal 69 done 70 71 ip netns exec $ns1 ./pm_nl_ctl limits 8 8 72 ip netns exec $ns2 ./pm_nl_ctl limits 8 8 73 74 add_mark_rules $ns1 1 75 add_mark_rules $ns2 2 76} 77 78cleanup() 79{ 80 for netns in "$ns1" "$ns2"; do 81 ip netns del $netns 82 done 83 rm -f "$cin" "$cout" 84 rm -f "$sin" "$sout" 85} 86 87mptcp_lib_check_mptcp 88 89ip -Version > /dev/null 2>&1 90if [ $? -ne 0 ];then 91 echo "SKIP: Could not run test without ip tool" 92 exit $ksft_skip 93fi 94 95# Use the legacy version if available to support old kernel versions 96if iptables-legacy -V &> /dev/null; then 97 iptables="iptables-legacy" 98 ip6tables="ip6tables-legacy" 99elif ! iptables -V &> /dev/null; then 100 echo "SKIP: Could not run all tests without iptables tool" 101 exit $ksft_skip 102elif ! ip6tables -V &> /dev/null; then 103 echo "SKIP: Could not run all tests without ip6tables tool" 104 exit $ksft_skip 105fi 106 107check_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 ret=1 125 return 1 126 fi 127 done 128 129 return 0 130} 131 132print_file_err() 133{ 134 ls -l "$1" 1>&2 135 echo "Trailing bytes are: " 136 tail -c 27 "$1" 137} 138 139check_transfer() 140{ 141 in=$1 142 out=$2 143 what=$3 144 145 cmp "$in" "$out" > /dev/null 2>&1 146 if [ $? -ne 0 ] ;then 147 echo "[ FAIL ] $what does not match (in, out):" 148 print_file_err "$in" 149 print_file_err "$out" 150 ret=1 151 152 return 1 153 fi 154 155 return 0 156} 157 158# $1: IP address 159is_v6() 160{ 161 [ -z "${1##*:*}" ] 162} 163 164do_transfer() 165{ 166 listener_ns="$1" 167 connector_ns="$2" 168 cl_proto="$3" 169 srv_proto="$4" 170 connect_addr="$5" 171 172 port=12001 173 174 :> "$cout" 175 :> "$sout" 176 177 mptcp_connect="./mptcp_connect -r 20" 178 179 local local_addr 180 if is_v6 "${connect_addr}"; then 181 local_addr="::" 182 else 183 local_addr="0.0.0.0" 184 fi 185 186 timeout ${timeout_test} \ 187 ip netns exec ${listener_ns} \ 188 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c TIMESTAMPNS \ 189 ${local_addr} < "$sin" > "$sout" & 190 spid=$! 191 192 sleep 1 193 194 timeout ${timeout_test} \ 195 ip netns exec ${connector_ns} \ 196 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c TIMESTAMPNS \ 197 $connect_addr < "$cin" > "$cout" & 198 199 cpid=$! 200 201 wait $cpid 202 retc=$? 203 wait $spid 204 rets=$? 205 206 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then 207 echo " client exit code $retc, server $rets" 1>&2 208 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2 209 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port" 210 211 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2 212 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port" 213 214 ret=1 215 return 1 216 fi 217 218 if [ $local_addr = "::" ];then 219 check_mark $listener_ns 6 || retc=1 220 check_mark $connector_ns 6 || retc=1 221 else 222 check_mark $listener_ns 4 || retc=1 223 check_mark $connector_ns 4 || retc=1 224 fi 225 226 check_transfer $cin $sout "file received by server" 227 228 rets=$? 229 230 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then 231 return 0 232 fi 233 234 return 1 235} 236 237make_file() 238{ 239 name=$1 240 who=$2 241 size=$3 242 243 dd if=/dev/urandom of="$name" bs=1024 count=$size 2> /dev/null 244 echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name" 245 246 echo "Created $name (size $size KB) containing data sent by $who" 247} 248 249run_tests() 250{ 251 listener_ns="$1" 252 connector_ns="$2" 253 connect_addr="$3" 254 lret=0 255 256 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 257 258 lret=$? 259 260 if [ $lret -ne 0 ]; then 261 ret=$lret 262 return 263 fi 264} 265 266sin=$(mktemp) 267sout=$(mktemp) 268cin=$(mktemp) 269cout=$(mktemp) 270init 271make_file "$cin" "client" 1 272make_file "$sin" "server" 1 273trap cleanup EXIT 274 275run_tests $ns1 $ns2 10.0.1.1 276run_tests $ns1 $ns2 dead:beef:1::1 277 278 279if [ $ret -eq 0 ];then 280 echo "PASS: all packets had packet mark set" 281fi 282 283exit $ret 284