0001
0002
0003
0004 ret=0
0005 sin=""
0006 sout=""
0007 cin=""
0008 cout=""
0009 ksft_skip=4
0010 timeout_poll=30
0011 timeout_test=$((timeout_poll * 2 + 1))
0012 mptcp_connect=""
0013 do_all_tests=1
0014
0015 add_mark_rules()
0016 {
0017 local ns=$1
0018 local m=$2
0019
0020 for t in iptables ip6tables; do
0021
0022 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT
0023
0024
0025 ip netns exec $ns $t -A OUTPUT -p tcp --tcp-flags RST RST -m mark --mark 0 -j ACCEPT
0026
0027 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark $m -j ACCEPT
0028 ip netns exec $ns $t -A OUTPUT -p tcp -m mark --mark 0 -j DROP
0029 done
0030 }
0031
0032 init()
0033 {
0034 rndh=$(printf %x $sec)-$(mktemp -u XXXXXX)
0035
0036 ns1="ns1-$rndh"
0037 ns2="ns2-$rndh"
0038
0039 for netns in "$ns1" "$ns2";do
0040 ip netns add $netns || exit $ksft_skip
0041 ip -net $netns link set lo up
0042 ip netns exec $netns sysctl -q net.mptcp.enabled=1
0043 ip netns exec $netns sysctl -q net.ipv4.conf.all.rp_filter=0
0044 ip netns exec $netns sysctl -q net.ipv4.conf.default.rp_filter=0
0045 done
0046
0047 for i in `seq 1 4`; do
0048 ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2"
0049 ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i
0050 ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad
0051 ip -net "$ns1" link set ns1eth$i up
0052
0053 ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i
0054 ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad
0055 ip -net "$ns2" link set ns2eth$i up
0056
0057
0058 ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i
0059
0060 ip netns exec $ns1 ./pm_nl_ctl add 10.0.$i.1 flags signal
0061 ip netns exec $ns1 ./pm_nl_ctl add dead:beef:$i::1 flags signal
0062
0063 ip netns exec $ns2 ./pm_nl_ctl add 10.0.$i.2 flags signal
0064 ip netns exec $ns2 ./pm_nl_ctl add dead:beef:$i::2 flags signal
0065 done
0066
0067 ip netns exec $ns1 ./pm_nl_ctl limits 8 8
0068 ip netns exec $ns2 ./pm_nl_ctl limits 8 8
0069
0070 add_mark_rules $ns1 1
0071 add_mark_rules $ns2 2
0072 }
0073
0074 cleanup()
0075 {
0076 for netns in "$ns1" "$ns2"; do
0077 ip netns del $netns
0078 done
0079 rm -f "$cin" "$cout"
0080 rm -f "$sin" "$sout"
0081 }
0082
0083 ip -Version > /dev/null 2>&1
0084 if [ $? -ne 0 ];then
0085 echo "SKIP: Could not run test without ip tool"
0086 exit $ksft_skip
0087 fi
0088
0089 iptables -V > /dev/null 2>&1
0090 if [ $? -ne 0 ];then
0091 echo "SKIP: Could not run all tests without iptables tool"
0092 exit $ksft_skip
0093 fi
0094
0095 ip6tables -V > /dev/null 2>&1
0096 if [ $? -ne 0 ];then
0097 echo "SKIP: Could not run all tests without ip6tables tool"
0098 exit $ksft_skip
0099 fi
0100
0101 check_mark()
0102 {
0103 local ns=$1
0104 local af=$2
0105
0106 tables=iptables
0107
0108 if [ $af -eq 6 ];then
0109 tables=ip6tables
0110 fi
0111
0112 counters=$(ip netns exec $ns $tables -v -L OUTPUT | grep DROP)
0113 values=${counters%DROP*}
0114
0115 for v in $values; do
0116 if [ $v -ne 0 ]; then
0117 echo "FAIL: got $tables $values in ns $ns , not 0 - not all expected packets marked" 1>&2
0118 return 1
0119 fi
0120 done
0121
0122 return 0
0123 }
0124
0125 print_file_err()
0126 {
0127 ls -l "$1" 1>&2
0128 echo "Trailing bytes are: "
0129 tail -c 27 "$1"
0130 }
0131
0132 check_transfer()
0133 {
0134 in=$1
0135 out=$2
0136 what=$3
0137
0138 cmp "$in" "$out" > /dev/null 2>&1
0139 if [ $? -ne 0 ] ;then
0140 echo "[ FAIL ] $what does not match (in, out):"
0141 print_file_err "$in"
0142 print_file_err "$out"
0143 ret=1
0144
0145 return 1
0146 fi
0147
0148 return 0
0149 }
0150
0151
0152 is_v6()
0153 {
0154 [ -z "${1##*:*}" ]
0155 }
0156
0157 do_transfer()
0158 {
0159 listener_ns="$1"
0160 connector_ns="$2"
0161 cl_proto="$3"
0162 srv_proto="$4"
0163 connect_addr="$5"
0164
0165 port=12001
0166
0167 :> "$cout"
0168 :> "$sout"
0169
0170 mptcp_connect="./mptcp_connect -r 20"
0171
0172 local local_addr
0173 if is_v6 "${connect_addr}"; then
0174 local_addr="::"
0175 else
0176 local_addr="0.0.0.0"
0177 fi
0178
0179 timeout ${timeout_test} \
0180 ip netns exec ${listener_ns} \
0181 $mptcp_connect -t ${timeout_poll} -l -M 1 -p $port -s ${srv_proto} -c TIMESTAMPNS,TCPINQ \
0182 ${local_addr} < "$sin" > "$sout" &
0183 spid=$!
0184
0185 sleep 1
0186
0187 timeout ${timeout_test} \
0188 ip netns exec ${connector_ns} \
0189 $mptcp_connect -t ${timeout_poll} -M 2 -p $port -s ${cl_proto} -c TIMESTAMPNS,TCPINQ \
0190 $connect_addr < "$cin" > "$cout" &
0191
0192 cpid=$!
0193
0194 wait $cpid
0195 retc=$?
0196 wait $spid
0197 rets=$?
0198
0199 if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
0200 echo " client exit code $retc, server $rets" 1>&2
0201 echo -e "\nnetns ${listener_ns} socket stat for ${port}:" 1>&2
0202 ip netns exec ${listener_ns} ss -Menita 1>&2 -o "sport = :$port"
0203
0204 echo -e "\nnetns ${connector_ns} socket stat for ${port}:" 1>&2
0205 ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port"
0206
0207 ret=1
0208 return 1
0209 fi
0210
0211 if [ $local_addr = "::" ];then
0212 check_mark $listener_ns 6
0213 check_mark $connector_ns 6
0214 else
0215 check_mark $listener_ns 4
0216 check_mark $connector_ns 4
0217 fi
0218
0219 check_transfer $cin $sout "file received by server"
0220
0221 rets=$?
0222
0223 if [ $retc -eq 0 ] && [ $rets -eq 0 ];then
0224 return 0
0225 fi
0226
0227 return 1
0228 }
0229
0230 make_file()
0231 {
0232 name=$1
0233 who=$2
0234 size=$3
0235
0236 dd if=/dev/urandom of="$name" bs=1024 count=$size 2> /dev/null
0237 echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
0238
0239 echo "Created $name (size $size KB) containing data sent by $who"
0240 }
0241
0242 do_mptcp_sockopt_tests()
0243 {
0244 local lret=0
0245
0246 ./mptcp_sockopt
0247 lret=$?
0248
0249 if [ $lret -ne 0 ]; then
0250 echo "FAIL: SOL_MPTCP getsockopt" 1>&2
0251 ret=$lret
0252 return
0253 fi
0254
0255 ./mptcp_sockopt -6
0256 lret=$?
0257
0258 if [ $lret -ne 0 ]; then
0259 echo "FAIL: SOL_MPTCP getsockopt (ipv6)" 1>&2
0260 ret=$lret
0261 return
0262 fi
0263 }
0264
0265 run_tests()
0266 {
0267 listener_ns="$1"
0268 connector_ns="$2"
0269 connect_addr="$3"
0270 local lret=0
0271
0272 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr}
0273
0274 lret=$?
0275
0276 if [ $lret -ne 0 ]; then
0277 ret=$lret
0278 return
0279 fi
0280 }
0281
0282 do_tcpinq_test()
0283 {
0284 ip netns exec "$ns1" ./mptcp_inq "$@"
0285 lret=$?
0286 if [ $lret -ne 0 ];then
0287 ret=$lret
0288 echo "FAIL: mptcp_inq $@" 1>&2
0289 return $lret
0290 fi
0291
0292 echo "PASS: TCP_INQ cmsg/ioctl $@"
0293 return $lret
0294 }
0295
0296 do_tcpinq_tests()
0297 {
0298 local lret=0
0299
0300 ip netns exec "$ns1" iptables -F
0301 ip netns exec "$ns1" ip6tables -F
0302
0303 for args in "-t tcp" "-r tcp"; do
0304 do_tcpinq_test $args
0305 lret=$?
0306 if [ $lret -ne 0 ] ; then
0307 return $lret
0308 fi
0309 do_tcpinq_test -6 $args
0310 lret=$?
0311 if [ $lret -ne 0 ] ; then
0312 return $lret
0313 fi
0314 done
0315
0316 do_tcpinq_test -r tcp -t tcp
0317
0318 return $?
0319 }
0320
0321 sin=$(mktemp)
0322 sout=$(mktemp)
0323 cin=$(mktemp)
0324 cout=$(mktemp)
0325 init
0326 make_file "$cin" "client" 1
0327 make_file "$sin" "server" 1
0328 trap cleanup EXIT
0329
0330 run_tests $ns1 $ns2 10.0.1.1
0331 run_tests $ns1 $ns2 dead:beef:1::1
0332
0333 if [ $ret -eq 0 ];then
0334 echo "PASS: all packets had packet mark set"
0335 fi
0336
0337 do_mptcp_sockopt_tests
0338 if [ $ret -eq 0 ];then
0339 echo "PASS: SOL_MPTCP getsockopt has expected information"
0340 fi
0341
0342 do_tcpinq_tests
0343 exit $ret