Skip to content

Commit 94695e5

Browse files
enkechen-panwksacilotto
authored andcommitted
tcp: make TCP_USER_TIMEOUT accurate for zero window probes
BugLink: https://bugs.launchpad.net/bugs/1916061 commit 344db93 upstream. The TCP_USER_TIMEOUT is checked by the 0-window probe timer. As the timer has backoff with a max interval of about two minutes, the actual timeout for TCP_USER_TIMEOUT can be off by up to two minutes. In this patch the TCP_USER_TIMEOUT is made more accurate by taking it into account when computing the timer value for the 0-window probes. This patch is similar to and builds on top of the one that made TCP_USER_TIMEOUT accurate for RTOs in commit b701a99 ("tcp: Add tcp_clamp_rto_to_user_timeout() helper to improve accuracy"). Fixes: 9721e70 ("tcp: simplify window probe aborting on USER_TIMEOUT") Signed-off-by: Enke Chen <enchen@paloaltonetworks.com> Reviewed-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://lore.kernel.org/r/20210122191306.GA99540@localhost.localdomain Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 6ad7251 commit 94695e5

File tree

4 files changed

+22
-0
lines changed

4 files changed

+22
-0
lines changed

include/net/tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,7 @@ static inline void tcp_clear_xmit_timers(struct sock *sk)
619619

620620
unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
621621
unsigned int tcp_current_mss(struct sock *sk);
622+
u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when);
622623

623624
/* Bound MSS / TSO packet size with the half of the window */
624625
static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)

net/ipv4/tcp_input.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,6 +3295,7 @@ static void tcp_ack_probe(struct sock *sk)
32953295
} else {
32963296
unsigned long when = tcp_probe0_when(sk, TCP_RTO_MAX);
32973297

3298+
when = tcp_clamp_probe0_to_user_timeout(sk, when);
32983299
tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
32993300
when, TCP_RTO_MAX, NULL);
33003301
}

net/ipv4/tcp_output.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3850,6 +3850,8 @@ void tcp_send_probe0(struct sock *sk)
38503850
*/
38513851
timeout = TCP_RESOURCE_PROBE_INTERVAL;
38523852
}
3853+
3854+
timeout = tcp_clamp_probe0_to_user_timeout(sk, timeout);
38533855
tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0, timeout, TCP_RTO_MAX, NULL);
38543856
}
38553857

net/ipv4/tcp_timer.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
4040
return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));
4141
}
4242

43+
u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when)
44+
{
45+
struct inet_connection_sock *icsk = inet_csk(sk);
46+
u32 remaining;
47+
s32 elapsed;
48+
49+
if (!icsk->icsk_user_timeout || !icsk->icsk_probes_tstamp)
50+
return when;
51+
52+
elapsed = tcp_jiffies32 - icsk->icsk_probes_tstamp;
53+
if (unlikely(elapsed < 0))
54+
elapsed = 0;
55+
remaining = msecs_to_jiffies(icsk->icsk_user_timeout) - elapsed;
56+
remaining = max_t(u32, remaining, TCP_TIMEOUT_MIN);
57+
58+
return min_t(u32, remaining, when);
59+
}
60+
4361
/**
4462
* tcp_write_err() - close socket and save error info
4563
* @sk: The socket the error has appeared on.

0 commit comments

Comments
 (0)