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