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 ns_sbox="ns_sbox-$rndh" 39 40 for netns in "$ns1" "$ns2" "$ns_sbox";do 41 ip netns add $netns || exit $ksft_skip 42 ip -net $netns link set lo up 43 ip netns exec $netns sysctl -q net.mptcp.enabled=1 44 ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0 45 ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0 46 done 47 48 for i in `seq 1 4`; do 49 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2" 50 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i 51 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad 52 ip -net "$ns1" link set ns1eth$i up 53 54 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i 55 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad 56 ip -net "$ns2" link set ns2eth$i up 57 58 # let $ns2 reach any $ns1 address from any interface 59 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i 60 61 ip netns exec $ns1 ./pm_nl_ctl add 10.0.$i.1 flags signal 62 ip netns exec $ns1 ./pm_nl_ctl add dead:beef:$i::1 flags signal 63 64 ip netns exec $ns2 ./pm_nl_ctl add 10.0.$i.2 flags signal 65 ip netns exec $ns2 ./pm_nl_ctl add dead:beef:$i::2 flags signal 66 done 67 68 ip netns exec $ns1 ./pm_nl_ctl limits 8 8 69 ip netns exec $ns2 ./pm_nl_ctl limits 8 8 70 71 add_mark_rules $ns1 1 72 add_mark_rules $ns2 2 73} 74 75cleanup() 76{ 77 for netns in "$ns1" "$ns2" "$ns_sbox"; do 78 ip netns del $netns 79 done 80 rm -f "$cin" "$cout" 81 rm -f "$sin" "$sout" 82} 83 84ip -Version > /dev/null 2>&1 85if [ $? -ne 0 ];then 86 echo "SKIP: Could not run test without ip tool" 87 exit $ksft_skip 88fi 89 90iptables -V > /dev/null 2>&1 91if [ $? -ne 0 ];then 92 echo "SKIP: Could not run all tests without iptables tool" 93 exit $ksft_skip 94fi 95 96ip6tables -V > /dev/null 2>&1 97if [ $? -ne 0 ];then 98 echo "SKIP: Could not run all tests without ip6tables tool" 99 exit $ksft_skip 100fi 101 102check_mark() 103{ 104 local ns=$1 105 local af=$2 106 107 tables=iptables 108 109 if [ $af -eq 6 ];then 110 tables=ip6tables 111 fi 112 113 counters=$(ip netns exec $ns $tables -v -L OUTPUT | grep DROP) 114 values=${counters%DROP*} 115 116 for v in $values; do 117 if [ $v -ne 0 ]; then 118 echo "FAIL: got $tables $values in ns $ns , not 0 - not all expected packets marked" 1>&2 119 return 1 120 fi 121 done 122 123 return 0 124} 125 126print_file_err() 127{ 128 ls -l "$1" 1>&2 129 echo "Trailing bytes are: " 130 tail -c 27 "$1" 131} 132 133check_transfer() 134{ 135 in=$1 136 out=$2 137 what=$3 138 139 cmp "$in" "$out" > /dev/null 2>&1 140 if [ $? -ne 0 ] ;then 141 echo "[ FAIL ] $what does not match (in, out):" 142 print_file_err "$in" 143 print_file_err "$out" 144 ret=1 145 146 return 1 147 fi 148 149 return 0 150} 151 152# $1: IP address 153is_v6() 154{ 155 [ -z "${1##*:*}" ] 156} 157 158do_transfer() 159{ 160 listener_ns="$1" 161 connector_ns="$2" 162 cl_proto="$3" 163 srv_proto="$4" 164 connect_addr="$5" 165 166 port=12001 167 168 :> "$cout" 169 :> "$sout" 170 171 mptcp_connect="./mptcp_connect -r 20" 172 173 local local_addr 174 if is_v6 "${connect_addr}"; then 175 local_addr="::" 176 else 177 local_addr="0.0.0.0" 178 fi 179 180 timeout ${timeout_test} \ 181 ip netns exec ${listener_ns} \ 182 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c TIMESTAMPNS,TCPINQ \ 183 ${local_addr} < "$sin" > "$sout" & 184 spid=$! 185 186 sleep 1 187 188 timeout ${timeout_test} \ 189 ip netns exec ${connector_ns} \ 190 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c TIMESTAMPNS,TCPINQ \ 191 $connect_addr < "$cin" > "$cout" & 192 193 cpid=$! 194 195 wait $cpid 196 retc=$? 197 wait $spid 198 rets=$? 199 200 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then 201 echo " client exit code $retc, server $rets" 1>&2 202 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2 203 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port" 204 205 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2 206 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port" 207 208 ret=1 209 return 1 210 fi 211 212 if [ $local_addr = "::" ];then 213 check_mark $listener_ns 6 214 check_mark $connector_ns 6 215 else 216 check_mark $listener_ns 4 217 check_mark $connector_ns 4 218 fi 219 220 check_transfer $cin $sout "file received by server" 221 222 rets=$? 223 224 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then 225 return 0 226 fi 227 228 return 1 229} 230 231make_file() 232{ 233 name=$1 234 who=$2 235 size=$3 236 237 dd if=/dev/urandom of="$name" bs=1024 count=$size 2> /dev/null 238 echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name" 239 240 echo "Created $name (size $size KB) containing data sent by $who" 241} 242 243do_mptcp_sockopt_tests() 244{ 245 local lret=0 246 247 ip netns exec "$ns_sbox" ./mptcp_sockopt 248 lret=$? 249 250 if [ $lret -ne 0 ]; then 251 echo "FAIL: SOL_MPTCP getsockopt" 1>&2 252 ret=$lret 253 return 254 fi 255 256 ip netns exec "$ns_sbox" ./mptcp_sockopt -6 257 lret=$? 258 259 if [ $lret -ne 0 ]; then 260 echo "FAIL: SOL_MPTCP getsockopt (ipv6)" 1>&2 261 ret=$lret 262 return 263 fi 264} 265 266run_tests() 267{ 268 listener_ns="$1" 269 connector_ns="$2" 270 connect_addr="$3" 271 local lret=0 272 273 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} 274 275 lret=$? 276 277 if [ $lret -ne 0 ]; then 278 ret=$lret 279 return 280 fi 281} 282 283do_tcpinq_test() 284{ 285 ip netns exec "$ns1" ./mptcp_inq "$@" 286 lret=$? 287 if [ $lret -ne 0 ];then 288 ret=$lret 289 echo "FAIL: mptcp_inq $@" 1>&2 290 return $lret 291 fi 292 293 echo "PASS: TCP_INQ cmsg/ioctl $@" 294 return $lret 295} 296 297do_tcpinq_tests() 298{ 299 local lret=0 300 301 ip netns exec "$ns1" iptables -F 302 ip netns exec "$ns1" ip6tables -F 303 304 for args in "-t tcp" "-r tcp"; do 305 do_tcpinq_test $args 306 lret=$? 307 if [ $lret -ne 0 ] ; then 308 return $lret 309 fi 310 do_tcpinq_test -6 $args 311 lret=$? 312 if [ $lret -ne 0 ] ; then 313 return $lret 314 fi 315 done 316 317 do_tcpinq_test -r tcp -t tcp 318 319 return $? 320} 321 322sin=$(mktemp) 323sout=$(mktemp) 324cin=$(mktemp) 325cout=$(mktemp) 326init 327make_file "$cin" "client" 1 328make_file "$sin" "server" 1 329trap cleanup EXIT 330 331run_tests $ns1 $ns2 10.0.1.1 332run_tests $ns1 $ns2 dead:beef:1::1 333 334if [ $ret -eq 0 ];then 335 echo "PASS: all packets had packet mark set" 336fi 337 338do_mptcp_sockopt_tests 339if [ $ret -eq 0 ];then 340 echo "PASS: SOL_MPTCP getsockopt has expected information" 341fi 342 343do_tcpinq_tests 344exit $ret 345