mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
tcp: fix TCP_DEFER_ACCEPT retrans calculation
Fix TCP_DEFER_ACCEPT conversion between seconds and retransmission to match the TCP SYN-ACK retransmission periods because the time is converted to such retransmissions. The old algorithm selects one more retransmission in some cases. Allow up to 255 retransmissions. Signed-off-by: Julian Anastasov <ja@ssi.bg> Acked-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0c3d79bce4
commit
b103cf3438
1 changed files with 43 additions and 12 deletions
|
@ -326,6 +326,43 @@ void tcp_enter_memory_pressure(struct sock *sk)
|
||||||
|
|
||||||
EXPORT_SYMBOL(tcp_enter_memory_pressure);
|
EXPORT_SYMBOL(tcp_enter_memory_pressure);
|
||||||
|
|
||||||
|
/* Convert seconds to retransmits based on initial and max timeout */
|
||||||
|
static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
|
||||||
|
{
|
||||||
|
u8 res = 0;
|
||||||
|
|
||||||
|
if (seconds > 0) {
|
||||||
|
int period = timeout;
|
||||||
|
|
||||||
|
res = 1;
|
||||||
|
while (seconds > period && res < 255) {
|
||||||
|
res++;
|
||||||
|
timeout <<= 1;
|
||||||
|
if (timeout > rto_max)
|
||||||
|
timeout = rto_max;
|
||||||
|
period += timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert retransmits to seconds based on initial and max timeout */
|
||||||
|
static int retrans_to_secs(u8 retrans, int timeout, int rto_max)
|
||||||
|
{
|
||||||
|
int period = 0;
|
||||||
|
|
||||||
|
if (retrans > 0) {
|
||||||
|
period = timeout;
|
||||||
|
while (--retrans) {
|
||||||
|
timeout <<= 1;
|
||||||
|
if (timeout > rto_max)
|
||||||
|
timeout = rto_max;
|
||||||
|
period += timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return period;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for a TCP event.
|
* Wait for a TCP event.
|
||||||
*
|
*
|
||||||
|
@ -2163,16 +2200,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCP_DEFER_ACCEPT:
|
case TCP_DEFER_ACCEPT:
|
||||||
icsk->icsk_accept_queue.rskq_defer_accept = 0;
|
/* Translate value in seconds to number of retransmits */
|
||||||
if (val > 0) {
|
icsk->icsk_accept_queue.rskq_defer_accept =
|
||||||
/* Translate value in seconds to number of
|
secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
|
||||||
* retransmits */
|
TCP_RTO_MAX / HZ);
|
||||||
while (icsk->icsk_accept_queue.rskq_defer_accept < 32 &&
|
|
||||||
val > ((TCP_TIMEOUT_INIT / HZ) <<
|
|
||||||
icsk->icsk_accept_queue.rskq_defer_accept))
|
|
||||||
icsk->icsk_accept_queue.rskq_defer_accept++;
|
|
||||||
icsk->icsk_accept_queue.rskq_defer_accept++;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TCP_WINDOW_CLAMP:
|
case TCP_WINDOW_CLAMP:
|
||||||
|
@ -2353,8 +2384,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
|
||||||
val = (val ? : sysctl_tcp_fin_timeout) / HZ;
|
val = (val ? : sysctl_tcp_fin_timeout) / HZ;
|
||||||
break;
|
break;
|
||||||
case TCP_DEFER_ACCEPT:
|
case TCP_DEFER_ACCEPT:
|
||||||
val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 :
|
val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept,
|
||||||
((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1));
|
TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ);
|
||||||
break;
|
break;
|
||||||
case TCP_WINDOW_CLAMP:
|
case TCP_WINDOW_CLAMP:
|
||||||
val = tp->window_clamp;
|
val = tp->window_clamp;
|
||||||
|
|
Loading…
Reference in a new issue