362 lines · bash
1#!/bin/bash2# SPDX-License-Identifier: GPL-2.03 4# Double quotes to prevent globbing and word splitting is recommended in new5# code but we accept it, especially because there were too many before having6# address all other issues detected by shellcheck.7#shellcheck disable=SC20868 9. "$(dirname "${0}")/mptcp_lib.sh"10 11ret=012sin=""13sout=""14cin=""15cout=""16timeout_poll=3017timeout_test=$((timeout_poll * 2 + 1))18iptables="iptables"19ip6tables="ip6tables"20 21ns1=""22ns2=""23ns_sbox=""24 25usage() {26 echo "Usage: $0 [ -i ] [ -h ]"27 echo -e "\t-i: use 'ip mptcp' instead of 'pm_nl_ctl'"28 echo -e "\t-h: help"29}30 31while getopts "hi" option;do32 case "$option" in33 "h")34 usage "$0"35 exit ${KSFT_PASS}36 ;;37 "i")38 mptcp_lib_set_ip_mptcp39 ;;40 "?")41 usage "$0"42 exit ${KSFT_FAIL}43 ;;44 esac45done46 47add_mark_rules()48{49 local ns=$150 local m=$251 52 local t53 for t in ${iptables} ${ip6tables}; do54 # just to debug: check we have multiple subflows connection requests55 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT56 57 # RST packets might be handled by a internal dummy socket58 ip netns exec $ns $t -A OUTPUT -p tcp --tcp-flags RST RST -m mark --mark 0 -j ACCEPT59 60 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark $m -j ACCEPT61 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark 0 -j DROP62 done63}64 65init()66{67 mptcp_lib_ns_init ns1 ns2 ns_sbox68 69 local i70 for i in $(seq 1 4); do71 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2"72 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i73 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad74 ip -net "$ns1" link set ns1eth$i up75 76 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i77 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad78 ip -net "$ns2" link set ns2eth$i up79 80 # let $ns2 reach any $ns1 address from any interface81 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i82 83 mptcp_lib_pm_nl_add_endpoint "${ns1}" "10.0.${i}.1" flags signal84 mptcp_lib_pm_nl_add_endpoint "${ns1}" "dead:beef:${i}::1" flags signal85 86 mptcp_lib_pm_nl_add_endpoint "${ns2}" "10.0.${i}.2" flags signal87 mptcp_lib_pm_nl_add_endpoint "${ns2}" "dead:beef:${i}::2" flags signal88 done89 90 mptcp_lib_pm_nl_set_limits "${ns1}" 8 891 mptcp_lib_pm_nl_set_limits "${ns2}" 8 892 93 add_mark_rules $ns1 194 add_mark_rules $ns2 295}96 97# This function is used in the cleanup trap98#shellcheck disable=SC231799cleanup()100{101 mptcp_lib_ns_exit "${ns1}" "${ns2}" "${ns_sbox}"102 rm -f "$cin" "$cout"103 rm -f "$sin" "$sout"104}105 106mptcp_lib_check_mptcp107mptcp_lib_check_kallsyms108mptcp_lib_check_tools ip "${iptables}" "${ip6tables}"109 110check_mark()111{112 local ns=$1113 local af=$2114 115 local tables=${iptables}116 117 if [ $af -eq 6 ];then118 tables=${ip6tables}119 fi120 121 local counters values122 counters=$(ip netns exec $ns $tables -v -L OUTPUT | grep DROP)123 values=${counters%DROP*}124 125 local v126 for v in $values; do127 if [ $v -ne 0 ]; then128 mptcp_lib_pr_fail "got $tables $values in ns $ns," \129 "not 0 - not all expected packets marked"130 ret=${KSFT_FAIL}131 return 1132 fi133 done134 135 return 0136}137 138print_title()139{140 mptcp_lib_print_title "${@}"141}142 143do_transfer()144{145 local listener_ns="$1"146 local connector_ns="$2"147 local cl_proto="$3"148 local srv_proto="$4"149 local connect_addr="$5"150 151 local port=12001152 153 :> "$cout"154 :> "$sout"155 156 local mptcp_connect="./mptcp_connect -r 20"157 158 local local_addr ip159 if mptcp_lib_is_v6 "${connect_addr}"; then160 local_addr="::"161 ip=ipv6162 else163 local_addr="0.0.0.0"164 ip=ipv4165 fi166 167 cmsg="TIMESTAMPNS"168 if mptcp_lib_kallsyms_has "mptcp_ioctl$"; then169 cmsg+=",TCPINQ"170 fi171 172 timeout ${timeout_test} \173 ip netns exec ${listener_ns} \174 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c "${cmsg}" \175 ${local_addr} < "$sin" > "$sout" &176 local spid=$!177 178 sleep 1179 180 timeout ${timeout_test} \181 ip netns exec ${connector_ns} \182 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c "${cmsg}" \183 $connect_addr < "$cin" > "$cout" &184 185 local cpid=$!186 187 wait $cpid188 local retc=$?189 wait $spid190 local rets=$?191 192 print_title "Transfer ${ip:2}"193 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then194 mptcp_lib_pr_fail "client exit code $retc, server $rets"195 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2196 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port"197 198 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2199 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port"200 201 mptcp_lib_result_fail "transfer ${ip}"202 203 ret=${KSFT_FAIL}204 return 1205 fi206 if ! mptcp_lib_check_transfer $cin $sout "file received by server"; then207 rets=1208 else209 mptcp_lib_pr_ok210 fi211 mptcp_lib_result_code "${rets}" "transfer ${ip}"212 213 print_title "Mark ${ip:2}"214 if [ $local_addr = "::" ];then215 check_mark $listener_ns 6 || retc=1216 check_mark $connector_ns 6 || retc=1217 else218 check_mark $listener_ns 4 || retc=1219 check_mark $connector_ns 4 || retc=1220 fi221 222 mptcp_lib_result_code "${retc}" "mark ${ip}"223 224 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then225 mptcp_lib_pr_ok226 return 0227 fi228 mptcp_lib_pr_fail229 230 return 1231}232 233make_file()234{235 local name=$1236 local who=$2237 local size=$3238 239 mptcp_lib_make_file $name 1024 $size240 241 echo "Created $name (size $size KB) containing data sent by $who"242}243 244do_mptcp_sockopt_tests()245{246 local lret=0247 248 if ! mptcp_lib_kallsyms_has "mptcp_diag_fill_info$"; then249 mptcp_lib_pr_skip "MPTCP sockopt not supported"250 mptcp_lib_result_skip "sockopt"251 return252 fi253 254 ip netns exec "$ns_sbox" ./mptcp_sockopt255 lret=$?256 257 print_title "SOL_MPTCP sockopt v4"258 if [ $lret -ne 0 ]; then259 mptcp_lib_pr_fail260 mptcp_lib_result_fail "sockopt v4"261 ret=$lret262 return263 fi264 mptcp_lib_pr_ok265 mptcp_lib_result_pass "sockopt v4"266 267 ip netns exec "$ns_sbox" ./mptcp_sockopt -6268 lret=$?269 270 print_title "SOL_MPTCP sockopt v6"271 if [ $lret -ne 0 ]; then272 mptcp_lib_pr_fail273 mptcp_lib_result_fail "sockopt v6"274 ret=$lret275 return276 fi277 mptcp_lib_pr_ok278 mptcp_lib_result_pass "sockopt v6"279}280 281run_tests()282{283 local listener_ns="$1"284 local connector_ns="$2"285 local connect_addr="$3"286 local lret=0287 288 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr}289 290 lret=$?291 292 if [ $lret -ne 0 ]; then293 ret=$lret294 return295 fi296}297 298do_tcpinq_test()299{300 print_title "TCP_INQ cmsg/ioctl $*"301 ip netns exec "$ns_sbox" ./mptcp_inq "$@"302 local lret=$?303 if [ $lret -ne 0 ];then304 ret=$lret305 mptcp_lib_pr_fail306 mptcp_lib_result_fail "TCP_INQ: $*"307 return $lret308 fi309 310 mptcp_lib_pr_ok311 mptcp_lib_result_pass "TCP_INQ: $*"312 return $lret313}314 315do_tcpinq_tests()316{317 local lret=0318 319 if ! mptcp_lib_kallsyms_has "mptcp_ioctl$"; then320 mptcp_lib_pr_skip "TCP_INQ not supported"321 mptcp_lib_result_skip "TCP_INQ"322 return323 fi324 325 local args326 for args in "-t tcp" "-r tcp"; do327 do_tcpinq_test $args328 lret=$?329 if [ $lret -ne 0 ] ; then330 return $lret331 fi332 do_tcpinq_test -6 $args333 lret=$?334 if [ $lret -ne 0 ] ; then335 return $lret336 fi337 done338 339 do_tcpinq_test -r tcp -t tcp340 341 return $?342}343 344sin=$(mktemp)345sout=$(mktemp)346cin=$(mktemp)347cout=$(mktemp)348init349make_file "$cin" "client" 1350make_file "$sin" "server" 1351trap cleanup EXIT352mptcp_lib_subtests_last_ts_reset353 354run_tests $ns1 $ns2 10.0.1.1355run_tests $ns1 $ns2 dead:beef:1::1356 357do_mptcp_sockopt_tests358do_tcpinq_tests359 360mptcp_lib_result_print_all_tap361exit $ret362