diff --git a/net/mptcp/mib.c b/net/mptcp/mib.c index 7558802a14350..e55d3dfbee0c3 100644 --- a/net/mptcp/mib.c +++ b/net/mptcp/mib.c @@ -48,6 +48,10 @@ static const struct snmp_mib mptcp_snmp_list[] = { SNMP_MIB_ITEM("MPPrioRx", MPTCP_MIB_MPPRIORX), SNMP_MIB_ITEM("MPFailTx", MPTCP_MIB_MPFAILTX), SNMP_MIB_ITEM("MPFailRx", MPTCP_MIB_MPFAILRX), + SNMP_MIB_ITEM("MPFastcloseTx", MPTCP_MIB_MPFASTCLOSETX), + SNMP_MIB_ITEM("MPFastcloseRx", MPTCP_MIB_MPFASTCLOSERX), + SNMP_MIB_ITEM("MPRstTx", MPTCP_MIB_MPRSTTX), + SNMP_MIB_ITEM("MPRstRx", MPTCP_MIB_MPRSTRX), SNMP_MIB_ITEM("RcvPruned", MPTCP_MIB_RCVPRUNED), SNMP_MIB_ITEM("SubflowStale", MPTCP_MIB_SUBFLOWSTALE), SNMP_MIB_ITEM("SubflowRecover", MPTCP_MIB_SUBFLOWRECOVER), diff --git a/net/mptcp/mib.h b/net/mptcp/mib.h index 2966fcb6548ba..00576179a619f 100644 --- a/net/mptcp/mib.h +++ b/net/mptcp/mib.h @@ -41,6 +41,10 @@ enum linux_mptcp_mib_field { MPTCP_MIB_MPPRIORX, /* Received a MP_PRIO */ MPTCP_MIB_MPFAILTX, /* Transmit a MP_FAIL */ MPTCP_MIB_MPFAILRX, /* Received a MP_FAIL */ + MPTCP_MIB_MPFASTCLOSETX, /* Transmit a MP_FASTCLOSE */ + MPTCP_MIB_MPFASTCLOSERX, /* Received a MP_FASTCLOSE */ + MPTCP_MIB_MPRSTTX, /* Transmit a MP_RST */ + MPTCP_MIB_MPRSTRX, /* Received a MP_RST */ MPTCP_MIB_RCVPRUNED, /* Incoming packet dropped due to memory limit */ MPTCP_MIB_SUBFLOWSTALE, /* Subflows entered 'stale' status */ MPTCP_MIB_SUBFLOWRECOVER, /* Subflows returned to active status after being stale */ diff --git a/net/mptcp/options.c b/net/mptcp/options.c index ac10a04ccd7cc..325383646f5c0 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -323,6 +323,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, mp_opt->rcvr_key = get_unaligned_be64(ptr); ptr += 8; mp_opt->suboptions |= OPTION_MPTCP_FASTCLOSE; + pr_debug("MP_FASTCLOSE: recv_key=%llu", mp_opt->rcvr_key); break; case MPTCPOPT_RST: @@ -832,11 +833,13 @@ bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { *size += opt_size; remaining -= opt_size; + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSETX); } /* MP_RST can be used with MP_FASTCLOSE and MP_FAIL if there is room */ if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { *size += opt_size; remaining -= opt_size; + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTTX); } return true; } @@ -1124,6 +1127,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) msk->local_key == mp_opt.rcvr_key) { WRITE_ONCE(msk->rcv_fastclose, true); mptcp_schedule_work((struct sock *)msk); + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPFASTCLOSERX); } if ((mp_opt.suboptions & OPTION_MPTCP_ADD_ADDR) && @@ -1158,6 +1162,7 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) subflow->reset_seen = 1; subflow->reset_reason = mp_opt.reset_reason; subflow->reset_transient = mp_opt.reset_transient; + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPRSTRX); } if (!(mp_opt.suboptions & OPTION_MPTCP_DSS)) diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh index 77b359a49a470..45c6e5f069164 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -12,14 +12,15 @@ cout="" ksft_skip=4 timeout_poll=30 timeout_test=$((timeout_poll * 2 + 1)) -mptcp_connect="" capture=0 checksum=0 ip_mptcp=0 +check_invert=0 do_all_tests=1 init=0 TEST_COUNT=0 +nr_blank=40 # generated using "nfbpf_compile '(ip && (ip[54] & 0xf0) == 0x30) || # (ip6 && (ip6[74] & 0xf0) == 0x30)'" @@ -59,6 +60,8 @@ init_partial() fi done + check_invert=0 + # ns1 ns2 # ns1eth1 ns2eth1 # ns1eth2 ns2eth2 @@ -216,15 +219,21 @@ check_transfer() out=$2 what=$3 - cmp "$in" "$out" > /dev/null 2>&1 - if [ $? -ne 0 ] ;then - echo "[ FAIL ] $what does not match (in, out):" - print_file_err "$in" - print_file_err "$out" - ret=1 + cmp -l "$in" "$out" | while read line; do + local arr=($line) - return 1 - fi + let sum=0${arr[1]}+0${arr[2]} + if [ $check_invert -eq 0 ] || [ $sum -ne $((0xff)) ]; then + echo "[ FAIL ] $what does not match (in, out):" + print_file_err "$in" + print_file_err "$out" + ret=1 + + return 1 + else + echo "$what has inverted byte at ${arr[0]}" + fi + done return 0 } @@ -443,12 +452,19 @@ do_transfer() NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \ nstat -n + local extra_args if [ $speed = "fast" ]; then - mptcp_connect="./mptcp_connect -j" + extra_args="-j" elif [ $speed = "slow" ]; then - mptcp_connect="./mptcp_connect -r 50" - elif [ $speed = "least" ]; then - mptcp_connect="./mptcp_connect -r 10" + extra_args="-r 50" + elif [[ $speed = "speed_"* ]]; then + extra_args="-r ${speed:6}" + fi + + if [[ "${addr_nr_ns2}" = "fastclose_"* ]]; then + # disconnect + extra_args="$extra_args -I ${addr_nr_ns2:10}" + addr_nr_ns2=0 fi local local_addr @@ -458,16 +474,16 @@ do_transfer() local_addr="0.0.0.0" fi - if [ "$test_link_fail" -eq 2 ];then + if [ "$test_link_fail" -gt 1 ];then timeout ${timeout_test} \ ip netns exec ${listener_ns} \ - $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - ${local_addr} < "$sinfail" > "$sout" & + ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ + $extra_args ${local_addr} < "$sinfail" > "$sout" & else timeout ${timeout_test} \ ip netns exec ${listener_ns} \ - $mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - ${local_addr} < "$sin" > "$sout" & + ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ + $extra_args ${local_addr} < "$sin" > "$sout" & fi spid=$! @@ -476,15 +492,21 @@ do_transfer() if [ "$test_link_fail" -eq 0 ];then timeout ${timeout_test} \ ip netns exec ${connector_ns} \ - $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ - $connect_addr < "$cin" > "$cout" & - else + ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ + $extra_args $connect_addr < "$cin" > "$cout" & + elif [ "$test_link_fail" -eq 1 ] || [ "$test_link_fail" -eq 2 ];then ( cat "$cinfail" ; sleep 2; link_failure $listener_ns ; cat "$cinfail" ) | \ tee "$cinsent" | \ timeout ${timeout_test} \ ip netns exec ${connector_ns} \ - $mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ - $connect_addr > "$cout" & + ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ + $extra_args $connect_addr > "$cout" & + else + cat "$cinfail" | tee "$cinsent" | \ + timeout ${timeout_test} \ + ip netns exec ${connector_ns} \ + ./mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \ + $extra_args $connect_addr > "$cout" & fi cpid=$! @@ -644,7 +666,7 @@ do_transfer() return 1 fi - if [ "$test_link_fail" -eq 2 ];then + if [ "$test_link_fail" -gt 1 ];then check_transfer $sinfail $cout "file received by client" else check_transfer $sin $cout "file received by client" @@ -689,9 +711,18 @@ run_tests() speed="${7:-fast}" sflags="${8:-""}" + # The values above 2 are reused to make test files + # with the given sizes (KB) + if [ "$test_linkfail" -gt 2 ]; then + size=$test_linkfail + + if [ -z "$cinfail" ]; then + cinfail=$(mktemp) + fi + make_file "$cinfail" "client" $size # create the input file for the failure test when # the first failure test run - if [ "$test_linkfail" -ne 0 -a -z "$cinfail" ]; then + elif [ "$test_linkfail" -ne 0 -a -z "$cinfail" ]; then # the client file must be considerably larger # of the maximum expected cwin value, or the # link utilization will be not predicable @@ -704,7 +735,14 @@ run_tests() make_file "$cinfail" "client" $size fi - if [ "$test_linkfail" -eq 2 -a -z "$sinfail" ]; then + if [ "$test_linkfail" -gt 2 ]; then + size=$test_linkfail + + if [ -z "$sinfail" ]; then + sinfail=$(mktemp) + fi + make_file "$sinfail" "server" $size + elif [ "$test_linkfail" -eq 2 -a -z "$sinfail" ]; then size=$((RANDOM%16)) size=$((size+1)) size=$((size*2048)) @@ -728,19 +766,33 @@ dump_stats() chk_csum_nr() { local msg=${1:-""} + local csum_ns1=${2:-0} + local csum_ns2=${3:-0} local count local dump_stats + local allow_multi_errors_ns1=0 + local allow_multi_errors_ns2=0 + + if [[ "${csum_ns1}" = "+"* ]]; then + allow_multi_errors_ns1=1 + csum_ns1=${csum_ns1:1} + fi + if [[ "${csum_ns2}" = "+"* ]]; then + allow_multi_errors_ns2=1 + csum_ns2=${csum_ns2:1} + fi if [ ! -z "$msg" ]; then - printf "%02u" "$TEST_COUNT" + printf "%03u" "$TEST_COUNT" else - echo -n " " + echo -n " " fi printf " %-36s %s" "$msg" "sum" count=`ip netns exec $ns1 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}'` [ -z "$count" ] && count=0 - if [ "$count" != 0 ]; then - echo "[fail] got $count data checksum error[s] expected 0" + if [ "$count" != $csum_ns1 -a $allow_multi_errors_ns1 -eq 0 ] || + [ "$count" -lt $csum_ns1 -a $allow_multi_errors_ns1 -eq 1 ]; then + echo "[fail] got $count data checksum error[s] expected $csum_ns1" ret=1 dump_stats=1 else @@ -749,8 +801,9 @@ chk_csum_nr() echo -n " - csum " count=`ip netns exec $ns2 nstat -as | grep MPTcpExtDataCsumErr | awk '{print $2}'` [ -z "$count" ] && count=0 - if [ "$count" != 0 ]; then - echo "[fail] got $count data checksum error[s] expected 0" + if [ "$count" != $csum_ns2 -a $allow_multi_errors_ns2 -eq 0 ] || + [ "$count" -lt $csum_ns2 -a $allow_multi_errors_ns2 -eq 1 ]; then + echo "[fail] got $count data checksum error[s] expected $csum_ns2" ret=1 dump_stats=1 else @@ -761,27 +814,59 @@ chk_csum_nr() chk_fail_nr() { - local mp_fail_nr_tx=$1 - local mp_fail_nr_rx=$2 + local fail_tx=$1 + local fail_rx=$2 local count local dump_stats - printf "%-39s %s" " " "ftx" + printf "%-${nr_blank}s %s" " " "ftx" count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPFailTx | awk '{print $2}'` [ -z "$count" ] && count=0 - if [ "$count" != "$mp_fail_nr_tx" ]; then - echo "[fail] got $count MP_FAIL[s] TX expected $mp_fail_nr_tx" + if [ "$count" != "$fail_tx" ]; then + echo "[fail] got $count MP_FAIL[s] TX expected $fail_tx" ret=1 dump_stats=1 else echo -n "[ ok ]" fi - echo -n " - frx " + echo -n " - failrx" count=`ip netns exec $ns2 nstat -as | grep MPTcpExtMPFailRx | awk '{print $2}'` [ -z "$count" ] && count=0 - if [ "$count" != "$mp_fail_nr_rx" ]; then - echo "[fail] got $count MP_FAIL[s] RX expected $mp_fail_nr_rx" + if [ "$count" != "$fail_rx" ]; then + echo "[fail] got $count MP_FAIL[s] RX expected $fail_rx" + ret=1 + dump_stats=1 + else + echo "[ ok ]" + fi + + [ "${dump_stats}" = 1 ] && dump_stats +} + +chk_fclose_nr() +{ + local fclose_tx=$1 + local fclose_rx=$2 + local count + local dump_stats + + printf "%-${nr_blank}s %s" " " "ctx" + count=$(ip netns exec $ns2 nstat -as | grep MPTcpExtMPFastcloseTx | awk '{print $2}') + [ -z "$count" ] && count=0 + if [ "$count" != "$fclose_tx" ]; then + echo "[fail] got $count MP_FASTCLOSE[s] TX expected $fclose_tx" + ret=1 + dump_stats=1 + else + echo -n "[ ok ]" + fi + + echo -n " - fclzrx" + count=$(ip netns exec $ns1 nstat -as | grep MPTcpExtMPFastcloseRx | awk '{print $2}') + [ -z "$count" ] && count=0 + if [ "$count" != "$fclose_rx" ]; then + echo "[fail] got $count MP_FASTCLOSE[s] RX expected $fclose_rx" ret=1 dump_stats=1 else @@ -791,17 +876,65 @@ chk_fail_nr() [ "${dump_stats}" = 1 ] && dump_stats } +chk_rst_nr() +{ + local rst_tx=$1 + local rst_rx=$2 + local ns_invert=${3:-""} + local count + local dump_stats + local ns_tx=$ns1 + local ns_rx=$ns2 + local extra_msg="" + + if [[ $ns_invert = "invert" ]]; then + ns_tx=$ns2 + ns_rx=$ns1 + extra_msg=" invert" + fi + + printf "%-${nr_blank}s %s" " " "rtx" + count=$(ip netns exec $ns_tx nstat -as | grep MPTcpExtMPRstTx | awk '{print $2}') + [ -z "$count" ] && count=0 + if [ "$count" != "$rst_tx" ]; then + echo "[fail] got $count MP_RST[s] TX expected $rst_tx" + ret=1 + dump_stats=1 + else + echo -n "[ ok ]" + fi + + echo -n " - rstrx " + count=$(ip netns exec $ns_rx nstat -as | grep MPTcpExtMPRstRx | awk '{print $2}') + [ -z "$count" ] && count=0 + if [ "$count" != "$rst_rx" ]; then + echo "[fail] got $count MP_RST[s] RX expected $rst_rx" + ret=1 + dump_stats=1 + else + echo -n "[ ok ]" + fi + + [ "${dump_stats}" = 1 ] && dump_stats + + echo "$extra_msg" +} + chk_join_nr() { local msg="$1" local syn_nr=$2 local syn_ack_nr=$3 local ack_nr=$4 + local csum_ns1=${5:-0} + local csum_ns2=${6:-0} + local fail_nr=${7:-0} + local rst_nr=${8:-0} local count local dump_stats local with_cookie - printf "%02u %-36s %s" "$TEST_COUNT" "$msg" "syn" + printf "%03u %-36s %s" "$TEST_COUNT" "$msg" "syn" count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinSynRx | awk '{print $2}'` [ -z "$count" ] && count=0 if [ "$count" != "$syn_nr" ]; then @@ -843,8 +976,9 @@ chk_join_nr() fi [ "${dump_stats}" = 1 ] && dump_stats if [ $checksum -eq 1 ]; then - chk_csum_nr - chk_fail_nr 0 0 + chk_csum_nr "" $csum_ns1 $csum_ns2 + chk_fail_nr $fail_nr $fail_nr + chk_rst_nr $rst_nr $rst_nr fi } @@ -863,7 +997,7 @@ chk_stale_nr() local stale_nr local recover_nr - printf "%-39s %-18s" " " "stale" + printf "%-${nr_blank}s %-18s" " " "stale" stale_nr=`ip netns exec $ns nstat -as | grep MPTcpExtSubflowStale | awk '{print $2}'` [ -z "$stale_nr" ] && stale_nr=0 recover_nr=`ip netns exec $ns nstat -as | grep MPTcpExtSubflowRecover | awk '{print $2}'` @@ -904,7 +1038,7 @@ chk_add_nr() timeout=`ip netns exec $ns1 sysctl -n net.mptcp.add_addr_timeout` - printf "%-39s %s" " " "add" + printf "%-${nr_blank}s %s" " " "add" count=`ip netns exec $ns2 nstat -as MPTcpExtAddAddr | grep MPTcpExtAddAddr | awk '{print $2}'` [ -z "$count" ] && count=0 @@ -941,7 +1075,7 @@ chk_add_nr() echo "[ ok ]" fi - printf "%-39s %s" " " "syn" + printf "%-${nr_blank}s %s" " " "syn" count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPJoinPortSynRx | awk '{print $2}'` [ -z "$count" ] && count=0 @@ -980,7 +1114,7 @@ chk_add_nr() echo "[ ok ]" fi - printf "%-39s %s" " " "syn" + printf "%-${nr_blank}s %s" " " "syn" count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMismatchPortSynRx | awk '{print $2}'` [ -z "$count" ] && count=0 @@ -1019,18 +1153,17 @@ chk_rm_nr() local invert=${3:-""} local count local dump_stats - local addr_ns - local subflow_ns + local addr_ns=$ns1 + local subflow_ns=$ns2 + local extra_msg="" - if [ -z $invert ]; then - addr_ns=$ns1 - subflow_ns=$ns2 - elif [ $invert = "invert" ]; then + if [[ $invert = "invert" ]]; then addr_ns=$ns2 subflow_ns=$ns1 + extra_msg=" invert" fi - printf "%-39s %s" " " "rm " + printf "%-${nr_blank}s %s" " " "rm " count=`ip netns exec $addr_ns nstat -as | grep MPTcpExtRmAddr | awk '{print $2}'` [ -z "$count" ] && count=0 if [ "$count" != "$rm_addr_nr" ]; then @@ -1041,7 +1174,7 @@ chk_rm_nr() echo -n "[ ok ]" fi - echo -n " - sf " + echo -n " - rmsf " count=`ip netns exec $subflow_ns nstat -as | grep MPTcpExtRmSubflow | awk '{print $2}'` [ -z "$count" ] && count=0 if [ "$count" != "$rm_subflow_nr" ]; then @@ -1049,10 +1182,12 @@ chk_rm_nr() ret=1 dump_stats=1 else - echo "[ ok ]" + echo -n "[ ok ]" fi [ "${dump_stats}" = 1 ] && dump_stats + + echo "$extra_msg" } chk_prio_nr() @@ -1062,7 +1197,7 @@ chk_prio_nr() local count local dump_stats - printf "%-39s %s" " " "ptx" + printf "%-${nr_blank}s %s" " " "ptx" count=`ip netns exec $ns1 nstat -as | grep MPTcpExtMPPrioTx | awk '{print $2}'` [ -z "$count" ] && count=0 if [ "$count" != "$mp_prio_nr_tx" ]; then @@ -1098,7 +1233,7 @@ chk_link_usage() local tx_rate=$((tx_link * 100 / $tx_total)) local tolerance=5 - printf "%-39s %-18s" " " "link usage" + printf "%-${nr_blank}s %-18s" " " "link usage" if [ $tx_rate -lt $((expected_rate - $tolerance)) -o \ $tx_rate -gt $((expected_rate + $tolerance)) ]; then echo "[fail] got $tx_rate% usage, expected $expected_rate%" @@ -1429,7 +1564,7 @@ add_addr_timeout_tests() pm_nl_add_endpoint $ns1 10.0.2.1 flags signal pm_nl_add_endpoint $ns1 10.0.3.1 flags signal pm_nl_set_limits $ns2 2 2 - run_tests $ns1 $ns2 10.0.1.1 0 0 0 least + run_tests $ns1 $ns2 10.0.1.1 0 0 0 speed_10 chk_join_nr "signal addresses, ADD_ADDR timeout" 2 2 2 chk_add_nr 8 0 @@ -1439,7 +1574,7 @@ add_addr_timeout_tests() pm_nl_add_endpoint $ns1 10.0.12.1 flags signal pm_nl_add_endpoint $ns1 10.0.3.1 flags signal pm_nl_set_limits $ns2 2 2 - run_tests $ns1 $ns2 10.0.1.1 0 0 0 least + run_tests $ns1 $ns2 10.0.1.1 0 0 0 speed_10 chk_join_nr "invalid address, ADD_ADDR timeout" 1 1 1 chk_add_nr 8 0 } @@ -2096,6 +2231,15 @@ fullmesh_tests() chk_rm_nr 0 1 } +fastclose_tests() +{ + reset + run_tests $ns1 $ns2 10.0.1.1 1024 0 fastclose_2 + chk_join_nr "fastclose test" 0 0 0 + chk_fclose_nr 1 1 + chk_rst_nr 1 1 invert +} + all_tests() { subflows_tests @@ -2113,6 +2257,7 @@ all_tests() checksum_tests deny_join_id0_tests fullmesh_tests + fastclose_tests } # [$1: error message] @@ -2139,6 +2284,7 @@ usage() echo " -S checksum_tests" echo " -d deny_join_id0_tests" echo " -m fullmesh_tests" + echo " -z fastclose_tests" echo " -c capture pcap files" echo " -C enable data checksum" echo " -i use ip mptcp" @@ -2170,7 +2316,7 @@ if [ $do_all_tests -eq 1 ]; then exit $ret fi -while getopts 'fesltra64bpkdmchCSi' opt; do +while getopts 'fesltra64bpkdmchzCSi' opt; do case $opt in f) subflows_tests @@ -2217,6 +2363,9 @@ while getopts 'fesltra64bpkdmchCSi' opt; do m) fullmesh_tests ;; + z) + fastclose_tests + ;; c) ;; C)