# Double quotes to prevent globbing and word splitting is recommended in new # code but we accept it, especially because there were too many before having # address all other issues detected by shellcheck. #shellcheck disable=SC2086
# ShellCheck incorrectly believes that most of the code here is unreachable # because it's invoked by variable name, see how the "tests" array is used #shellcheck disable=SC2317,SC2329
declare -A all_tests
declare -a only_tests_ids
declare -a only_tests_names
declare -A failed_tests
MPTCP_LIB_TEST_FORMAT="%03u %s\n"
TEST_NAME=""
nr_blank=6
# These var are used only in some tests, make sure they are not already set
unset FAILING_LINKS
unset test_linkfail
unset addr_nr_ns1
unset addr_nr_ns2
unset cestab_ns1
unset cestab_ns2
unset sflags
unset fastclose
unset fullmesh
unset speed
unset join_syn_rej
unset join_csum_ns1
unset join_csum_ns2
unset join_fail_nr
unset join_rst_nr
unset join_infi_nr
unset join_corrupted_pkts
unset join_syn_tx
unset join_create_err
unset join_bind_err
unset join_connect_err
local netns for netns in "$ns1""$ns2"; do
ip netns exec $netns sysctl -q net.mptcp.pm_type=0 2>/dev/null || true if $checksum; then
ip netns exec $netns sysctl -q net.mptcp.checksum_enabled=1 fi done
local i for i in $(seq 1 4); do
ip link add ns1eth$i netns "$ns1" type veth peer name ns2eth$i netns "$ns2"
ip -net "$ns1" addr add 10.0.$i.1/24 dev ns1eth$i
ip -net "$ns1" addr add dead:beef:$i::1/64 dev ns1eth$i nodad
ip -net "$ns1" link set ns1eth$i up
ip -net "$ns2" addr add 10.0.$i.2/24 dev ns2eth$i
ip -net "$ns2" addr add dead:beef:$i::2/64 dev ns2eth$i nodad
ip -net "$ns2" link set ns2eth$i up
# let $ns2 reach any $ns1 address from any interface
ip -net "$ns2" route add default via 10.0.$i.1 dev ns2eth$i metric 10$i
ip -net "$ns2" route add default via dead:beef:$i::1 dev ns2eth$i metric 10$i done
}
init_shapers()
{
local i for i in $(seq 1 4); do
tc -n $ns1 qdisc add dev ns1eth$i root netem rate 20mbit delay 1ms
tc -n $ns2 qdisc add dev ns2eth$i root netem rate 20mbit delay 1ms done
}
cleanup_partial()
{ rm -f "$capout"
mptcp_lib_ns_exit "${ns1}""${ns2}"
}
init() {
init=1
mptcp_lib_check_mptcp
mptcp_lib_check_kallsyms
mptcp_lib_check_tools ip tc ss "${iptables}""${ip6tables}"
print_info()
{ # It can be empty, no need to print anything then
[ -z "${1}" ] && return
mptcp_lib_print_info " Info: ${*}"
}
print_ok()
{
mptcp_lib_pr_ok "${@}"
}
print_fail()
{
mptcp_lib_pr_fail "${@}"
}
print_skip()
{
mptcp_lib_pr_skip "${@}"
}
# $1: check name; $2: rc
print_results()
{
local check="${1}"
local rc=${2}
print_check "${check}" if [ ${rc} = ${KSFT_PASS} ]; then
print_ok elif [ ${rc} = ${KSFT_SKIP} ]; then
print_skip else
fail_test "see above" fi
}
# [ $1: fail msg ]
mark_as_skipped()
{
local msg="${1:-"Feature not supported"}"
mptcp_lib_fail_if_expected_feature "${msg}"
print_check "${msg}"
print_skip
last_test_skipped=1
}
# $@: condition
continue_if()
{ if ! "${@}"; then
mark_as_skipped
return 1 fi
}
skip_test()
{ if [ "${#only_tests_ids[@]}" -eq 0 ] && [ "${#only_tests_names[@]}" -eq 0 ]; then
return 1 fi
local i for i in "${only_tests_ids[@]}"; do if [ "$((MPTCP_LIB_TEST_COUNTER+1))" -eq "${i}" ]; then
return 1 fi done for i in "${only_tests_names[@]}"; do if [ "${TEST_NAME}" = "${i}" ]; then
return 1 fi done
return 0
}
append_prev_results()
{ if [ ${last_test_failed} -eq 1 ]; then
mptcp_lib_result_fail "${TEST_NAME}" elif [ ${last_test_skipped} -eq 1 ]; then
mptcp_lib_result_skip "${TEST_NAME}" elif [ ${last_test_ignored} -ne 1 ]; then
mptcp_lib_result_pass "${TEST_NAME}" fi
if skip_test; then
MPTCP_LIB_TEST_COUNTER=$((MPTCP_LIB_TEST_COUNTER+1))
last_test_ignored=1
return 1 fi
mptcp_lib_print_title "${TEST_NAME}"
if [ "${init}" != "1" ]; then
init else
cleanup_partial fi
init_partial
return 0
}
# $1: test name ; $2: counter to check
reset_check_counter()
{
reset "${1}" || return 1
local counter="${2}"
if ! nstat -asz "${counter}" | grep -wq "${counter}"; then
mark_as_skipped "counter '${counter}' is not available"
return 1 fi
}
# $1: test name
reset_with_cookies()
{
reset "${1}" || return 1
local netns for netns in "$ns1""$ns2"; do
ip netns exec $netns sysctl -q net.ipv4.tcp_syncookies=2 done
}
# $1: test name
reset_with_add_addr_timeout()
{
local ip="${2:-4}"
local tables
reset "${1}" || return 1
tables="${iptables}" if [ $ip -eq 6 ]; then
tables="${ip6tables}" fi
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
if ! ip netns exec $ns2 $tables -A OUTPUT -p tcp \
-m tcp --tcp-option 30 \
-m bpf --bytecode \ "$CBPF_MPTCP_SUBOPTION_ADD_ADDR" \
-j DROP; then
mark_as_skipped "unable to set the 'add addr' rule"
return 1 fi
}
# $1: test name
reset_with_checksum()
{
local ns1_enable=$1
local ns2_enable=$2
reset "checksum test ${ns1_enable} ${ns2_enable}" || return 1
ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=$ns1_enable
ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=$ns2_enable
validate_checksum=true
}
reset_with_allow_join_id0()
{
local ns1_enable=$2
local ns2_enable=$3
reset "${1}" || return 1
ip netns exec $ns1 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns1_enable
ip netns exec $ns2 sysctl -q net.mptcp.allow_join_initial_addr_port=$ns2_enable
}
# Modify TCP payload without corrupting the TCP packet # # This rule inverts a 8-bit word at byte offset 148 for the 2nd TCP ACK packets # carrying enough data. # Once it is done, the TCP Checksum field is updated so the packet is still # considered as valid at the TCP level. # Because the MPTCP checksum, covering the TCP options and data, has not been # updated, the modification will be detected and an MP_FAIL will be emitted: # what we want to validate here without corrupting "random" MPTCP options. # # To avoid having tc producing this pr_info() message for each TCP ACK packets # not carrying enough data: # # tc action pedit offset 162 out of bounds # # Netfilter is used to mark packets with enough data.
setup_fail_rules()
{
check_invert=1
validate_checksum=true
local i="$1"
local ip="${2:-4}"
local tables
tables="${iptables}" if [ $ip -eq 6 ]; then
tables="${ip6tables}" fi
local ns="${!1}"
local src="${2}"
local target="${3}"
local chain="${4:-INPUT}"
if ! ip netns exec "${ns}" ${iptables} \
-A "${chain}" \
-s "${src}" \
-p tcp \
-j "${target}"; then
mark_as_skipped "unable to set the filter rules"
return 1 fi
}
# $1: err msg
fail_test()
{ if ! mptcp_lib_subtest_is_flaky; then
ret=${KSFT_FAIL} fi
if [ ${#} -gt 0 ]; then
print_fail "${@}" fi
# just in case a test is marked twice as failed if [ ${last_test_failed} -eq 0 ]; then
failed_tests[${MPTCP_LIB_TEST_COUNTER}]="${TEST_NAME}"
dump_stats
last_test_failed=1 fi
}
get_failed_tests_ids()
{ # sorted
local i for i in "${!failed_tests[@]}"; do echo"${i}" done | sort -n
}
check_transfer()
{
local in=$1
local out=$2
local what=$3
local bytes=$4
local i a b
local line if [ -n "$bytes" ]; then
local out_size # when truncating we must check the size explicitly
out_size=$(wc -c $out | awk '{print $1}') if [ $out_size -ne $bytes ]; then
fail_test "$what output file has wrong size ($out_size, $bytes)"
return 1 fi
# note: BusyBox's "cmp" command doesn't support --bytes
tmpfile=$(mktemp)
head --bytes="$bytes""$in" > "$tmpfile"
mv "$tmpfile""$in"
head --bytes="$bytes""$out" > "$tmpfile"
mv "$tmpfile""$out"
tmpfile="" fi
cmp -l "$in""$out" | while read -r i a b; do
local sum=$((0${a} + 0${b})) if [ $check_invert -eq 0 ] || [ $sum -ne $((0xff)) ]; then
fail_test "$what does not match (in, out):"
mptcp_lib_print_file_err "$in"
mptcp_lib_print_file_err "$out"
return 1 else
print_info "$what has inverted byte at ${i}" fi done
return 0
}
do_ping()
{
local listener_ns="$1"
local connector_ns="$2"
local connect_addr="$3"
if ! ip netns exec ${connector_ns} ping -q -c 1 $connect_addr >/dev/null; then
fail_test "$listener_ns -> $connect_addr connectivity" fi
}
link_failure()
{
local ns="$1"
if [ -z "$FAILING_LINKS" ]; then
l=$((RANDOM%4))
FAILING_LINKS=$((l+1)) fi
local l for l in $FAILING_LINKS; do
local veth="ns1eth$l"
ip -net "$ns" link set "$veth" down done
}
pm_nl_set_endpoint()
{
local listener_ns="$1"
local connector_ns="$2"
local connect_addr="$3"
local addr_nr_ns1=${addr_nr_ns1:-0}
local addr_nr_ns2=${addr_nr_ns2:-0}
local sflags=${sflags:-""}
local fullmesh=${fullmesh:-""}
local flags="subflow" if [ -n "${fullmesh}" ]; then
flags="${flags},fullmesh"
addr_nr_ns2=${fullmesh} fi
# let the mptcp subflow be established in background before # do endpoint manipulation if [ $addr_nr_ns1 != "0" ] || [ $addr_nr_ns2 != "0" ]; then
sleep 1 fi
if [ $addr_nr_ns1 -gt 0 ]; then
local counter=2
local add_nr_ns1=${addr_nr_ns1}
local id=10 while [ $add_nr_ns1 -gt 0 ]; do
local addr if mptcp_lib_is_v6 "${connect_addr}"; then
addr="dead:beef:$counter::1" else
addr="10.0.$counter.1" fi
pm_nl_add_endpoint $ns1 $addr flags signal
counter=$((counter + 1))
add_nr_ns1=$((add_nr_ns1 - 1))
id=$((id + 1)) done elif [ $addr_nr_ns1 -lt 0 ]; then
local rm_nr_ns1=$((-addr_nr_ns1)) if [ $rm_nr_ns1 -lt 8 ]; then
local counter=0
local line
pm_nl_show_endpoints ${listener_ns} | while read -r line; do # shellcheck disable=SC2206 # we do want to split per word
local arr=($line)
local nr=0
local i for i in "${arr[@]}"; do if [ $i = "id" ]; then if [ $counter -eq $rm_nr_ns1 ]; then
break fi
id=${arr[$nr+1]}
rm_addr=$(rm_addr_count ${connector_ns})
pm_nl_del_endpoint ${listener_ns} $id
wait_rm_addr ${connector_ns} ${rm_addr}
counter=$((counter + 1)) fi
nr=$((nr + 1)) done done elif [ $rm_nr_ns1 -eq 8 ]; then
pm_nl_flush_endpoint ${listener_ns} elif [ $rm_nr_ns1 -eq 9 ]; then
pm_nl_del_endpoint ${listener_ns} 0 ${connect_addr} fi fi
# if newly added endpoints must be deleted, give the background msk # some time to created them
[ $addr_nr_ns1 -gt 0 ] && [ $addr_nr_ns2 -lt 0 ] && sleep 1
if [ $addr_nr_ns2 -gt 0 ]; then
local add_nr_ns2=${addr_nr_ns2}
local counter=3
local id=20 while [ $add_nr_ns2 -gt 0 ]; do
local addr if mptcp_lib_is_v6 "${connect_addr}"; then
addr="dead:beef:$counter::2" else
addr="10.0.$counter.2" fi
pm_nl_add_endpoint $ns2 $addr flags $flags
counter=$((counter + 1))
add_nr_ns2=$((add_nr_ns2 - 1))
id=$((id + 1)) done elif [ $addr_nr_ns2 -lt 0 ]; then
local rm_nr_ns2=$((-addr_nr_ns2)) if [ $rm_nr_ns2 -lt 8 ]; then
local counter=0
local line
pm_nl_show_endpoints ${connector_ns} | while read -r line; do # shellcheck disable=SC2206 # we do want to split per word
local arr=($line)
local nr=0
local i for i in "${arr[@]}"; do if [ $i = "id" ]; then if [ $counter -eq $rm_nr_ns2 ]; then
break fi
local id rm_addr # rm_addr are serialized, allow the previous one to # complete
id=${arr[$nr+1]}
rm_addr=$(rm_addr_count ${listener_ns})
pm_nl_del_endpoint ${connector_ns} $id
wait_rm_addr ${listener_ns} ${rm_addr}
counter=$((counter + 1)) fi
nr=$((nr + 1)) done done elif [ $rm_nr_ns2 -eq 8 ]; then
pm_nl_flush_endpoint ${connector_ns} elif [ $rm_nr_ns2 -eq 9 ]; then
local addr if mptcp_lib_is_v6 "${connect_addr}"; then
addr="dead:beef:1::2" else
addr="10.0.1.2" fi
pm_nl_del_endpoint ${connector_ns} 0 $addr fi fi
if [ -n "${sflags}" ]; then
sleep 1
local netns for netns in "$ns1""$ns2"; do
local line
pm_nl_show_endpoints $netns | while read -r line; do # shellcheck disable=SC2206 # we do want to split per word
local arr=($line)
local nr=0
local id
local i for i in "${arr[@]}"; do if [ $i = "id" ]; then
id=${arr[$nr+1]} fi
nr=$((nr + 1)) done
pm_nl_change_endpoint $netns $id $sflags done done fi
}
chk_cestab_nr()
{
local ns=$1
local cestab=$2
local count
print_check "currently established: $cestab"
count=$(mptcp_lib_get_counter ${ns} "MPTcpExtMPCurrEstab") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$cestab" ]; then
fail_test "got $count current establish[s] expected $cestab" else
print_ok fi
}
# $1 namespace 1, $2 namespace 2
check_cestab()
{ if [ -n "${cestab_ns1}" ]; then
chk_cestab_nr ${1} ${cestab_ns1} fi if [ -n "${cestab_ns2}" ]; then
chk_cestab_nr ${2} ${cestab_ns2} fi
}
cond_start_capture()
{
local ns="$1"
:> "$capout"
if $capture; then
local capuser capfile if [ -z $SUDO_USER ]; then
capuser="" else
capuser="-Z $SUDO_USER" fi
do_transfer()
{
local listener_ns="$1"
local connector_ns="$2"
local cl_proto="$3"
local srv_proto="$4"
local connect_addr="$5"
local port
local FAILING_LINKS=${FAILING_LINKS:-""}
local fastclose=${fastclose:-""}
local speed=${speed:-"fast"}
port=$(get_port)
:> "$cout"
:> "$sout"
cond_start_capture ${listener_ns}
NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \
nstat -n
NSTAT_HISTORY=/tmp/${connector_ns}.nstat ip netns exec ${connector_ns} \
nstat -n
local extra_args if [ $speed = "fast" ]; then
extra_args="-j" elif [ $speed = "slow" ]; then
extra_args="-r 50" elif [ $speed -gt 0 ]; then
extra_args="-r ${speed}" fi
local extra_cl_args=""
local extra_srv_args=""
local trunc_size="" if [ -n "${fastclose}" ]; then if [ ${test_linkfail} -le 1 ]; then
fail_test "fastclose tests need test_linkfail argument"
return 1 fi
# disconnect
trunc_size=${test_linkfail}
local side=${fastclose}
if [ ${side} = "client" ]; then
extra_cl_args="-f ${test_linkfail}"
extra_srv_args="-f -1" elif [ ${side} = "server" ]; then
extra_srv_args="-f ${test_linkfail}"
extra_cl_args="-f -1" else
fail_test "wrong/unknown fastclose spec ${side}"
return 1 fi fi
if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
fail_test "client exit code $retc, server $rets"
mptcp_lib_pr_err_stats "${listener_ns}""${connector_ns}""${port}" \ "/tmp/${listener_ns}.out""/tmp/${connector_ns}.out"
return 1 fi
if [ "$test_linkfail" -gt 1 ];then
check_transfer $sinfail $cout "file received by client" $trunc_size else
check_transfer $sin $cout "file received by client" $trunc_size fi
retc=$? if [ "$test_linkfail" -eq 0 ];then
check_transfer $cin $sout "file received by server" $trunc_size else
check_transfer $cinsent $sout "file received by server" $trunc_size fi
rets=$?
[ $retc -eq 0 ] && [ $rets -eq 0 ]
}
make_file()
{
local name=$1
local who=$2
local size=$3
mptcp_lib_make_file $name 1024 $size
print_info "Test file (size $size KB) for $who"
}
run_tests()
{
local listener_ns="$1"
local connector_ns="$2"
local connect_addr="$3"
local size
local test_linkfail=${test_linkfail:-0}
# 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 elif [ "$test_linkfail" -ne 0 ] && [ -z "$cinfail" ]; then # the client file must be considerably larger # of the maximum expected cwin value, or the # link utilization will be not predicable
size=$((RANDOM%2))
size=$((size+1))
size=$((size*8192))
size=$((size + ( RANDOM % 8192) ))
cinfail=$(mktemp)
make_file "$cinfail""client" $size fi
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 ] && [ -z "$sinfail" ]; then
size=$((RANDOM%16))
size=$((size+1))
size=$((size*2048))
sinfail=$(mktemp)
make_file "$sinfail""server" $size fi
dump_stats()
{ echo Server ns stats
ip netns exec $ns1 nstat -as | grep Tcp echo Client ns stats
ip netns exec $ns2 nstat -as | grep Tcp
}
chk_csum_nr()
{
local csum_ns1=${1:-0}
local csum_ns2=${2:-0}
local count
local extra_msg=""
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
print_check "checksum server"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtDataCsumErr") if [ -n "$count" ] && [ "$count" != "$csum_ns1" ]; then
extra_msg+=" ns1=$count" fi if [ -z "$count" ]; then
print_skip elif { [ "$count" != $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns1 ] && [ $allow_multi_errors_ns1 -eq 1 ]; }; then
fail_test "got $count data checksum error[s] expected $csum_ns1" else
print_ok fi
print_check "checksum client"
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDataCsumErr") if [ -n "$count" ] && [ "$count" != "$csum_ns2" ]; then
extra_msg+=" ns2=$count" fi if [ -z "$count" ]; then
print_skip elif { [ "$count" != $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 0 ]; } ||
{ [ "$count" -lt $csum_ns2 ] && [ $allow_multi_errors_ns2 -eq 1 ]; }; then
fail_test "got $count data checksum error[s] expected $csum_ns2" else
print_ok fi
print_info "$extra_msg"
}
chk_fail_nr()
{
local fail_tx=$1
local fail_rx=$2
local ns_invert=${3:-""}
local count
local ns_tx=$ns1
local ns_rx=$ns2
local tx="server"
local rx="client"
local extra_msg=""
local allow_tx_lost=0
local allow_rx_lost=0
if [[ $ns_invert = "invert" ]]; then
ns_tx=$ns2
ns_rx=$ns1
tx="client"
rx="server" fi
if [[ "${fail_tx}" = "-"* ]]; then
allow_tx_lost=1
fail_tx=${fail_tx:1} fi if [[ "${fail_rx}" = "-"* ]]; then
allow_rx_lost=1
fail_rx=${fail_rx:1} fi
print_check "fail tx ${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFailTx") if [ -n "$count" ] && [ "$count" != "$fail_tx" ]; then
extra_msg+=" tx=$count" fi if [ -z "$count" ]; then
print_skip elif { [ "$count" != "$fail_tx" ] && [ $allow_tx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_tx" ] && [ $allow_tx_lost -eq 1 ]; }; then
fail_test "got $count MP_FAIL[s] TX expected $fail_tx" else
print_ok fi
print_check "fail rx ${rx}"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFailRx") if [ -n "$count" ] && [ "$count" != "$fail_rx" ]; then
extra_msg+=" rx=$count" fi if [ -z "$count" ]; then
print_skip elif { [ "$count" != "$fail_rx" ] && [ $allow_rx_lost -eq 0 ]; } ||
{ [ "$count" -gt "$fail_rx" ] && [ $allow_rx_lost -eq 1 ]; }; then
fail_test "got $count MP_FAIL[s] RX expected $fail_rx" else
print_ok fi
print_info "$extra_msg"
}
chk_fclose_nr()
{
local fclose_tx=$1
local fclose_rx=$2
local ns_invert=$3
local count
local ns_tx=$ns2
local ns_rx=$ns1
local tx="client"
local rx="server"
if [[ $ns_invert = "invert" ]]; then
ns_tx=$ns1
ns_rx=$ns2
tx="server"
rx="client" fi
print_check "fast close tx ${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFastcloseTx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$fclose_tx" ]; then
fail_test "got $count MP_FASTCLOSE[s] TX expected $fclose_tx" else
print_ok fi
print_check "fast close rx ${rx}"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFastcloseRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$fclose_rx" ]; then
fail_test "got $count MP_FASTCLOSE[s] RX expected $fclose_rx" else
print_ok fi
}
chk_rst_nr()
{
local rst_tx=$1
local rst_rx=$2
local ns_invert=${3:-""}
local count
local ns_tx=$ns1
local ns_rx=$ns2
local tx="server"
local rx="client"
if [[ $ns_invert = "invert" ]]; then
ns_tx=$ns2
ns_rx=$ns1
tx="client"
rx="server" fi
print_check "reset tx ${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPRstTx") if [ -z "$count" ]; then
print_skip # accept more rst than expected except if we don't expect any elif { [ $rst_tx -ne 0 ] && [ $count -lt $rst_tx ]; } ||
{ [ $rst_tx -eq 0 ] && [ $count -ne 0 ]; }; then
fail_test "got $count MP_RST[s] TX expected $rst_tx" else
print_ok fi
print_check "reset rx ${rx}"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPRstRx") if [ -z "$count" ]; then
print_skip # accept more rst than expected except if we don't expect any elif { [ $rst_rx -ne 0 ] && [ $count -lt $rst_rx ]; } ||
{ [ $rst_rx -eq 0 ] && [ $count -ne 0 ]; }; then
fail_test "got $count MP_RST[s] RX expected $rst_rx" else
print_ok fi
}
chk_infi_nr()
{
local infi_tx=$1
local infi_rx=$2
local count
print_check "infi tx client"
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtInfiniteMapTx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$infi_tx" ]; then
fail_test "got $count infinite map[s] TX expected $infi_tx" else
print_ok fi
print_check "infi rx server"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtInfiniteMapRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$infi_rx" ]; then
fail_test "got $count infinite map[s] RX expected $infi_rx" else
print_ok fi
}
chk_join_tx_nr()
{
local syn_tx=${join_syn_tx:-0}
local create=${join_create_err:-0}
local bind=${join_bind_err:-0}
local connect=${join_connect_err:-0}
local rc=${KSFT_PASS}
local count
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynTx") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$syn_tx" ]; then
rc=${KSFT_FAIL}
print_check "syn tx"
fail_test "got $count JOIN[s] syn tx expected $syn_tx" fi
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynTxCreatSkErr") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$create" ]; then
rc=${KSFT_FAIL}
print_check "syn tx create socket error"
fail_test "got $count JOIN[s] syn tx create socket error expected $create" fi
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynTxBindErr") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$bind" ]; then
rc=${KSFT_FAIL}
print_check "syn tx bind error"
fail_test "got $count JOIN[s] syn tx bind error expected $bind" fi
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynTxConnectErr") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$connect" ]; then
rc=${KSFT_FAIL}
print_check "syn tx connect error"
fail_test "got $count JOIN[s] syn tx connect error expected $connect" fi
print_results "join Tx" ${rc}
}
chk_join_nr()
{
local syn_nr=$1
local syn_ack_nr=$2
local ack_nr=$3
local syn_rej=${join_syn_rej:-0}
local csum_ns1=${join_csum_ns1:-0}
local csum_ns2=${join_csum_ns2:-0}
local fail_nr=${join_fail_nr:-0}
local rst_nr=${join_rst_nr:-0}
local infi_nr=${join_infi_nr:-0}
local corrupted_pkts=${join_corrupted_pkts:-0}
local rc=${KSFT_PASS}
local count
local with_cookie
if [ "${corrupted_pkts}" -gt 0 ]; then
print_info "${corrupted_pkts} corrupted pkts" fi
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinSynRx") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$syn_nr" ]; then
rc=${KSFT_FAIL}
print_check "syn rx"
fail_test "got $count JOIN[s] syn rx expected $syn_nr" fi
with_cookie=$(ip netns exec $ns2 sysctl -n net.ipv4.tcp_syncookies)
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckRx") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$syn_ack_nr" ]; then # simult connections exceeding the limit with cookie enabled could go up to # synack validation as the conn limit can be enforced reliably only after # the subflow creation if [ "$with_cookie" != 2 ] || [ "$count" -le "$syn_ack_nr" ] || [ "$count" -gt "$syn_nr" ]; then
rc=${KSFT_FAIL}
print_check "synack rx"
fail_test "got $count JOIN[s] synack rx expected $syn_ack_nr" fi fi
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckHMacFailure") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "0" ]; then
rc=${KSFT_FAIL}
print_check "synack HMAC"
fail_test "got $count JOIN[s] synack HMAC failure expected 0" fi
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckRx") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$ack_nr" ]; then
rc=${KSFT_FAIL}
print_check "ack rx"
fail_test "got $count JOIN[s] ack rx expected $ack_nr" fi
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinAckHMacFailure") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "0" ]; then
rc=${KSFT_FAIL}
print_check "ack HMAC"
fail_test "got $count JOIN[s] ack HMAC failure expected 0" fi
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinRejected") if [ -z "$count" ]; then
rc=${KSFT_SKIP} elif [ "$count" != "$syn_rej" ]; then
rc=${KSFT_FAIL}
print_check "syn rejected"
fail_test "got $count JOIN[s] syn rejected expected $syn_rej" fi
if $validate_checksum; then
chk_csum_nr $csum_ns1 $csum_ns2
chk_fail_nr $fail_nr $fail_nr
chk_rst_nr $rst_nr $rst_nr
chk_infi_nr $infi_nr $infi_nr fi
}
# a negative value for 'stale_max' means no upper bound: # for bidirectional transfer, if one peer sleep for a while # - as these tests do - we can have a quite high number of # stale/recover conversions, proportional to # sleep duration/ MPTCP-level RTX interval.
chk_stale_nr()
{
local ns=$1
local stale_min=$2
local stale_max=$3
local stale_delta=$4
local dump_stats
local stale_nr
local recover_nr
print_check "stale"
stale_nr=$(mptcp_lib_get_counter ${ns} "MPTcpExtSubflowStale")
recover_nr=$(mptcp_lib_get_counter ${ns} "MPTcpExtSubflowRecover") if [ -z "$stale_nr" ] || [ -z "$recover_nr" ]; then
print_skip elif [ $stale_nr -lt $stale_min ] ||
{ [ $stale_max -gt 0 ] && [ $stale_nr -gt $stale_max ]; } ||
[ $((stale_nr - recover_nr)) -ne $stale_delta ]; then
fail_test "got $stale_nr stale[s] $recover_nr recover[s], " \ " expected stale in range [$stale_min..$stale_max]," \ " stale-recover delta $stale_delta"
dump_stats=1 else
print_ok fi
if [ "${dump_stats}" = 1 ]; then echo $ns stats
ip netns exec $ns ip -s link show
ip netns exec $ns nstat -as | grep MPTcp fi
}
chk_add_nr()
{
local add_nr=$1
local echo_nr=$2
local port_nr=${3:-0}
local ns_invert=${4:-""}
local syn_nr=$port_nr
local syn_ack_nr=$port_nr
local ack_nr=$port_nr
local mis_syn_nr=0
local mis_ack_nr=0
local ns_tx=$ns1
local ns_rx=$ns2
local tx=""
local rx=""
local count
local timeout
if [[ $ns_invert = "invert" ]]; then
ns_tx=$ns2
ns_rx=$ns1
tx=" client"
rx=" server" fi
print_check "add addr rx${rx}"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtAddAddr") if [ -z "$count" ]; then
print_skip # if the test configured a short timeout tolerate greater then expected # add addrs options, due to retransmissions elif [ "$count" != "$add_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_nr" ]; }; then
fail_test "got $count ADD_ADDR[s] expected $add_nr" else
print_ok fi
print_check "add addr echo rx${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtEchoAdd") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$echo_nr" ]; then
fail_test "got $count ADD_ADDR echo[s] expected $echo_nr" else
print_ok fi
if [ $port_nr -gt 0 ]; then
print_check "add addr rx with port${rx}"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtPortAdd") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$port_nr" ]; then
fail_test "got $count ADD_ADDR[s] with a port-number expected $port_nr" else
print_ok fi
print_check "syn rx port${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortSynRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$syn_nr" ]; then
fail_test "got $count JOIN[s] syn with a different \
port-number expected $syn_nr" else
print_ok fi
print_check "synack rx port${rx}"
count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPJoinPortSynAckRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$syn_ack_nr" ]; then
fail_test "got $count JOIN[s] synack with a different \
port-number expected $syn_ack_nr" else
print_ok fi
print_check "ack rx port${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPJoinPortAckRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$ack_nr" ]; then
fail_test "got $count JOIN[s] ack with a different \
port-number expected $ack_nr" else
print_ok fi
print_check "syn rx port mismatch${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortSynRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$mis_syn_nr" ]; then
fail_test "got $count JOIN[s] syn with a mismatched \
port-number expected $mis_syn_nr" else
print_ok fi
print_check "ack rx port mismatch${tx}"
count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMismatchPortAckRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$mis_ack_nr" ]; then
fail_test "got $count JOIN[s] ack with a mismatched \
port-number expected $mis_ack_nr" else
print_ok fi fi
}
chk_add_tx_nr()
{
local add_tx_nr=$1
local echo_tx_nr=$2
local timeout
local count
print_check "add addr tx"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtAddAddrTx") if [ -z "$count" ]; then
print_skip # if the test configured a short timeout tolerate greater then expected # add addrs options, due to retransmissions elif [ "$count" != "$add_tx_nr" ] && { [ "$timeout" -gt 1 ] || [ "$count" -lt "$add_tx_nr" ]; }; then
fail_test "got $count ADD_ADDR[s] TX, expected $add_tx_nr" else
print_ok fi
print_check "add addr echo tx"
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtEchoAddTx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$echo_tx_nr" ]; then
fail_test "got $count ADD_ADDR echo[s] TX, expected $echo_tx_nr" else
print_ok fi
}
chk_rm_nr()
{
local rm_addr_nr=$1
local rm_subflow_nr=$2
local invert
local simult
local count
local addr_ns=$ns1
local subflow_ns=$ns2
local addr="server"
local subflow="client"
local extra_msg=""
# in case of simult flush, the subflow removal count on each side is # unreliable
count=$((count + cnt)) if [ "$count" != "$rm_subflow_nr" ]; then
suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
extra_msg="simult" fi if [ $count -ge "$rm_subflow_nr" ] && \
[ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
print_ok "$suffix" else
fail_test "got $count RM_SUBFLOW[s] expected in range [$rm_subflow_nr:$((rm_subflow_nr*2))]" fi elif [ "$count" != "$rm_subflow_nr" ]; then
fail_test "got $count RM_SUBFLOW[s] expected $rm_subflow_nr" else
print_ok fi
print_info "$extra_msg"
}
chk_rm_tx_nr()
{
local rm_addr_tx_nr=$1
print_check "rm addr tx client"
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtRmAddrTx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$rm_addr_tx_nr" ]; then
fail_test "got $count RM_ADDR[s] expected $rm_addr_tx_nr" else
print_ok fi
}
chk_prio_nr()
{
local mp_prio_nr_tx=$1
local mp_prio_nr_rx=$2
local mpj_syn=$3
local mpj_syn_ack=$4
local count
print_check "mp_prio tx server"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPPrioTx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$mp_prio_nr_tx" ]; then
fail_test "got $count MP_PRIO[s] TX expected $mp_prio_nr_tx" else
print_ok fi
print_check "mp_prio rx client"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPPrioRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$mp_prio_nr_rx" ]; then
fail_test "got $count MP_PRIO[s] RX expected $mp_prio_nr_rx" else
print_ok fi
print_check "syn backup"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPJoinSynBackupRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$mpj_syn" ]; then
fail_test "got $count JOIN[s] syn with Backup expected $mpj_syn" else
print_ok fi
print_check "synack backup"
count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtMPJoinSynAckBackupRx") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$mpj_syn_ack" ]; then
fail_test "got $count JOIN[s] synack with Backup expected $mpj_syn_ack" else
print_ok fi
}
chk_subflow_nr()
{
local msg="$1"
local subflow_nr=$2
local cnt1
local cnt2
local dump_stats
cnt1=$(ss -N $ns1 -inmHM | mptcp_lib_get_info_value "$info1""$info1")
cnt2=$(ss -N $ns2 -inmHM | mptcp_lib_get_info_value "$info2""$info2") # 'ss' only display active connections and counters that are not 0.
[ -z "$cnt1" ] && cnt1=0
[ -z "$cnt2" ] && cnt2=0
if [ "$cnt1" != "$exp1" ] || [ "$cnt2" != "$exp2" ]; then
fail_test "got $cnt1:$cnt2 $info1:$info2 expected $exp1:$exp2"
dump_stats=1 else
print_ok fi
if [ "$dump_stats" = 1 ]; then
ss -N $ns1 -inmHM
ss -N $ns2 -inmHM fi
}
# $1: subflows in ns1 ; $2: subflows in ns2 # number of all subflows, including the initial subflow.
chk_subflows_total()
{
local cnt1
local cnt2
local info="subflows_total"
local dump_stats
# if subflows_total counter is supported, use it: if [ -n "$(ss -N $ns1 -inmHM | mptcp_lib_get_info_value $info $info)" ]; then
chk_mptcp_info $info $1 $info $2
return fi
print_check "$info $1:$2"
# if not, count the TCP connections that are in fact MPTCP subflows
cnt1=$(ss -N $ns1 -ti state established state syn-sent state syn-recv |
grep -c tcp-ulp-mptcp)
cnt2=$(ss -N $ns2 -ti state established state syn-sent state syn-recv |
grep -c tcp-ulp-mptcp)
if [ "$1" != "$cnt1" ] || [ "$2" != "$cnt2" ]; then
fail_test "got subflows $cnt1:$cnt2 expected $1:$2"
dump_stats=1 else
print_ok fi
if [ "$dump_stats" = 1 ]; then
ss -N $ns1 -ti
ss -N $ns2 -ti fi
}
chk_link_usage()
{
local ns=$1
local link=$2
local out=$3
local expected_rate=$4
local tx_link tx_total
tx_link=$(ip netns exec $ns cat /sys/class/net/$link/statistics/tx_bytes)
tx_total=$(stat --format=%s $out)
local tx_rate=$((tx_link * 100 / tx_total))
local tolerance=5
# multiple subflows limited by server if reset "multiple subflows, limited by server"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
join_syn_rej=1 \
chk_join_nr 2 2 1 fi
# single subflow, dev if reset "single subflow, dev"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow dev ns2eth3
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1 fi
}
subflows_error_tests()
{ # If a single subflow is configured, and matches the MPC src # address, no additional subflow should be created if reset "no MPC reuse with single endpoint"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.12.2 flags subflow
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
join_bind_err=1 \
chk_join_nr 0 0 0 fi
# multiple subflows, with subflow timeout on MPJ if reset_with_tcp_filter "multi subflows, with subflow timeout" ns1 10.0.3.2 DROP &&
continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
join_syn_tx=2 \
chk_join_nr 1 1 1 fi
# multiple subflows, check that the endpoint corresponding to # closed subflow (due to reset) is not reused if additional # subflows are added later if reset_with_tcp_filter "multi subflows, fair usage on close" ns1 10.0.3.2 REJECT &&
continue_if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
speed=slow \
run_tests $ns1 $ns2 10.0.1.1 &
# mpj subflow will be in TW after the reset
wait_attempt_fail $ns2
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
wait
# additional subflow could be created only if the PM select # the later endpoint, skipping the already used one
join_syn_tx=2 \
chk_join_nr 1 1 1 fi
}
signal_address_tests()
{ # add_address, unused if reset "unused signal address"; then
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0
chk_add_tx_nr 1 1
chk_add_nr 1 1 fi
# accept and use add_addr if reset "signal address"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 fi
# accept and use add_addr with an additional subflow # note: signal address in server ns and local addresses in client ns must # belong to different subnets or one of the listed local address could be # used for 'add_addr' subflow if reset "subflow and signal"; then
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 1 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1 fi
# uncommon: subflow and signal flags on the same endpoint # or because the user wrongly picked both, but still expects the client # to create additional subflows if reset "subflow and signal together"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags signal,subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 0 invert # only initiated by ns2
chk_add_nr 0 0 0 # none initiated by ns1
chk_rst_nr 0 0 invert # no RST sent by the client
chk_rst_nr 0 0 # no RST sent by the server fi
# accept and use add_addr with additional subflows if reset "multiple subflows and signal"; then
pm_nl_set_limits $ns1 0 3
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 1 1 fi
# signal addresses if reset "signal addresses"; then
pm_nl_set_limits $ns1 3 3
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
pm_nl_set_limits $ns2 3 3
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 3 3 fi
# signal invalid addresses if reset "signal invalid addresses"; then
pm_nl_set_limits $ns1 3 3
pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
pm_nl_set_limits $ns2 3 3
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
join_syn_tx=3 \
chk_join_nr 1 1 1
chk_add_nr 3 3 fi
# signal addresses race test if reset "signal addresses race test"; then
pm_nl_set_limits $ns1 4 4
pm_nl_set_limits $ns2 4 4
pm_nl_add_endpoint $ns1 10.0.1.1 flags signal
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
pm_nl_add_endpoint $ns2 10.0.1.2 flags signal
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
pm_nl_add_endpoint $ns2 10.0.3.2 flags signal
pm_nl_add_endpoint $ns2 10.0.4.2 flags signal
# the peer could possibly miss some addr notification, allow retransmission
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
# It is not directly linked to the commit introducing this # symbol but for the parent one which is linked anyway. if ! mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
chk_join_nr 3 3 2
chk_add_nr 4 4 else
chk_join_nr 3 3 3 # the server will not signal the address terminating # the MPC subflow
chk_add_nr 3 3 fi fi
}
link_failure_tests()
{ # accept and use add_addr with additional subflows and link loss if reset "multiple flows, signal, link failure"; then # without any b/w limit each veth could spool the packets and get # them acked at xmit time, so that the corresponding subflow will # have almost always no outstanding pkts, the scheduler will pick # always the first subflow and we will have hard time testing # active backup and link switch-over. # Let's set some arbitrary (low) virtual link limits.
init_shapers
pm_nl_set_limits $ns1 0 3
pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
pm_nl_add_endpoint $ns2 10.0.4.2 dev ns2eth4 flags subflow
test_linkfail=1 \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 1 1
chk_stale_nr $ns2 1 5 1 fi
# accept and use add_addr with additional subflows and link loss # for bidirectional transfer if reset "multi flows, signal, bidi, link fail"; then
init_shapers
pm_nl_set_limits $ns1 0 3
pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
pm_nl_add_endpoint $ns2 10.0.4.2 dev ns2eth4 flags subflow
test_linkfail=2 \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 1 1
chk_stale_nr $ns2 1 -1 1 fi
# 2 subflows plus 1 backup subflow with a lossy link, backup # will never be used if reset "backup subflow unused, link failure"; then
init_shapers
pm_nl_set_limits $ns1 0 2
pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
pm_nl_set_limits $ns2 1 2
pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
FAILING_LINKS="1" test_linkfail=1 \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1
chk_link_usage $ns2 ns2eth3 $cinsent 0 fi
# 2 lossy links after half transfer, backup will get half of # the traffic if reset "backup flow used, multi links fail"; then
init_shapers
pm_nl_set_limits $ns1 0 2
pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
pm_nl_set_limits $ns2 1 2
pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
FAILING_LINKS="1 2" test_linkfail=1 \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1
chk_stale_nr $ns2 2 4 2
chk_link_usage $ns2 ns2eth3 $cinsent 50 fi
# use a backup subflow with the first subflow on a lossy link # for bidirectional transfer if reset "backup flow used, bidi, link failure"; then
init_shapers
pm_nl_set_limits $ns1 0 2
pm_nl_add_endpoint $ns1 10.0.2.1 dev ns1eth2 flags signal
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow,backup
FAILING_LINKS="1 2" test_linkfail=2 \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1
chk_stale_nr $ns2 1 -1 2
chk_link_usage $ns2 ns2eth3 $cinsent 50 fi
}
# signal address v6-map-v4 if reset "signal address v6-map-v4"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 "::ffff:10.0.2.1" flags signal
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 fi
# no subflow IPv6 to v4 address if reset "no JOIN with diff families v4-v6"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 dead:beef:2::2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0 fi
# no subflow IPv6 to v4 address even if v6 has a valid v4 at the end if reset "no JOIN with diff families v4-v6-2"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 dead:beef:2::10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0 fi
# no subflow IPv4 to v6 address, no need to slow down too then if reset "no JOIN with diff families v6-v4"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 dead:beef:1::1
chk_join_nr 0 0 0 fi
}
mixed_tests()
{ if reset "IPv4 sockets do not use IPv6 addresses" &&
continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0 fi
# Need an IPv6 mptcp socket to allow subflows of both families if reset "simult IPv4 and IPv6 subflows" &&
continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.1.1 flags signal
speed=slow \
run_tests $ns1 $ns2 dead:beef:2::1
chk_join_nr 1 1 1 fi
# cross families subflows will not be created even in fullmesh mode if reset "simult IPv4 and IPv6 subflows, fullmesh 1x1" &&
continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 4
pm_nl_set_limits $ns2 1 4
pm_nl_add_endpoint $ns2 dead:beef:2::2 flags subflow,fullmesh
pm_nl_add_endpoint $ns1 10.0.1.1 flags signal
speed=slow \
run_tests $ns1 $ns2 dead:beef:2::1
chk_join_nr 1 1 1 fi
# fullmesh still tries to create all the possibly subflows with # matching family if reset "simult IPv4 and IPv6 subflows, fullmesh 2x2" &&
continue_if mptcp_lib_kversion_ge 6.3; then
pm_nl_set_limits $ns1 0 4
pm_nl_set_limits $ns2 2 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal
fullmesh=1 speed=slow \
run_tests $ns1 $ns2 dead:beef:1::1
chk_join_nr 4 4 4 fi
}
if reset "mpc switch to backup" &&
continue_if mptcp_lib_kallsyms_doesnt_have "T mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
sflags=backup speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0
chk_prio_nr 0 1 0 0 fi
if reset "mpc switch to backup both sides" &&
continue_if mptcp_lib_kallsyms_doesnt_have "T mptcp_subflow_send_ack$"; then
pm_nl_add_endpoint $ns1 10.0.1.1 flags subflow
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow
sflags=backup speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0
chk_prio_nr 1 1 0 0 fi
}
verify_listener_events()
{
local e_type=$2
local e_saddr=$4
local e_sport=$5
local name
if [ $e_type = $MPTCP_LIB_EVENT_LISTENER_CREATED ]; then
name="LISTENER_CREATED" elif [ $e_type = $MPTCP_LIB_EVENT_LISTENER_CLOSED ]; then
name="LISTENER_CLOSED " else
name="$e_type" fi
print_check "$name $e_saddr:$e_sport"
if ! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then
print_skip "event not supported"
return fi
if mptcp_lib_verify_listener_events "${@}"; then
print_ok
return 0 fi
fail_test
}
chk_mpc_endp_attempt()
{
local retl=$1
local attempts=$2
print_check "Connect"
if [ ${retl} = 124 ]; then
fail_test "timeout on connect" elif [ ${retl} = 0 ]; then
fail_test "unexpected successful connect" else
print_ok
print_check "Attempts"
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPCapableEndpAttempt") if [ -z "$count" ]; then
print_skip elif [ "$count" != "$attempts" ]; then
fail_test "got ${count} MPC attempt[s] on port-based endpoint, expected ${attempts}" else
print_ok fi fi
}
add_addr_ports_tests()
{ # signal address with port if reset "signal address with port"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 1 fi
# subflow and signal with port if reset "subflow and signal with port"; then
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 1 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1 1 fi
# single address with port, remove # pm listener events if reset_with_events "remove single address with port"; then
pm_nl_set_limits $ns1 0 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_set_limits $ns2 1 1
addr_nr_ns1=-1 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 1
chk_rm_nr 1 1 invert
# subflow and signal with port, remove if reset "remove subflow and signal with port"; then
pm_nl_set_limits $ns1 0 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_set_limits $ns2 1 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
addr_nr_ns1=-1 addr_nr_ns2=-1 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1 1
chk_rm_nr 1 1 fi
# subflows and signal with port, flush if reset "flush subflows and signal with port"; then
pm_nl_set_limits $ns1 0 3
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
addr_nr_ns1=-8 addr_nr_ns2=-2 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 1 1
chk_rm_nr 1 3 invert simult fi
# multiple addresses with port if reset "multiple addresses with port"; then
pm_nl_set_limits $ns1 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal port 10100
pm_nl_set_limits $ns2 2 2
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 2 2 2 fi
# multiple addresses with ports if reset "multiple addresses with ports"; then
pm_nl_set_limits $ns1 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal port 10100
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal port 10101
pm_nl_set_limits $ns2 2 2
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 2 2 2 fi
if reset "port-based signal endpoint must not accept mpc"; then
local port retl count
port=$(get_port)
cond_start_capture ${ns1}
pm_nl_add_endpoint ${ns1} 10.0.2.1 flags signal port ${port}
mptcp_lib_wait_local_port_listen ${ns1} ${port}
syncookies_tests()
{ # single subflow, syncookies if reset_with_cookies "single subflow with syn cookies"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1 fi
# multiple subflows with syn cookies if reset_with_cookies "multiple subflows with syn cookies"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2 fi
# multiple subflows limited by server if reset_with_cookies "subflows limited by server w cookies"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
join_syn_rej=1 \
chk_join_nr 2 1 1 fi
# test signal address with cookies if reset_with_cookies "signal address with syn cookies"; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 fi
# test cookie with subflow and signal if reset_with_cookies "subflow and signal w cookies"; then
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 1 2
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_add_nr 1 1 fi
# accept and use add_addr with additional subflows if reset_with_cookies "subflows and signal w. cookies"; then
pm_nl_set_limits $ns1 0 3
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 1 1 fi
}
checksum_tests()
{
local checksum_enable for checksum_enable in "0 0""1 1""0 1""1 0"; do # checksum test 0 0, 1 1, 0 1, 1 0 if reset_with_checksum ${checksum_enable}; then
pm_nl_set_limits $ns1 0 1
pm_nl_set_limits $ns2 0 1
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 0 0 0 fi done
}
# signal address allow join id0 ns1 # ADD_ADDRs are not affected by allow_join_id0 value. if reset_with_allow_join_id0 "signal address allow join id0 ns1" 1 0; then
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 fi
# signal address allow join id0 ns2 # ADD_ADDRs are not affected by allow_join_id0 value. if reset_with_allow_join_id0 "signal address allow join id0 ns2" 0 1; then
pm_nl_set_limits $ns1 1 1
pm_nl_set_limits $ns2 1 1
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1
chk_add_nr 1 1 fi
# subflow and address allow join id0 ns1 if reset_with_allow_join_id0 "subflow and address allow join id0 1" 1 0; then
pm_nl_set_limits $ns1 2 2
pm_nl_set_limits $ns2 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2 fi
# subflow and address allow join id0 ns2 if reset_with_allow_join_id0 "subflow and address allow join id0 2" 0 1; then
pm_nl_set_limits $ns1 2 2
pm_nl_set_limits $ns2 2 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 1 1 1 fi
# default limits, server deny join id 0 + signal if reset_with_allow_join_id0 "default limits, server deny join id 0" 0 1; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 0 2
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2 fi
}
fullmesh_tests()
{ # fullmesh 1 # 2 fullmesh addrs in ns2, added before the connection, # 1 non-fullmesh addr in ns1, added during the connection. if reset "fullmesh test 2x1"; then
pm_nl_set_limits $ns1 0 4
pm_nl_set_limits $ns2 1 4
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,fullmesh
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,fullmesh
addr_nr_ns1=1 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 4 4 4
chk_add_nr 1 1 fi
# fullmesh 2 # 1 non-fullmesh addr in ns1, added before the connection, # 1 fullmesh addr in ns2, added during the connection. if reset "fullmesh test 1x1"; then
pm_nl_set_limits $ns1 1 3
pm_nl_set_limits $ns2 1 3
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
pm_nl_add_endpoint $ns2 10.0.1.2 flags subflow,fullmesh fi
fullmesh=1 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
chk_add_nr 1 1 fi
# fullmesh 3 # 1 non-fullmesh addr in ns1, added before the connection, # 2 fullmesh addrs in ns2, added during the connection. if reset "fullmesh test 1x2"; then
pm_nl_set_limits $ns1 2 5
pm_nl_set_limits $ns2 1 5
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
fullmesh=2 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 5 5 5
chk_add_nr 1 1 fi
# fullmesh 4 # 1 non-fullmesh addr in ns1, added before the connection, # 2 fullmesh addrs in ns2, added during the connection, # limit max_subflows to 4. if reset "fullmesh test 1x2, limited"; then
pm_nl_set_limits $ns1 2 4
pm_nl_set_limits $ns2 1 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
fullmesh=2 speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 4 4 4
chk_add_nr 1 1 fi
# set fullmesh flag if reset "set fullmesh flag test" &&
continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow
pm_nl_set_limits $ns2 4 4
addr_nr_ns2=1 sflags=fullmesh speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_rm_nr 0 1 fi
# set nofullmesh flag if reset "set nofullmesh flag test" &&
continue_if mptcp_lib_kversion_ge 5.18; then
pm_nl_set_limits $ns1 4 4
pm_nl_add_endpoint $ns1 10.0.2.1 flags subflow,fullmesh
pm_nl_set_limits $ns2 4 4
fullmesh=1 sflags=nofullmesh speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 2 2 2
chk_rm_nr 0 1 fi
pm_nl_add_endpoint $ns2 10.0.2.2 id 33 2>/dev/null
pm_nl_check_endpoint "ID change is prevented" \
$ns2 10.0.2.2 id 1 flags implicit
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
pm_nl_check_endpoint "modif is allowed" \
$ns2 10.0.2.2 id 1 flags signal
mptcp_lib_kill_group_wait $tests_pid fi
if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT &&
continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
start_events
pm_nl_set_limits $ns1 0 3
pm_nl_set_limits $ns2 0 3
pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
{ test_linkfail=128 speed=5 \
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
local tests_pid=$!
wait_mpj $ns2
pm_nl_check_endpoint "creation" \
$ns2 10.0.2.2 id 2 flags subflow dev ns2eth2
chk_subflow_nr "before delete id 2" 2
chk_mptcp_info subflows 1 subflows 1
local i for i in $(seq 3); do
pm_nl_del_endpoint $ns2 1 10.0.1.2
sleep 0.5
chk_subflow_nr "after delete id 0 ($i)" 2
chk_mptcp_info subflows 2 subflows 2 # only decr for additional sf
pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
wait_mpj $ns2
chk_subflow_nr "after re-add id 0 ($i)" 3
chk_mptcp_info subflows 3 subflows 3 done
chk_evt_nr ns2 MPTCP_LIB_EVENT_CREATED 1
chk_evt_nr ns2 MPTCP_LIB_EVENT_ESTABLISHED 1
chk_evt_nr ns2 MPTCP_LIB_EVENT_ANNOUNCED 0
chk_evt_nr ns2 MPTCP_LIB_EVENT_REMOVED 0
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_ESTABLISHED 6
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_CLOSED 5 # one has been closed before estab
join_syn_tx=7 \
chk_join_nr 6 6 6
chk_rm_nr 4 4 fi
# remove and re-add if reset_with_events "delete re-add signal" &&
continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=0
pm_nl_set_limits $ns1 0 3
pm_nl_set_limits $ns2 3 3
pm_nl_add_endpoint $ns1 10.0.2.1 id 1 flags signal # broadcast IP: no packet for this address will be received on ns1
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
pm_nl_add_endpoint $ns1 10.0.1.1 id 42 flags signal
{ test_linkfail=128 speed=5 \
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
local tests_pid=$!
wait_mpj $ns2
pm_nl_check_endpoint "creation" \
$ns1 10.0.2.1 id 1 flags signal
chk_subflow_nr "before delete" 2
chk_mptcp_info subflows 1 subflows 1
# flush and re-add if reset_with_tcp_filter "flush re-add" ns2 10.0.3.2 REJECT OUTPUT &&
continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then
pm_nl_set_limits $ns1 0 2
pm_nl_set_limits $ns2 1 2 # broadcast IP: no packet for this address will be received on ns1
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow
{ test_linkfail=128 speed=20 \
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
local tests_pid=$!
# [$1: error message]
usage()
{ if [ -n "${1}" ]; then echo"${1}"
ret=${KSFT_FAIL} fi
echo"mptcp_join usage:"
local key for key in "${!all_tests[@]}"; do echo" -${key} ${all_tests[${key}]}" done
echo" -c capture pcap files" echo" -C enable data checksum" echo" -i use ip mptcp" echo" -h help"
echo"[test ids|names]"
exit ${ret}
}
# Use a "simple" array to force an specific order we cannot have with an associative one
all_tests_sorted=(
f@subflows_tests
e@subflows_error_tests
s@signal_address_tests
l@link_failure_tests
t@add_addr_timeout_tests
r@remove_tests
a@add_tests
6@ipv6_tests
4@v4mapped_tests
M@mixed_tests
b@backup_tests
p@add_addr_ports_tests
k@syncookies_tests
S@checksum_tests
d@deny_join_id0_tests
m@fullmesh_tests
z@fastclose_tests
F@fail_tests
u@userspace_tests
I@endpoint_tests
)
all_tests_args=""
all_tests_names=() for subtests in "${all_tests_sorted[@]}"; do
key="${subtests%@*}"
value="${subtests#*@}"
tests=() while getopts "${all_tests_args}cCih" opt; do
case $opt in
["${all_tests_args}"])
tests+=("${all_tests[${opt}]}")
;;
c)
capture=true
;;
C)
checksum=true
;;
i)
mptcp_lib_set_ip_mptcp
;;
h)
usage
;;
*)
usage "Unknown option: -${opt}"
;;
esac done
shift $((OPTIND - 1))
for arg in "${@}"; do if [[ "${arg}" =~ ^[0-9]+$ ]]; then
only_tests_ids+=("${arg}") else
only_tests_names+=("${arg}") fi done
if [ ${#tests[@]} -eq 0 ]; then
tests=("${all_tests_names[@]}") fi
mptcp_lib_subtests_last_ts_reset for subtests in "${tests[@]}"; do "${subtests}" done
append_prev_results
if [ ${ret} -ne 0 ]; then echo echo"${#failed_tests[@]} failure(s) has(ve) been detected:" for i in $(get_failed_tests_ids); do echo -e "\t- ${i}: ${failed_tests[${i}]}" done echo fi
mptcp_lib_result_print_all_tap
exit $ret
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.52 Sekunden
(vorverarbeitet am 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.