Commit 0c3d79bc authored by Julian Anastasov's avatar Julian Anastasov Committed by David S. Miller

tcp: reduce SYN-ACK retrans for TCP_DEFER_ACCEPT

Change SYN-ACK retransmitting code for the TCP_DEFER_ACCEPT
users to not retransmit SYN-ACKs during the deferring period if
ACK from client was received. The goal is to reduce traffic
during the deferring period. When the period is finished
we continue with sending SYN-ACKs (at least one) but this time
any traffic from client will change the request to established
socket allowing application to terminate it properly.
Also, do not drop acked request if sending of SYN-ACK fails.
Signed-off-by: default avatarJulian Anastasov <ja@ssi.bg>
Acked-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d1b99ba4
...@@ -446,6 +446,28 @@ extern int sysctl_tcp_synack_retries; ...@@ -446,6 +446,28 @@ extern int sysctl_tcp_synack_retries;
EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add); EXPORT_SYMBOL_GPL(inet_csk_reqsk_queue_hash_add);
/* Decide when to expire the request and when to resend SYN-ACK */
static inline void syn_ack_recalc(struct request_sock *req, const int thresh,
const int max_retries,
const u8 rskq_defer_accept,
int *expire, int *resend)
{
if (!rskq_defer_accept) {
*expire = req->retrans >= thresh;
*resend = 1;
return;
}
*expire = req->retrans >= thresh &&
(!inet_rsk(req)->acked || req->retrans >= max_retries);
/*
* Do not resend while waiting for data after ACK,
* start to resend on end of deferring period to give
* last chance for data or ACK to create established socket.
*/
*resend = !inet_rsk(req)->acked ||
req->retrans >= rskq_defer_accept - 1;
}
void inet_csk_reqsk_queue_prune(struct sock *parent, void inet_csk_reqsk_queue_prune(struct sock *parent,
const unsigned long interval, const unsigned long interval,
const unsigned long timeout, const unsigned long timeout,
...@@ -501,9 +523,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, ...@@ -501,9 +523,15 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
reqp=&lopt->syn_table[i]; reqp=&lopt->syn_table[i];
while ((req = *reqp) != NULL) { while ((req = *reqp) != NULL) {
if (time_after_eq(now, req->expires)) { if (time_after_eq(now, req->expires)) {
if ((req->retrans < thresh || int expire = 0, resend = 0;
(inet_rsk(req)->acked && req->retrans < max_retries))
&& !req->rsk_ops->rtx_syn_ack(parent, req)) { syn_ack_recalc(req, thresh, max_retries,
queue->rskq_defer_accept,
&expire, &resend);
if (!expire &&
(!resend ||
!req->rsk_ops->rtx_syn_ack(parent, req) ||
inet_rsk(req)->acked)) {
unsigned long timeo; unsigned long timeo;
if (req->retrans++ == 0) if (req->retrans++ == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment