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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).