Added the test cases for MP_FAIL, the multiple subflows test for the MP_RST
case and the single subflow one for the infinite mapping case.
Added a new function reset_with_fail(), in it use 'iptables' and 'tc
action pedit' commands to trigger the checksum failures.
Added a new global variable pedit_action to trace whether the tc pedit
action happened during the test. Check and set it in the new function
pedit_action_happened(). Show it in the test description and pass it to
chk_join_nr() to check the numbers of the checksum failures, MP_FAIL
sending and receiving, the infinite mapping sending and receiving.
Added a new global variable validate_checksum to enable checksums for
the MP_FAIL tests without passing the '-C' argument.
Also added the tests needed kernel configures in the config file.
Suggested-by: Davide Caratti <dcaratti@redhat.com>
Co-developed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
tools/testing/selftests/net/mptcp/config | 8 +
.../testing/selftests/net/mptcp/mptcp_join.sh | 154 ++++++++++++++++--
2 files changed, 148 insertions(+), 14 deletions(-)
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index d36b7da5082a..38021a0dd527 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -12,6 +12,9 @@ CONFIG_NF_TABLES=m
CONFIG_NFT_COMPAT=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NF_TABLES_INET=y
CONFIG_NFT_TPROXY=m
CONFIG_NFT_SOCKET=m
@@ -19,3 +22,8 @@ CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_NF_TARGET_REJECT=m
CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_SCH_INGRESS=m
diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
index 90a6adc36490..a62f737805ab 100755
--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
+++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
@@ -17,6 +17,8 @@ capture=0
checksum=0
ip_mptcp=0
check_invert=0
+validate_checksum=0
+pedit_action=0
do_all_tests=1
TEST_COUNT=0
@@ -62,6 +64,7 @@ init()
done
check_invert=0
+ validate_checksum=$checksum
# ns1 ns2
# ns1eth1 ns2eth1
@@ -167,6 +170,63 @@ reset_with_allow_join_id0()
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.
+reset_with_fail()
+{
+ reset
+
+ ip netns exec $ns1 sysctl -q net.mptcp.checksum_enabled=1
+ ip netns exec $ns2 sysctl -q net.mptcp.checksum_enabled=1
+
+ check_invert=1
+ validate_checksum=1
+ pedit_action=0
+ local i="$1"
+ local ip="${2:-4}"
+ local tables
+
+ tables="iptables"
+ if [ $ip -eq 6 ]; then
+ tables="ip6tables"
+ fi
+
+ ip netns exec $ns2 $tables \
+ -t mangle \
+ -A OUTPUT \
+ -o ns2eth$i \
+ -p tcp \
+ -m length --length 150:9999 \
+ -m statistic --mode nth --packet 1 --every 99999 \
+ -j MARK --set-mark 42
+ if [ $? -ne 0 ];then
+ echo "SKIP: Couldn not add the $tables rule"
+ exit $ksft_skip
+ fi
+
+ tc -n $ns2 qdisc add dev ns2eth$i clsact
+ tc -n $ns2 filter add dev ns2eth$i egress \
+ protocol ip prio 1000 \
+ handle 42 fw \
+ action pedit munge offset 148 u8 invert \
+ pipe csum tcp \
+ index 100
+}
+
ip -Version > /dev/null 2>&1
if [ $? -ne 0 ];then
echo "SKIP: Could not run test without ip tool"
@@ -185,6 +245,12 @@ if [ $? -ne 0 ];then
exit $ksft_skip
fi
+jq -V > /dev/null 2>&1
+if [ $? -ne 0 ];then
+ echo "SKIP: Could not run all tests without jq tool"
+ exit $ksft_skip
+fi
+
print_file_err()
{
ls -l "$1" 1>&2
@@ -245,6 +311,19 @@ link_failure()
done
}
+pedit_action_happened()
+{
+ i="$1"
+
+ local action=$(tc -n $ns2 -j -s action show action pedit index 100)
+ local packets=$(echo $action | jq '.[1].actions[0].stats.packets')
+
+ if [ $packets != "null" ] && [ $packets -gt 0 ]; then
+ pedit_action=1
+ fi
+ tc -n $ns2 qdisc del dev ns2eth$i clsact
+}
+
# $1: IP address
is_v6()
{
@@ -446,7 +525,7 @@ 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} \
@@ -466,13 +545,19 @@ do_transfer()
ip netns exec ${connector_ns} \
$mptcp_connect -t ${timeout_poll} -p $port -s ${cl_proto} \
$connect_addr < "$cin" > "$cout" &
- else
+ 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" &
+ else
+ 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" &
fi
cpid=$!
@@ -632,7 +717,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"
@@ -681,7 +766,12 @@ run_tests()
# create the input file for the failure test when
# the first failure test run
- if [ "$test_linkfail" -ne 0 -a -z "$cinfail" ]; then
+ if [ "$test_linkfail" -eq 3 ]; then
+ if [ -z "$cinfail" ]; then
+ cinfail=$(mktemp)
+ fi
+ make_file "$cinfail" "client" 512
+ 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
@@ -694,7 +784,12 @@ run_tests()
make_file "$cinfail" "client" $size
fi
- if [ "$test_linkfail" -eq 2 -a -z "$sinfail" ]; then
+ if [ "$test_linkfail" -eq 3 ]; then
+ if [ -z "$sinfail" ]; then
+ sinfail=$(mktemp)
+ fi
+ make_file "$sinfail" "server" 512
+ elif [ "$test_linkfail" -eq 2 -a -z "$sinfail" ]; then
size=$((RANDOM%16))
size=$((size+1))
size=$((size*2048))
@@ -719,6 +814,8 @@ dump_stats()
chk_csum_nr()
{
local msg=${1:-""}
+ local csum_ns1=${2:-0}
+ local csum_ns2=${3:-0}
local count
local dump_stats
@@ -730,8 +827,8 @@ chk_csum_nr()
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 ]; then
+ echo "[fail] got $count data checksum error[s] expected $csum_ns1"
ret=1
dump_stats=1
else
@@ -740,8 +837,8 @@ 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 ]; then
+ echo "[fail] got $count data checksum error[s] expected $csum_ns2"
ret=1
dump_stats=1
else
@@ -820,6 +917,8 @@ chk_join_nr()
local syn_nr=$2
local syn_ack_nr=$3
local ack_nr=$4
+ local fail_nr=${5:-0}
+ local infi_nr=${6:-0}
local count
local dump_stats
@@ -856,10 +955,10 @@ chk_join_nr()
echo "[ ok ]"
fi
[ "${dump_stats}" = 1 ] && dump_stats
- if [ $checksum -eq 1 ]; then
- chk_csum_nr
- chk_fail_nr 0 0
- chk_infi_nr 0 0
+ if [ $validate_checksum -eq 1 ]; then
+ chk_csum_nr "" $fail_nr
+ chk_fail_nr $fail_nr $fail_nr
+ chk_infi_nr $infi_nr $infi_nr
fi
}
@@ -2164,6 +2263,28 @@ userspace_tests()
chk_rm_nr 0 0
}
+fail_tests()
+{
+ # multiple subflows
+ reset_with_fail 2
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
+ pm_nl_add_endpoint $ns2 10.0.3.2 dev ns2eth3 flags subflow
+ run_tests $ns1 $ns2 10.0.1.1 3
+ pedit_action_happened 2
+ chk_join_nr "MP_FAIL MP_RST: $pedit_action pedit action" 2 2 2 $pedit_action
+
+ # single subflow
+ reset_with_fail 1
+ pm_nl_set_limits $ns1 0 2
+ pm_nl_set_limits $ns2 0 2
+ run_tests $ns1 $ns2 10.0.1.1 3
+ pedit_action_happened 1
+ chk_join_nr "MP_FAIL infinite map: $pedit_action pedit action" 0 0 0 \
+ $pedit_action $pedit_action
+}
+
all_tests()
{
subflows_tests
@@ -2182,6 +2303,7 @@ all_tests()
deny_join_id0_tests
fullmesh_tests
userspace_tests
+ fail_tests
}
usage()
@@ -2203,6 +2325,7 @@ usage()
echo " -d deny_join_id0_tests"
echo " -m fullmesh_tests"
echo " -u userspace_tests"
+ echo " -F fail_tests"
echo " -c capture pcap files"
echo " -C enable data checksum"
echo " -i use ip mptcp"
@@ -2242,7 +2365,7 @@ if [ $do_all_tests -eq 1 ]; then
exit $ret
fi
-while getopts 'fesltra64bpkdmuchCSi' opt; do
+while getopts 'fesltra64bpkdmuchCSFi' opt; do
case $opt in
f)
subflows_tests
@@ -2292,6 +2415,9 @@ while getopts 'fesltra64bpkdmuchCSi' opt; do
u)
userspace_tests
;;
+ F)
+ fail_tests
+ ;;
c)
;;
C)
--
2.34.1
© 2016 - 2026 Red Hat, Inc.