Commit 5de7796d authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'mptcp-more-selftest-coverage-and-code-cleanup-for-net-next'

Mat Martineau says:

====================
mptcp: More selftest coverage and code cleanup for net-next

Patches 1-5 and 7-8 add selftest coverage (and an associated subflow
counter in the kernel) to validate the recently-updated handling of
subflows with ID 0.

Patch 6 renames a label in the userspace path manager for clarity.

Patches 9-11 and 13-15 factor out common selftest code by moving certain
functions to mptcp_lib.sh

Patch 12 makes sure the random data file generated for selftest
payloads has the intended size.

v3: https://lore.kernel.org/r/20231115-send-net-next-2023107-v3-0-1ef58145a882@kernel.org
v2: https://lore.kernel.org/r/20231114-send-net-next-2023107-v2-0-b650a477362c@kernel.org
v1: https://lore.kernel.org/r/20231027-send-net-next-2023107-v1-0-03eff9452957@kernel.org
====================

Link: https://lore.kernel.org/r/20231128-send-net-next-2023107-v4-0-8d6b94150f6b@kernel.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 3d6d7549 9369777c
......@@ -57,6 +57,7 @@ struct mptcp_info {
__u64 mptcpi_bytes_sent;
__u64 mptcpi_bytes_received;
__u64 mptcpi_bytes_acked;
__u8 mptcpi_subflows_total;
};
/* MPTCP Reset reason codes, rfc8684 */
......
......@@ -276,12 +276,12 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
if (!mptcp_pm_is_userspace(msk)) {
GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
goto remove_err;
goto out;
}
if (id_val == 0) {
err = mptcp_userspace_pm_remove_id_zero_address(msk, info);
goto remove_err;
goto out;
}
lock_sock(sk);
......@@ -296,7 +296,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
if (!match) {
GENL_SET_ERR_MSG(info, "address with specified id not found");
release_sock(sk);
goto remove_err;
goto out;
}
list_move(&match->list, &free_list);
......@@ -310,7 +310,7 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
}
err = 0;
remove_err:
out:
sock_put(sk);
return err;
}
......
......@@ -1072,6 +1072,15 @@ static inline void __mptcp_do_fallback(struct mptcp_sock *msk)
set_bit(MPTCP_FALLBACK_DONE, &msk->flags);
}
static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk)
{
struct sock *ssk = READ_ONCE(msk->first);
return ssk && ((1 << inet_sk_state_load(ssk)) &
(TCPF_ESTABLISHED | TCPF_SYN_SENT |
TCPF_SYN_RECV | TCPF_LISTEN));
}
static inline void mptcp_do_fallback(struct sock *ssk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
......
......@@ -938,6 +938,8 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
info->mptcpi_bytes_sent = msk->bytes_sent;
info->mptcpi_bytes_received = msk->bytes_received;
info->mptcpi_bytes_retrans = msk->bytes_retrans;
info->mptcpi_subflows_total = info->mptcpi_subflows +
__mptcp_has_initial_subflow(msk);
unlock_sock_fast(sk, slow);
}
EXPORT_SYMBOL_GPL(mptcp_diag_fill_info);
......
......@@ -182,23 +182,6 @@ chk_msk_inuse()
__chk_nr get_msk_inuse $expected "$msg" 0
}
# $1: ns, $2: port
wait_local_port_listen()
{
local listener_ns="${1}"
local port="${2}"
local port_hex i
port_hex="$(printf "%04X" "${port}")"
for i in $(seq 10); do
ip netns exec "${listener_ns}" cat /proc/net/tcp | \
awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
break
sleep 0.1
done
}
wait_connected()
{
local listener_ns="${1}"
......@@ -222,7 +205,7 @@ echo "a" | \
ip netns exec $ns \
./mptcp_connect -p 10000 -l -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
wait_local_port_listen $ns 10000
mptcp_lib_wait_local_port_listen $ns 10000
chk_msk_nr 0 "no msk on netns creation"
chk_msk_listen 10000
......@@ -245,7 +228,7 @@ echo "a" | \
ip netns exec $ns \
./mptcp_connect -p 10001 -l -s TCP -t ${timeout_poll} -w 20 \
0.0.0.0 >/dev/null &
wait_local_port_listen $ns 10001
mptcp_lib_wait_local_port_listen $ns 10001
echo "b" | \
timeout ${timeout_test} \
ip netns exec $ns \
......@@ -266,7 +249,7 @@ for I in `seq 1 $NR_CLIENTS`; do
./mptcp_connect -p $((I+10001)) -l -w 20 \
-t ${timeout_poll} 0.0.0.0 >/dev/null &
done
wait_local_port_listen $ns $((NR_CLIENTS + 10001))
mptcp_lib_wait_local_port_listen $ns $((NR_CLIENTS + 10001))
for I in `seq 1 $NR_CLIENTS`; do
echo "b" | \
......
......@@ -254,31 +254,6 @@ else
set_ethtool_flags "$ns4" ns4eth3 "$ethtool_args"
fi
print_file_err()
{
ls -l "$1" 1>&2
echo "Trailing bytes are: "
tail -c 27 "$1"
}
check_transfer()
{
local in=$1
local out=$2
local 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"
return 1
fi
return 0
}
check_mptcp_disabled()
{
local disabled_ns="ns_disabled-$rndh"
......@@ -310,12 +285,6 @@ check_mptcp_disabled()
return 0
}
# $1: IP address
is_v6()
{
[ -z "${1##*:*}" ]
}
do_ping()
{
local listener_ns="$1"
......@@ -324,7 +293,7 @@ do_ping()
local ping_args="-q -c 1"
local rc=0
if is_v6 "${connect_addr}"; then
if mptcp_lib_is_v6 "${connect_addr}"; then
$ipv6 || return 0
ping_args="${ping_args} -6"
fi
......@@ -341,38 +310,6 @@ do_ping()
return 0
}
# $1: ns, $2: MIB counter
get_mib_counter()
{
local listener_ns="${1}"
local mib="${2}"
# strip the header
ip netns exec "${listener_ns}" \
nstat -z -a "${mib}" | \
tail -n+2 | \
while read a count c rest; do
echo $count
done
}
# $1: ns, $2: port
wait_local_port_listen()
{
local listener_ns="${1}"
local port="${2}"
local port_hex i
port_hex="$(printf "%04X" "${port}")"
for i in $(seq 10); do
ip netns exec "${listener_ns}" cat /proc/net/tcp* | \
awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
break
sleep 0.1
done
}
do_transfer()
{
local listener_ns="$1"
......@@ -441,12 +378,12 @@ do_transfer()
nstat -n
fi
local stat_synrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
local stat_ackrx_last_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
local stat_cookietx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent")
local stat_cookierx_last=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv")
local stat_csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr")
local stat_csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr")
local stat_synrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
local stat_ackrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
local stat_cookietx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent")
local stat_cookierx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv")
local stat_csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr")
local stat_csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr")
timeout ${timeout_test} \
ip netns exec ${listener_ns} \
......@@ -454,7 +391,7 @@ do_transfer()
$extra_args $local_addr < "$sin" > "$sout" &
local spid=$!
wait_local_port_listen "${listener_ns}" "${port}"
mptcp_lib_wait_local_port_listen "${listener_ns}" "${port}"
local start
start=$(date +%s%3N)
......@@ -504,16 +441,16 @@ do_transfer()
return 1
fi
check_transfer $sin $cout "file received by client"
mptcp_lib_check_transfer $sin $cout "file received by client"
retc=$?
check_transfer $cin $sout "file received by server"
mptcp_lib_check_transfer $cin $sout "file received by server"
rets=$?
local stat_synrx_now_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
local stat_ackrx_now_l=$(get_mib_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
local stat_cookietx_now=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesSent")
local stat_cookierx_now=$(get_mib_counter "${listener_ns}" "TcpExtSyncookiesRecv")
local stat_ooo_now=$(get_mib_counter "${listener_ns}" "TcpExtTCPOFOQueue")
local stat_synrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
local stat_ackrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
local stat_cookietx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent")
local stat_cookierx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv")
local stat_ooo_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtTCPOFOQueue")
expect_synrx=$((stat_synrx_last_l))
expect_ackrx=$((stat_ackrx_last_l))
......@@ -542,8 +479,8 @@ do_transfer()
fi
if $checksum; then
local csum_err_s=$(get_mib_counter "${listener_ns}" "MPTcpExtDataCsumErr")
local csum_err_c=$(get_mib_counter "${connector_ns}" "MPTcpExtDataCsumErr")
local csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr")
local csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr")
local csum_err_s_nr=$((csum_err_s - stat_csum_err_s))
if [ $csum_err_s_nr -gt 0 ]; then
......@@ -613,9 +550,8 @@ make_file()
ksize=$((SIZE / 1024))
rem=$((SIZE - (ksize * 1024)))
dd if=/dev/urandom of="$name" bs=1024 count=$ksize 2> /dev/null
dd if=/dev/urandom conv=notrunc of="$name" bs=1 count=$rem 2> /dev/null
echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
mptcp_lib_make_file $name 1024 $ksize
dd if=/dev/urandom conv=notrunc of="$name" oflag=append bs=1 count=$rem 2> /dev/null
echo "Created $name (size $(du -b "$name")) containing data sent by $who"
}
......@@ -635,12 +571,12 @@ run_tests_lo()
fi
# skip if we don't want v6
if ! $ipv6 && is_v6 "${connect_addr}"; then
if ! $ipv6 && mptcp_lib_is_v6 "${connect_addr}"; then
return 0
fi
local local_addr
if is_v6 "${connect_addr}"; then
if mptcp_lib_is_v6 "${connect_addr}"; then
local_addr="::"
else
local_addr="0.0.0.0"
......@@ -708,7 +644,7 @@ run_test_transparent()
TEST_GROUP="${msg}"
# skip if we don't want v6
if ! $ipv6 && is_v6 "${connect_addr}"; then
if ! $ipv6 && mptcp_lib_is_v6 "${connect_addr}"; then
return 0
fi
......@@ -741,7 +677,7 @@ EOF
fi
local local_addr
if is_v6 "${connect_addr}"; then
if mptcp_lib_is_v6 "${connect_addr}"; then
local_addr="::"
r6flag="-6"
else
......
......@@ -207,3 +207,94 @@ mptcp_lib_result_print_all_tap() {
printf "%s\n" "${subtest}"
done
}
# get the value of keyword $1 in the line marked by keyword $2
mptcp_lib_get_info_value() {
grep "${2}" | sed -n 's/.*\('"${1}"':\)\([0-9a-f:.]*\).*$/\2/p;q'
}
# $1: info name ; $2: evts_ns ; $3: event type
mptcp_lib_evts_get_info() {
mptcp_lib_get_info_value "${1}" "^type:${3:-1}," < "${2}"
}
# $1: PID
mptcp_lib_kill_wait() {
[ "${1}" -eq 0 ] && return 0
kill -SIGUSR1 "${1}" > /dev/null 2>&1
kill "${1}" > /dev/null 2>&1
wait "${1}" 2>/dev/null
}
# $1: IP address
mptcp_lib_is_v6() {
[ -z "${1##*:*}" ]
}
# $1: ns, $2: MIB counter
mptcp_lib_get_counter() {
local ns="${1}"
local counter="${2}"
local count
count=$(ip netns exec "${ns}" nstat -asz "${counter}" |
awk 'NR==1 {next} {print $2}')
if [ -z "${count}" ]; then
mptcp_lib_fail_if_expected_feature "${counter} counter"
return 1
fi
echo "${count}"
}
mptcp_lib_make_file() {
local name="${1}"
local bs="${2}"
local size="${3}"
dd if=/dev/urandom of="${name}" bs="${bs}" count="${size}" 2> /dev/null
echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "${name}"
}
# $1: file
mptcp_lib_print_file_err() {
ls -l "${1}" 1>&2
echo "Trailing bytes are: "
tail -c 27 "${1}"
}
# $1: input file ; $2: output file ; $3: what kind of file
mptcp_lib_check_transfer() {
local in="${1}"
local out="${2}"
local what="${3}"
if ! cmp "$in" "$out" > /dev/null 2>&1; then
echo "[ FAIL ] $what does not match (in, out):"
mptcp_lib_print_file_err "$in"
mptcp_lib_print_file_err "$out"
return 1
fi
return 0
}
# $1: ns, $2: port
mptcp_lib_wait_local_port_listen() {
local listener_ns="${1}"
local port="${2}"
local port_hex
port_hex="$(printf "%04X" "${port}")"
local _
for _ in $(seq 10); do
ip netns exec "${listener_ns}" cat /proc/net/tcp* | \
awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) \
{rc=0; exit}} END {exit rc}" &&
break
sleep 0.1
done
}
......@@ -135,38 +135,6 @@ check_mark()
return 0
}
print_file_err()
{
ls -l "$1" 1>&2
echo "Trailing bytes are: "
tail -c 27 "$1"
}
check_transfer()
{
local in=$1
local out=$2
local 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
return 1
fi
return 0
}
# $1: IP address
is_v6()
{
[ -z "${1##*:*}" ]
}
do_transfer()
{
local listener_ns="$1"
......@@ -183,7 +151,7 @@ do_transfer()
local mptcp_connect="./mptcp_connect -r 20"
local local_addr ip
if is_v6 "${connect_addr}"; then
if mptcp_lib_is_v6 "${connect_addr}"; then
local_addr="::"
ip=ipv6
else
......@@ -238,7 +206,7 @@ do_transfer()
check_mark $connector_ns 4 || retc=1
fi
check_transfer $cin $sout "file received by server"
mptcp_lib_check_transfer $cin $sout "file received by server"
rets=$?
mptcp_lib_result_code "${retc}" "mark ${ip}"
......@@ -257,8 +225,7 @@ make_file()
local who=$2
local size=$3
dd if=/dev/urandom of="$name" bs=1024 count=$size 2> /dev/null
echo -e "\nMPTCP_TEST_FILE_END_MARKER" >> "$name"
mptcp_lib_make_file $name 1024 $size
echo "Created $name (size $size KB) containing data sent by $who"
}
......
......@@ -123,23 +123,6 @@ setup()
grep -q ' kmemleak_init$\| lockdep_init$\| kasan_init$\| prove_locking$' /proc/kallsyms && slack=$((slack+550))
}
# $1: ns, $2: port
wait_local_port_listen()
{
local listener_ns="${1}"
local port="${2}"
local port_hex i
port_hex="$(printf "%04X" "${port}")"
for i in $(seq 10); do
ip netns exec "${listener_ns}" cat /proc/net/tcp* | \
awk "BEGIN {rc=1} {if (\$2 ~ /:${port_hex}\$/ && \$4 ~ /0A/) {rc=0; exit}} END {exit rc}" &&
break
sleep 0.1
done
}
do_transfer()
{
local cin=$1
......@@ -179,7 +162,7 @@ do_transfer()
0.0.0.0 < "$sin" > "$sout" &
local spid=$!
wait_local_port_listen "${ns3}" "${port}"
mptcp_lib_wait_local_port_listen "${ns3}" "${port}"
timeout ${timeout_test} \
ip netns exec ${ns1} \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment