[PATCH net v2 2/2] tcp_metrics: use ssthresh value from dst if there is no metrics

From: Petr Tesarik
Date: Fri Jun 20 2025 - 08:58:10 EST


If there is no cached TCP metrics entry for a connection, initialize
tp->snd_ssthresh from the corresponding dst entry. Of course, this value
may have to be clamped to tp->snd_cwnd_clamp, but let's not copy and paste
the existing code. Instead, move the check to the common path.

When ssthresh value is zero, the connection should enter initial slow
start, indicated by setting tp->snd_ssthresh to infinity (ignoring the
value of tp->snd_cwnd_clamp). Move this check against zero to the common
path, too.

Fixes: 51c5d0c4b169 ("tcp: Maintain dynamic metrics in local cache.")
Signed-off-by: Petr Tesarik <ptesarik@xxxxxxxx>
---
net/ipv4/tcp_metrics.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index dd8f3457bd72..6f7172ea8bc8 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -473,12 +473,13 @@ void tcp_init_metrics(struct sock *sk)
/* ssthresh may have been reduced unnecessarily during.
* 3WHS. Restore it back to its initial default.
*/
- tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
+ tp->snd_ssthresh = 0;
if (!dst)
goto reset;

if (dst_metric_locked(dst, RTAX_CWND))
tp->snd_cwnd_clamp = dst_metric(dst, RTAX_CWND);
+ tp->snd_ssthresh = dst_metric(dst, RTAX_SSTHRESH);

rcu_read_lock();
tm = tcp_get_metrics(sk, dst, false);
@@ -487,13 +488,8 @@ void tcp_init_metrics(struct sock *sk)
goto reset;
}

- val = READ_ONCE(net->ipv4.sysctl_tcp_no_ssthresh_metrics_save) ?
- 0 : tcp_metric_get(tm, TCP_METRIC_SSTHRESH);
- if (val) {
- tp->snd_ssthresh = val;
- if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
- tp->snd_ssthresh = tp->snd_cwnd_clamp;
- }
+ if (!READ_ONCE(net->ipv4.sysctl_tcp_no_ssthresh_metrics_save))
+ tp->snd_ssthresh = tcp_metric_get(tm, TCP_METRIC_SSTHRESH);
val = tcp_metric_get(tm, TCP_METRIC_REORDERING);
if (val && tp->reordering != val)
tp->reordering = val;
@@ -537,6 +533,11 @@ void tcp_init_metrics(struct sock *sk)

inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK;
}
+
+ if (!tp->snd_ssthresh)
+ tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
+ else if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
+ tp->snd_ssthresh = tp->snd_cwnd_clamp;
}

bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst)
--
2.49.0