From: Willy Tarreau <w@1wt.eu>
To: Julian Anastasov <ja@ssi.bg>
Cc: David Miller <davem@davemloft.net>,
netdev@vger.kernel.org, eric.dumazet@gmail.com
Subject: Re: TCP_DEFER_ACCEPT is missing counter update
Date: Fri, 16 Oct 2009 07:03:10 +0200 [thread overview]
Message-ID: <20091016050310.GA5574@1wt.eu> (raw)
In-Reply-To: <Pine.LNX.4.58.0910152257410.3047@u.domain.uli>
Hello Julian,
On Fri, Oct 16, 2009 at 01:44:34AM +0300, Julian Anastasov wrote:
(...)
> I was not clear enough in previous email. Your goal
> is to decrease period per client while the actually decreased
> threshold is on the listener's socket. 256 conns will be enough
> to completely disable TCP_DEFER_ACCEPT on the listener (u8).
Damn! Now that you're explaining this, it seems obvious and makes
so much sense ! Of course you're right. We should not touch the
listening socket, only the new socket being created ! Thanks for
this clarification. David, Julian is right, please drop my patch.
(...)
> As for new flags, may be we should not change
> TCP_DEFER_ACCEPT values because current applications can
> depend on it.
I have no problem with that, eventhough I'm really doubting
that many applications depend on its current behaviour.
> There is some free space in
> struct request_sock_queue just after u8 rskq_defer_accept.
> May be new flags/modes can go there to define another
> behavior but it means also changes in applications to support
> it.
One idea I had was to make it signed, because there is currently
no use for negative values. But let's see your proposal below.
> /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
> - if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
> + if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
> TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
> inet_rsk(req)->acked = 1;
> return NULL;
> }
Yes, of course that looks a lot better !
(...)
> Such change will affect all servers that use
> TCP_DEFER_ACCEPT retransmissions less than TCP_SYNCNT. They
> will start to see wakeups without data after the TCP_DEFER_ACCEPT
> period.
Indeed. But anyway a server must always be prepared to see wakeup
without data, because there are some situations where it will still
happen. For instance, if hardware RX cksum is not possible, a data
packet will cause a wakeup and during the recv(), the copy_and_cksum
will detect a cksum error and will not send anything to userland,
so the application will get an empty read.
> To summarize:
>
> SECOND CLIENT SERVER
> ---------------------------------------------------------
> 0 SYN SYN-ACK
> if DATA => ESTABLISH
> if ACK => acked=1
> 3 SYN-ACK (set retrans=1)
> if ACK and TCP_DEFER_ACCEPT=1retrans => ESTABLISH
> if DATA => ESTABLISH
> if ACK => acked=1
> 9 if TCP_SYNCNT=1 => expire
> else SYN-ACK (set retrans=2)
> if ACK and TCP_DEFER_ACCEPT=2retrans => ESTABLISH
> if DATA => ESTABLISH
> if ACK => acked=1
> ...
>
> PRO:
>
> - if TCP_DEFER_ACCEPT<TCP_SYNCNT and client properly resends
> ACK on every SYN-ACK retransmission then we always will
> switch to established state on TCP_DEFER_ACCEPT expiration.
That's what I wanted to achieve :-)
> Such conns will never expire in SYN_RECV state. They
> will be terminated by client's FIN or will be accepted
> by server application and terminated properly. Of course,
> there is some chance if client delays its ACKs or if SYN-ACK
> is lost the open request to expire in SYN_RECV state.
Yes, but that must be covered by both ends stacks. Network
losses are normal and such events already happen in minor
quantities everyday.
> CON:
>
> - if client refuses to send DATA we still need these SYN-ACKs
> to trigger ACK retransmissions from client because the only
> way to switch to established state is when packet is received,
> I don't know how TCP_DEFER_ACCEPT expiration can directly change
> the open request to established state.
Well anyway this is already better than the current situation where
an apparently established connection silently dies. With this
proposal, applications have a way to get a normal behaviour.
> May be it is possible to send first SYN-ACK and
> if one ACK is received to send more SYN-ACKs after
> TCP_DEFER_ACCEPT period expires. Then client still has chance
> to send ACK or DATA that will switch open request to established
> socket. So, our timer will be silent when acked=1 while
> TCP_DEFER_ACCEPT period is active, for example:
>
> SYN
> SYN-ACK
> ACK
> ...
> acked=1 => no SYN-ACKs retrans (assume they are sent and lost)
>
> ...
> TCP_DEFER_ACCEPT expires => send 2nd SYN-ACK
> ... If no client's ACK then resend SYN-ACK while retrans<TCP_SYNCNT
> ...
> ACK or DATA => ESTABLISHED
On first reading I found it a bit dangerous because the client will assume
an established connection when not seeing any new SYN-ACKs. And if it has
no data to send, it will never retransmit its ACK. But after some thinking,
it still matches the purpose of TCP_DEFER_ACCEPT, without the extra
SYN-ACK / ACK dance that we currently observe. I was also worried about
middle firewalls, but they will have no problem because they'd see an
established connection (SYN,SYN-ACK,ACK), so their expiration timer will
be large enough to cover the lack of SYN-ACK during TCP_DEFER_ACCEPT.
> This will need little change in inet_csk_reqsk_queue_prune()
> but it saves SYN-ACK traffic during deferring period in the
> common case when client sends ACK. If such compromise is
> acceptable I can prepare and test some patch.
I would personally like this a lot ! This will satisfy people who
expect it to establish at the end of the "TCP_DEFER_ACCEPT delay"
as can be interpreted from the man page, will reduce the number of
useless SYN-ACKs that annoy other people while still making no
visible change for anyone who would rely on the current behaviour.
Regards,
Willy
next prev parent reply other threads:[~2009-10-16 5:03 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-13 5:07 TCP_DEFER_ACCEPT is missing counter update Willy Tarreau
2009-10-13 7:11 ` David Miller
2009-10-13 7:19 ` Willy Tarreau
2009-10-13 7:27 ` David Miller
2009-10-13 21:27 ` Julian Anastasov
2009-10-14 4:52 ` Willy Tarreau
2009-10-14 7:27 ` Julian Anastasov
2009-10-14 20:17 ` Willy Tarreau
2009-10-14 21:12 ` Olaf van der Spek
2009-10-14 22:43 ` David Miller
2009-10-15 6:08 ` Willy Tarreau
2009-10-15 8:47 ` Julian Anastasov
2009-10-15 12:41 ` Willy Tarreau
2009-10-15 22:44 ` Julian Anastasov
2009-10-16 3:51 ` Eric Dumazet
2009-10-16 5:00 ` Eric Dumazet
2009-10-16 5:29 ` Willy Tarreau
2009-10-16 6:05 ` Eric Dumazet
2009-10-16 6:18 ` Willy Tarreau
2009-10-16 7:08 ` Eric Dumazet
2009-10-16 7:19 ` Willy Tarreau
2009-10-16 5:03 ` Willy Tarreau [this message]
2009-10-16 8:49 ` Julian Anastasov
2009-10-16 10:40 ` Eric Dumazet
2009-10-16 19:27 ` Willy Tarreau
2009-10-17 11:48 ` Julian Anastasov
2009-10-17 12:07 ` Eric Dumazet
2009-10-17 14:20 ` Julian Anastasov
2009-10-19 20:01 ` Eric Dumazet
2009-10-19 20:11 ` Willy Tarreau
2009-10-19 20:17 ` Eric Dumazet
2009-10-20 2:23 ` David Miller
2009-10-15 7:59 ` Julian Anastasov
2009-10-16 10:08 ` Ilpo Järvinen
2009-10-13 7:23 ` Eric Dumazet
2009-10-13 7:34 ` Willy Tarreau
2009-10-13 8:08 ` Olaf van der Spek
2009-10-13 8:29 ` Eric Dumazet
2009-10-13 8:35 ` David Miller
2009-10-13 7:35 ` David Miller
2009-10-13 8:12 ` Willy Tarreau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20091016050310.GA5574@1wt.eu \
--to=w@1wt.eu \
--cc=davem@davemloft.net \
--cc=eric.dumazet@gmail.com \
--cc=ja@ssi.bg \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.