Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
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                 # just to debug: check we have multiple subflows connection requests
0022                 ip netns exec $ns $t -A OUTPUT -p tcp --syn -m mark --mark $m -j ACCEPT
0023 
0024                 # RST packets might be handled by a internal dummy socket
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                 # let $ns2 reach any $ns1 address from any interface
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 # $1: IP address
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