Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/576
Reviewed-by: Christoph Paasch <cpaasch@openai.com>
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu 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: Jakub Kicinski <kuba@kernel.org>

authored by

Geliang Tang and committed by
Jakub Kicinski
30549eeb 4ea83b75

+29 -7
+5 -3
Documentation/networking/mptcp-sysctl.rst
··· 8 8 =============================== 9 9 10 10 add_addr_timeout - INTEGER (seconds) 11 - Set the timeout after which an ADD_ADDR control message will be 12 - resent to an MPTCP peer that has not acknowledged a previous 13 - ADD_ADDR message. 11 + Set the maximum value of timeout after which an ADD_ADDR control message 12 + will be resent to an MPTCP peer that has not acknowledged a previous 13 + ADD_ADDR message. A dynamically estimated retransmission timeout based 14 + on the estimated connection round-trip-time is used if this value is 15 + lower than the maximum one. 14 16 15 17 Do not retransmit if set to 0. 16 18
+24 -4
net/mptcp/pm.c
··· 268 268 return -EINVAL; 269 269 } 270 270 271 + static unsigned int mptcp_adjust_add_addr_timeout(struct mptcp_sock *msk) 272 + { 273 + const struct net *net = sock_net((struct sock *)msk); 274 + unsigned int rto = mptcp_get_add_addr_timeout(net); 275 + struct mptcp_subflow_context *subflow; 276 + unsigned int max = 0; 277 + 278 + mptcp_for_each_subflow(msk, subflow) { 279 + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); 280 + struct inet_connection_sock *icsk = inet_csk(ssk); 281 + 282 + if (icsk->icsk_rto > max) 283 + max = icsk->icsk_rto; 284 + } 285 + 286 + if (max && max < rto) 287 + rto = max; 288 + 289 + return rto; 290 + } 291 + 271 292 static void mptcp_pm_add_timer(struct timer_list *timer) 272 293 { 273 294 struct mptcp_pm_add_entry *entry = timer_container_of(entry, timer, ··· 313 292 goto out; 314 293 } 315 294 316 - timeout = mptcp_get_add_addr_timeout(sock_net(sk)); 295 + timeout = mptcp_adjust_add_addr_timeout(msk); 317 296 if (!timeout) 318 297 goto out; 319 298 ··· 328 307 329 308 if (entry->retrans_times < ADD_ADDR_RETRANS_MAX) 330 309 sk_reset_timer(sk, timer, 331 - jiffies + timeout); 310 + jiffies + (timeout << entry->retrans_times)); 332 311 333 312 spin_unlock_bh(&msk->pm.lock); 334 313 ··· 369 348 { 370 349 struct mptcp_pm_add_entry *add_entry = NULL; 371 350 struct sock *sk = (struct sock *)msk; 372 - struct net *net = sock_net(sk); 373 351 unsigned int timeout; 374 352 375 353 lockdep_assert_held(&msk->pm.lock); ··· 394 374 395 375 timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0); 396 376 reset_timer: 397 - timeout = mptcp_get_add_addr_timeout(net); 377 + timeout = mptcp_adjust_add_addr_timeout(msk); 398 378 if (timeout) 399 379 sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout); 400 380