Re: [tcpm] Faster application handshakes with SYN/ACK payloads

Joe Touch <touch@ISI.EDU> Sat, 02 August 2008 02:22 UTC

Return-Path: <>
Received: from [] (localhost []) by (Postfix) with ESMTP id 5533B3A6B82; Fri, 1 Aug 2008 19:22:32 -0700 (PDT)
Received: from localhost (localhost []) by (Postfix) with ESMTP id D07033A6B83 for <>; Fri, 1 Aug 2008 19:22:30 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.53
X-Spam-Status: No, score=-1.53 tagged_above=-999 required=5 tests=[BAYES_00=-2.599, DATE_IN_PAST_06_12=1.069]
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id nz6kRH1uVW6S for <>; Fri, 1 Aug 2008 19:22:29 -0700 (PDT)
Received: from ( []) by (Postfix) with ESMTP id A39593A6B7A for <>; Fri, 1 Aug 2008 19:22:29 -0700 (PDT)
Received: from [] ( []) by (8.13.8/8.13.8) with ESMTP id m722M7bQ003767 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 1 Aug 2008 19:22:16 -0700 (PDT)
Message-ID: <>
Date: Fri, 01 Aug 2008 11:17:27 -0700
From: Joe Touch <touch@ISI.EDU>
User-Agent: Thunderbird (Windows/20080708)
MIME-Version: 1.0
To: Adam Langley <>
References: <> <> <>
In-Reply-To: <>
X-Enigmail-Version: 0.95.6
X-ISI-4-43-8-MailScanner: Found to be clean
Subject: Re: [tcpm] Faster application handshakes with SYN/ACK payloads
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: TCP Maintenance and Minor Extensions Working Group <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="us-ascii"; Format="flowed"

Hash: SHA1

Hi, Adam,

Adam Langley wrote:
| On Thu, Jul 31, 2008 at 4:02 PM, Joe Touch <> wrote:
|> - - TCP is already permitted to send data in the SYN-ACK
|>        prohibiting it when the SA-PP option is missing violates
|>        RFC1122 sec -- unknown options are silently ignored
|>        options that change TCP need to be explicitly acknowledged,
|>        and current (legacy) behavior should be assumed if not
|>        acknowledged
| Ah, I didn't know this. Thank you!
| I don't believe changing TCP to disallow this is a good idea. However,
| it's important that userland knows weather this experiment is in
| effect.

It's not an experiment; it's valid TCP behavior.

Why does the application need to know? As you note, it speeds up
application performance, but the app never knows how long the SYN
exchange takes anyway - or whether there are retransmissions.

- ------

Although there is more detailed feedback below, it might be useful to
raise this up a level.

If the purpose of this option is to encourage servers that know about
the option to potentially speed up their data transmission, then it
might be sufficient to just send the hint in the SYN. The SA would then
have the data if the server wanted to.

What if the server just assumed this? It seems like nothing
should break and it would work where it should anyway...

I.e., Nike's rule applies: "Just do it."
(no  need for an option)

(side note) Such an option might be useful, but might also be an issue.
It tests the fact that TCPs ignore unknown options, a test that might
fail. It also tests the fact that middleboxes should pass options
unmodified, which also might fail. Although either of these behaviors
would be out of spec, I wonder whether it's useful to try to optimize a
connection at the expense of it possibly failing.

If this option is intended to 'definitively speed up' connections,
there's nothing in TCP that is 'realtime'. Applications can't see things
like retransmission, or the fact that data in the SYN (and thus SYN-ACK)
need not be ACKd when the SYN (or SYNACK) is ACK'd. Application data
boundaries (writes) don't need to correspond to data segmentation
either. Overall, there seem like too many ways in which valid TCP
behavior can stall things for an extra RTT or so *anytime* during a
connection (including the handshake); forcing data into the SYNACK
doesn't seem productive if that's the case.

A change to TCP that makes this option visible seems like it's a change
to TCP semantics that requires broader modifications - the API needs to
be redefined, socket options (or the equivalent) need to be defined,
etc. For very short exchanges for which 1 RTT savings would be
significant, perhaps TCP isn't the right protocol to use, IMO. For
longer connections, the savings would be masked by other RTTs anyway.

- ------

The following are details, but it would be more useful to focus on the
above first...

- -- Joe

| Thus, I believe that I should echo the SA-PP option in the

You can, but it doesn't really matter. The SA-PP can be considered a
hint to the other end to encourage it to send data in the SA. If the SA
contains data, either the other end was suitably encouraged, or it
didn't need encouragement. Either way, the presence of the data in the
SA tells you what you need to know - that the other end sent data.

Either way, once your end receives SA data, it can allow its app layer
to access the data once the subsequent ACK is sent. As far as the
initiating end is concerned, the TWHS ends when that ACK is sent anyway.

| Also, it should probably change names: SYN/ACK Payloads
| Processed or some similar.
|> - - The rule "For a given SYN, if any resulting SYNACK frame has a
|> then all resulting frames MUST have a payload" appears to disable
|> persists and ACKs as would be needed for proper operation when data is
|> not available in one or more direction
| That's badly worded on my part. It should read:
| "For a given SYN, if any resulting SYNACK frame has a payload then all
| resulting SYNACK frames MUST have a payload"

There is only one SYNACK segment in a connection in a given direction,
excepting retransmissions. There is no reason why retransmissions need
to include data - if the SA with data is received, either the SA is ACKd
or the SA and data are ACKd; if the SA without data is received, it
would be ACKd.

The result is that either the ACK says the SA data got there or not. If
not, then it would be retransmitted in a regular data packet.

Again, since TCP is NOT a 'realtime' protocol - and doesn't have a
'realtime' handshake', the application can't know or care about the

| (i.e. the restriction only apply to SYNACK frames. It's just so a host
| cannot decide the retransmit a different SYNACK)

See above; I don't see why it would, but I don't see why the application
could care.

|> - - the diagrams need to include some corner cases:
|>        - when KX is larger than the PMTU in fig 3 (or NList is
|>        larger than the PMTU in fig 2)
|>        (i.e., it seems like there is a missing MUST NOT on the length)
| It's suggested that the payload be limited to 64-bytes to prevent
| amplification backscatter from a SYN flood. Thus these bytestrings
| have to fit within the MTU. If an implementation doesn't enforce this,
| then it has to drop support when replying on a link where the MTU is
| insufficient.

A 576 MTU is the smallest size that endpoints agree to reassemble; it is
NOT the smallest MTU all links agree to support in the Internet. The
smallest MTU is 68 bytes - i.e., IP with all possible options, TCP with
none, and the smallest possible fragment (8 bytes) [see RFC791]. As a
result, a 64-byte payload is too large to assume that it won't be
fragmented (that may be true practically in many cases, but it isn't a

|>        - how do you handle simultaneous opens?
| I believe that simultaneous opens work just fine, although both sides
| will believe that the other doesn't support this experiment since the
| option won't be echoed in the SYN.

A SA is just a SYN with an ACK. In simultaneous opens, the ACK for each
SYN comes alone. In that case, whether the ACK of the SYN (which, in
simultaneous open is just an ACK) could include the option and data if
it is sent after the other side's SYN is received. I.e., depending on
how the SYNs cross, the handshake might succeed or might not.

If confirming the option is critical, you need to handle this case. As
noted above, it might not be critical (or even necessary).

|> - - can you explain why you use a bit-field for the TCP option flag,
|> rather than just using a 2-byte option? (i.e., KIND, length)
| My hope was that by defining a flags option like this, future options
| that require only to signal their presence in a SYN could save space.

That might be a useful to document as a separate issue, since it's
orthogonal to this option. However, you'd need more rules, like the fact
that the responder needs to clear (or truncate) all bits it doesn't
understand or doesn't agree to.

It'd be useful to develop this more fully and get WG feedback on it
separately, IMO.

It's not always as efficient as it appears, FWIW: it trades efficiency
when many flags are set for inefficiency when only recent flags are
defined. E.g., the 25th such flag pays an extra 3-byte penalty when no
other flags are used.
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla -


tcpm mailing list