[PATCH mptcp-net v5 07/20] mptcp: pm: ADD_ADDR rtx: skip inactive subflows

Matthieu Baerts (NGI0) posted 20 patches 1 month, 3 weeks ago
There is a newer version of this series
[PATCH mptcp-net v5 07/20] mptcp: pm: ADD_ADDR rtx: skip inactive subflows
Posted by Matthieu Baerts (NGI0) 1 month, 3 weeks ago
When looking at the maximum RTO amongst the subflows, inactive subflows
were taken into account: that includes stale ones, and the initial one
if it has been already been closed.

Unusable subflows are now simply skipped. Stale ones are used as an
alternative: if there are only stale ones, to take their maximum RTO and
avoid to eventually fallback to net.mptcp.add_addr_timeout, which is set
to 2 minutes by default.

Fixes: 30549eebc4d8 ("mptcp: make ADD_ADDR retransmission timeout adaptive")
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
---
v2: restore accidentally deleted icsk->icsk_rto > max check
---
 net/mptcp/pm.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index bc5168831085..22ba75fa876c 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -306,20 +306,27 @@ 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;
+	unsigned int max = 0, max_stale = 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)
+		if (!__mptcp_subflow_active(subflow))
+			continue;
+
+		if (unlikely(subflow->stale)) {
+			if (icsk->icsk_rto > max_stale)
+				max_stale = icsk->icsk_rto;
+		} else if (icsk->icsk_rto > max) {
 			max = icsk->icsk_rto;
+		}
 	}
 
-	if (max && max < rto)
-		rto = max;
+	if (max)
+		return max < rto ? max : rto;
 
-	return rto;
+	return max_stale && max_stale < rto ? max_stale : rto;
 }
 
 static void mptcp_pm_add_timer(struct timer_list *timer)

-- 
2.53.0
Re: [PATCH mptcp-net v5 07/20] mptcp: pm: ADD_ADDR rtx: skip inactive subflows
Posted by Mat Martineau 1 month, 2 weeks ago
On Wed, 15 Apr 2026, Matthieu Baerts (NGI0) wrote:

> When looking at the maximum RTO amongst the subflows, inactive subflows
> were taken into account: that includes stale ones, and the initial one
> if it has been already been closed.
>
> Unusable subflows are now simply skipped. Stale ones are used as an
> alternative: if there are only stale ones, to take their maximum RTO and
> avoid to eventually fallback to net.mptcp.add_addr_timeout, which is set
> to 2 minutes by default.
>
> Fixes: 30549eebc4d8 ("mptcp: make ADD_ADDR retransmission timeout adaptive")
> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
> ---
> v2: restore accidentally deleted icsk->icsk_rto > max check
> ---
> net/mptcp/pm.c | 17 ++++++++++++-----
> 1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
> index bc5168831085..22ba75fa876c 100644
> --- a/net/mptcp/pm.c
> +++ b/net/mptcp/pm.c
> @@ -306,20 +306,27 @@ 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;
> +	unsigned int max = 0, max_stale = 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)
> +		if (!__mptcp_subflow_active(subflow))
> +			continue;
> +
> +		if (unlikely(subflow->stale)) {
> +			if (icsk->icsk_rto > max_stale)
> +				max_stale = icsk->icsk_rto;
> +		} else if (icsk->icsk_rto > max) {
> 			max = icsk->icsk_rto;
> +		}
> 	}
>
> -	if (max && max < rto)
> -		rto = max;
> +	if (max)
> +		return max < rto ? max : rto;
>
> -	return rto;
> +	return max_stale && max_stale < rto ? max_stale : rto;

I'd find this more readable as

if (max)
         return min(max, rto);
else if (max_stale)
         return min(max_stale, rto);
else
         return rto;

- Mat


> }
>
> static void mptcp_pm_add_timer(struct timer_list *timer)
>
> -- 
> 2.53.0
>
>
>
Re: [PATCH mptcp-net v5 07/20] mptcp: pm: ADD_ADDR rtx: skip inactive subflows
Posted by Matthieu Baerts 1 month, 2 weeks ago
Hi Mat,

On 18/04/2026 20:09, Mat Martineau wrote:
> On Wed, 15 Apr 2026, Matthieu Baerts (NGI0) wrote:
> 
>> When looking at the maximum RTO amongst the subflows, inactive subflows
>> were taken into account: that includes stale ones, and the initial one
>> if it has been already been closed.
>>
>> Unusable subflows are now simply skipped. Stale ones are used as an
>> alternative: if there are only stale ones, to take their maximum RTO and
>> avoid to eventually fallback to net.mptcp.add_addr_timeout, which is set
>> to 2 minutes by default.
>>
>> Fixes: 30549eebc4d8 ("mptcp: make ADD_ADDR retransmission timeout
>> adaptive")
>> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
>> ---
>> v2: restore accidentally deleted icsk->icsk_rto > max check
>> ---
>> net/mptcp/pm.c | 17 ++++++++++++-----
>> 1 file changed, 12 insertions(+), 5 deletions(-)
>>
>> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
>> index bc5168831085..22ba75fa876c 100644
>> --- a/net/mptcp/pm.c
>> +++ b/net/mptcp/pm.c
>> @@ -306,20 +306,27 @@ 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;
>> +    unsigned int max = 0, max_stale = 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)
>> +        if (!__mptcp_subflow_active(subflow))
>> +            continue;
>> +
>> +        if (unlikely(subflow->stale)) {
>> +            if (icsk->icsk_rto > max_stale)
>> +                max_stale = icsk->icsk_rto;
>> +        } else if (icsk->icsk_rto > max) {
>>             max = icsk->icsk_rto;
>> +        }
>>     }
>>
>> -    if (max && max < rto)
>> -        rto = max;
>> +    if (max)
>> +        return max < rto ? max : rto;
>>
>> -    return rto;
>> +    return max_stale && max_stale < rto ? max_stale : rto;
> 
> I'd find this more readable as
> 
> if (max)
>         return min(max, rto);
> else if (max_stale)
>         return min(max_stale, rto);
> else
>         return rto;
Good idea! I will switch to that, but without the 'else', if that's OK.

Cheers,
Matt
-- 
Sponsored by the NGI0 Core fund.

Re: [PATCH mptcp-net v5 07/20] mptcp: pm: ADD_ADDR rtx: skip inactive subflows
Posted by Mat Martineau 1 month, 2 weeks ago
On Mon, 20 Apr 2026, Matthieu Baerts wrote:

> Hi Mat,
>
> On 18/04/2026 20:09, Mat Martineau wrote:
>> On Wed, 15 Apr 2026, Matthieu Baerts (NGI0) wrote:
>>
>>> When looking at the maximum RTO amongst the subflows, inactive subflows
>>> were taken into account: that includes stale ones, and the initial one
>>> if it has been already been closed.
>>>
>>> Unusable subflows are now simply skipped. Stale ones are used as an
>>> alternative: if there are only stale ones, to take their maximum RTO and
>>> avoid to eventually fallback to net.mptcp.add_addr_timeout, which is set
>>> to 2 minutes by default.
>>>
>>> Fixes: 30549eebc4d8 ("mptcp: make ADD_ADDR retransmission timeout
>>> adaptive")
>>> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
>>> ---
>>> v2: restore accidentally deleted icsk->icsk_rto > max check
>>> ---
>>> net/mptcp/pm.c | 17 ++++++++++++-----
>>> 1 file changed, 12 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
>>> index bc5168831085..22ba75fa876c 100644
>>> --- a/net/mptcp/pm.c
>>> +++ b/net/mptcp/pm.c
>>> @@ -306,20 +306,27 @@ 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;
>>> +    unsigned int max = 0, max_stale = 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)
>>> +        if (!__mptcp_subflow_active(subflow))
>>> +            continue;
>>> +
>>> +        if (unlikely(subflow->stale)) {
>>> +            if (icsk->icsk_rto > max_stale)
>>> +                max_stale = icsk->icsk_rto;
>>> +        } else if (icsk->icsk_rto > max) {
>>>             max = icsk->icsk_rto;
>>> +        }
>>>     }
>>>
>>> -    if (max && max < rto)
>>> -        rto = max;
>>> +    if (max)
>>> +        return max < rto ? max : rto;
>>>
>>> -    return rto;
>>> +    return max_stale && max_stale < rto ? max_stale : rto;
>>
>> I'd find this more readable as
>>
>> if (max)
>>         return min(max, rto);
>> else if (max_stale)
>>         return min(max_stale, rto);
>> else
>>         return rto;
> Good idea! I will switch to that, but without the 'else', if that's OK.

Sure, that's even better.


- Mat