Commit 30549eeb authored by Geliang Tang's avatar Geliang Tang Committed by Jakub Kicinski
Browse files

mptcp: make ADD_ADDR retransmission timeout adaptive



Currently the ADD_ADDR option is retransmitted with a fixed timeout. This
patch makes the retransmission timeout adaptive by using the maximum RTO
among all the subflows, while still capping it at the configured maximum
value (add_addr_timeout_max). This improves responsiveness when
establishing new subflows.

Specifically:
1. Adds mptcp_adjust_add_addr_timeout() helper to compute the adaptive
timeout.
2. Uses maximum subflow RTO (icsk_rto) when available.
3. Applies exponential backoff based on retransmission count.
4. Maintains fallback to configured max timeout when no RTO data exists.

This slightly changes the behaviour of the MPTCP "add_addr_timeout"
sysctl knob to be used as a maximum instead of a fixed value. But this
is seen as an improvement: the ADD_ADDR might be sent quicker than
before to improve the overall MPTCP connection. Also, the default
value is set to 2 min, which was already way too long, and caused the
ADD_ADDR not to be retransmitted for connections shorter than 2 minutes.

Suggested-by: default avatarMatthieu Baerts (NGI0) <matttbe@kernel.org>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/576


Reviewed-by: default avatarChristoph Paasch <cpaasch@openai.com>
Signed-off-by: default avatarGeliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: default avatarMatthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: default avatarMatthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20250907-net-next-mptcp-add_addr-retrans-adapt-v1-1-824cc805772b@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 4ea83b75
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -8,9 +8,11 @@ MPTCP Sysfs variables
===============================

add_addr_timeout - INTEGER (seconds)
	Set the timeout after which an ADD_ADDR control message will be
	resent to an MPTCP peer that has not acknowledged a previous
	ADD_ADDR message.
	Set the maximum value of timeout after which an ADD_ADDR control message
	will be resent to an MPTCP peer that has not acknowledged a previous
	ADD_ADDR message. A dynamically estimated retransmission timeout based
	on the estimated connection round-trip-time is used if this value is
	lower than the maximum one.

	Do not retransmit if set to 0.

+24 −4
Original line number Diff line number Diff line
@@ -268,6 +268,27 @@ int mptcp_pm_mp_prio_send_ack(struct mptcp_sock *msk,
	return -EINVAL;
}

static unsigned int mptcp_adjust_add_addr_timeout(struct mptcp_sock *msk)
{
	const struct net *net = sock_net((struct sock *)msk);
	unsigned int rto = mptcp_get_add_addr_timeout(net);
	struct mptcp_subflow_context *subflow;
	unsigned int max = 0;

	mptcp_for_each_subflow(msk, subflow) {
		struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
		struct inet_connection_sock *icsk = inet_csk(ssk);

		if (icsk->icsk_rto > max)
			max = icsk->icsk_rto;
	}

	if (max && max < rto)
		rto = max;

	return rto;
}

static void mptcp_pm_add_timer(struct timer_list *timer)
{
	struct mptcp_pm_add_entry *entry = timer_container_of(entry, timer,
@@ -292,7 +313,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)
		goto out;
	}

	timeout = mptcp_get_add_addr_timeout(sock_net(sk));
	timeout = mptcp_adjust_add_addr_timeout(msk);
	if (!timeout)
		goto out;

@@ -307,7 +328,7 @@ static void mptcp_pm_add_timer(struct timer_list *timer)

	if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
		sk_reset_timer(sk, timer,
			       jiffies + timeout);
			       jiffies + (timeout << entry->retrans_times));

	spin_unlock_bh(&msk->pm.lock);

@@ -348,7 +369,6 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
{
	struct mptcp_pm_add_entry *add_entry = NULL;
	struct sock *sk = (struct sock *)msk;
	struct net *net = sock_net(sk);
	unsigned int timeout;

	lockdep_assert_held(&msk->pm.lock);
@@ -374,7 +394,7 @@ bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,

	timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
reset_timer:
	timeout = mptcp_get_add_addr_timeout(net);
	timeout = mptcp_adjust_add_addr_timeout(msk);
	if (timeout)
		sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout);