Merge branch 'mptcp-avoid-dup-nl-events-and-propagate-error'

Matthieu Baerts says:

====================
mptcp: avoid dup NL events and propagate error

Here are two fixes affecting the MPTCP Netlink events with their tests:

- Patches 1 & 2: a subflow closed NL event was visible multiple times in
  some specific conditions. A fix for v5.12.

- Patches 3 & 4: subflow closed NL events never contained the error
  code, even when expected. A fix for v5.11.

Plus an extra fix:

- Patch 5: fix a false positive with the "signal addresses race test"
  subtest when validating the MPTCP Join selftest on a v5.15.y stable
  kernel.
====================

Link: https://patch.msgid.link/20260127-net-mptcp-dup-nl-events-v1-0-7f71e1bc4feb@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-01-28 20:59:09 -08:00
commit df8b9be3d4
2 changed files with 81 additions and 13 deletions

View file

@ -821,11 +821,8 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk)
static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
{
int err = sock_error(ssk);
int ssk_state;
if (!err)
return false;
int err;
/* only propagate errors on fallen-back sockets or
* on MPC connect
@ -833,6 +830,10 @@ static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk)
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk)))
return false;
err = sock_error(ssk);
if (!err)
return false;
/* We need to propagate only transition to CLOSE state.
* Orphaned socket will see such state change via
* subflow_sched_work_if_closed() and that path will properly
@ -2598,8 +2599,8 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
struct mptcp_sock *msk = mptcp_sk(sk);
struct sk_buff *skb;
/* The first subflow can already be closed and still in the list */
if (subflow->close_event_done)
/* The first subflow can already be closed or disconnected */
if (subflow->close_event_done || READ_ONCE(subflow->local_id) < 0)
return;
subflow->close_event_done = true;

View file

@ -2329,17 +2329,16 @@ signal_address_tests()
ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=1
speed=slow \
run_tests $ns1 $ns2 10.0.1.1
chk_join_nr 3 3 3
# 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
if mptcp_lib_kallsyms_has "mptcp_pm_subflow_check_next$"; then
# the server will not signal the address terminating
# the MPC subflow
chk_add_nr 3 3
else
chk_add_nr 4 4
fi
fi
}
@ -3847,21 +3846,28 @@ userspace_pm_chk_get_addr()
fi
}
# $1: ns ; $2: event type ; $3: count
# $1: ns ; $2: event type ; $3: count ; [ $4: attr ; $5: attr count ]
chk_evt_nr()
{
local ns=${1}
local evt_name="${2}"
local exp="${3}"
local attr="${4}"
local attr_exp="${5}"
local evts="${evts_ns1}"
local evt="${!evt_name}"
local attr_name
local count
if [ -n "${attr}" ]; then
attr_name=", ${attr}: ${attr_exp}"
fi
evt_name="${evt_name:16}" # without MPTCP_LIB_EVENT_
[ "${ns}" == "ns2" ] && evts="${evts_ns2}"
print_check "event ${ns} ${evt_name} (${exp})"
print_check "event ${ns} ${evt_name} (${exp}${attr_name})"
if [[ "${evt_name}" = "LISTENER_"* ]] &&
! mptcp_lib_kallsyms_has "mptcp_event_pm_listener$"; then
@ -3872,11 +3878,42 @@ chk_evt_nr()
count=$(grep -cw "type:${evt}" "${evts}")
if [ "${count}" != "${exp}" ]; then
fail_test "got ${count} events, expected ${exp}"
cat "${evts}"
return
elif [ -z "${attr}" ]; then
print_ok
return
fi
count=$(grep -w "type:${evt}" "${evts}" | grep -c ",${attr}:")
if [ "${count}" != "${attr_exp}" ]; then
fail_test "got ${count} event attributes, expected ${attr_exp}"
grep -w "type:${evt}" "${evts}"
else
print_ok
fi
}
# $1: ns ; $2: event type ; $3: expected count
wait_event()
{
local ns="${1}"
local evt_name="${2}"
local exp="${3}"
local evt="${!evt_name}"
local evts="${evts_ns1}"
local count
[ "${ns}" == "ns2" ] && evts="${evts_ns2}"
for _ in $(seq 100); do
count=$(grep -cw "type:${evt}" "${evts}")
[ "${count}" -ge "${exp}" ] && break
sleep 0.1
done
}
userspace_tests()
{
# userspace pm type prevents add_addr
@ -4085,6 +4122,36 @@ userspace_tests()
kill_events_pids
mptcp_lib_kill_group_wait $tests_pid
fi
# userspace pm no duplicated spurious close events after an error
if reset_with_events "userspace pm no dup close events after error" &&
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
set_userspace_pm $ns2
pm_nl_set_limits $ns1 0 2
{ timeout_test=120 test_linkfail=128 speed=slow \
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
local tests_pid=$!
wait_event ns2 MPTCP_LIB_EVENT_ESTABLISHED 1
userspace_pm_add_sf $ns2 10.0.3.2 20
chk_mptcp_info subflows 1 subflows 1
chk_subflows_total 2 2
# force quick loss
ip netns exec $ns2 sysctl -q net.ipv4.tcp_syn_retries=1
if ip netns exec "${ns1}" ${iptables} -A INPUT -s "10.0.1.2" \
-p tcp --tcp-option 30 -j REJECT --reject-with tcp-reset &&
ip netns exec "${ns2}" ${iptables} -A INPUT -d "10.0.1.2" \
-p tcp --tcp-option 30 -j REJECT --reject-with tcp-reset; then
wait_event ns2 MPTCP_LIB_EVENT_SUB_CLOSED 1
wait_event ns1 MPTCP_LIB_EVENT_SUB_CLOSED 1
chk_subflows_total 1 1
userspace_pm_add_sf $ns2 10.0.1.2 0
wait_event ns2 MPTCP_LIB_EVENT_SUB_CLOSED 2
chk_evt_nr ns2 MPTCP_LIB_EVENT_SUB_CLOSED 2 error 2
fi
kill_events_pids
mptcp_lib_kill_group_wait $tests_pid
fi
}
endpoint_tests()