Subject: [tcpm] An even better way of extending TCP options on a SYN?

From: Bob Briscoe <[email-masked]>
Date: Mon, 21 Jul 2014 15:12:25 +0100

Chairs, Joe,

This will come as a surprise to everyone.

Overnight, I believe I thought up a much better way of extending the 
option space on a SYN. So I rushed to write it up before the TCPM 
meeting. I have just posted it as:

"Extended TCP Option Space in the Payload of an Alternative SYN"
<http://www.ietf.org/id/draft-briscoe-tcpm-syn-op-sis-00.txt>

I will still talk about the joint draft between Joe & I in the 
meeting - in a few minutes, but I may also mention this new one (if time).

Bob

________________________________________________________________
Bob Briscoe,                                                  BT

---

From: Joe Touch <[email-masked]>
Date: Mon, 21 Jul 2014 08:35:38 -0700

Hi, Bob,

This is the same as SYN-EOS DS with these three changes:

	1) instead of the two SYNs working together, SYN-C is
	self-contained

	2) the option is after the payload rather than before

	3) use of a magic number to detect rewriting

On these points:

#1 - DS SYNs already basically do this
	
	PRO of this solution:
		no need to wait for SYN-D if SYN-C arrives first

	CON of this solution:
		connections to upgraded servers have the same
		overhead for client and server as legacy in EOS-DS:
			client needs to keep track of two connections
			and RST one in process

			server needs to open two connections
			all the time, just to kill one off

	I don't see the PRO worth the CON, but that's me

#2 - seems like unnecessary complexity

	This just complicates option processing - remember
	that there are other options that process options,
	such as TCP-AO, and having the space be discontinuous
	begs how it is handled in cases like AO with no
	option coverage (for NAT traversal)

#3 - insufficient vs. a true checksum

	I don't think a checksum needs to be incredibly strong,
	but I also don't think a magic number is a sufficient substitute

So I don't think this is better, but that's me...

Joe

On 7/21/2014 7:12 AM, Bob Briscoe wrote:
> I will still talk about the joint draft between Joe & I in the meeting -
> in a few minutes, but I may also mention this new one (if time).
>
>
> Bob
>
>
>
>

---

From: Bob Briscoe <[email-masked]>
Date: Mon, 21 Jul 2014 20:24:06 +0100

Joe,

>                 no need to wait for SYN-D if SYN-C arrives first

Main PRO is no need for fate sharing (if the 2 SYNs end up at 
different servers, or crossing different paths, it doesn't matter, 
'cos you only use one or the other, so each has to be self-contained.

>                         client needs to keep track of two connections

You will probably prefer the alternative solution in the appendix. 
Did you read this?

>                         all the time, just to kill one off

Again, the alternative solution allows the upgraded server not to 
have to open the second connection.

You might wonder why I put the solution that solves these problems in 
the appendix and not in the body. I chose the one for the body based 
on near-perfect middlebox traversal, 'cos I put function above 
non-functional issues like overhead/performance. Others may have 
different priorities - which is why I documented both solutions.

>         I don't see the PRO worth the CON, but that's me

Solving the fate sharing problem with DS is the big win. And the new 
one is far simpler.

>         option coverage (for NAT traversal)

Surely it's no problem to marshall the options and the payload out of 
the packet into two separate structures (in memory) before working 
through the options and applying them to the remaining payload? It's 
only the same sort of operation as a pseudoheader.

>         but I also don't think a magic number is a sufficient substitute

The magic number isn't to protect against re-writing. It's so an 
upgraded server can distinguish an upgraded SYN.

Again, you'll probably prefer the alt solution in the appendix that 
does this the conventional way with a visible TCP option, rather than 
a hidden one.

Bob

---

From: Joe Touch <[email-masked]>
Date: Mon, 21 Jul 2014 13:00:08 -0700

On 7/21/2014 12:24 PM, Bob Briscoe wrote:
> Main PRO is no need for fate sharing (if the 2 SYNs end up at different
> servers, or crossing different paths, it doesn't matter, 'cos you only
> use one or the other, so each has to be self-contained.

Yes, it avoids fate-sharing problems.
> You will probably prefer the alternative solution in the appendix. Did
> you read this?

I did, but it's much messier and I don't think it is better.

FWIW, the client overhead statement above isn't affected; instead of 
sending a RST, it just interprets the SYN/ACK-L as a RST. I don't like 
interpreting a segment as something it isn't; IMO, a RST should have 
been sent.

> Again, the alternative solution allows the upgraded server not to have
> to open the second connection.

It depends on what you call "open"; the upgraded server still needs to 
process both incoming SYNs and respond to them both. Even without 
allocating extra memory, that's a different amount of work than silently 
keeping the OOB supplement.

> the appendix and not in the body. I chose the one for the body based on
> near-perfect middlebox traversal,'cos I put function above
> Solving the fate sharing problem with DS is the big win. And the new one
> is far simpler.

It's nearly exactly the same, AFAICT - except for fate sharing.

IMO, this can be a fix of SYN-EOS DS rather than a separate approach, 
but it's your call.

> through the options and applying them to the remaining payload?

That's a copy operation that slows things down, and AFAICT serves no 
useful purpose.

 > It's

Yes, but that's entrenched in TCP and UDP processing; you're adding a 
new one.

> upgraded server can distinguish an upgraded SYN.

Why is that any different than the option type? I don't see the benefit.

> Again, you'll probably prefer the alt solution in the appendix that does
> this the conventional way with a visible TCP option, rather than a
> hidden one.
>
>
> Bob
>
>

---

From: Bob Briscoe <[email-masked]>
Date: Mon, 21 Jul 2014 22:01:09 +0100

>I did, but it's much messier and I don't think it is better.

I don't think you can have read it. It is cleaner, not messier, ...

...because the server can explicitly know the SYN-L is from an 
upgraded client, so it can explicitly say it knows this, and not have 
to open connection state.

Then the client explicitly knows that the server knows.

In the other solution, there's more guessing and timeouts (but its 
middlebox traveral is likely to be very comprehensive - maybe 100%).

>sending a RST, it just interprets the SYN/ACK-L as a RST. I don't 
>like interpreting a segment as something it isn't; IMO, a RST should 
>have been sent.

That's a good idea. I'll change it so the server sends RST instead of 
SYN/ACK-L.
And I'll ACK you.

(I obviously didn't think too hard about this part - I've just 
realised I didn't even define the SYN/ACK-L segment. Now I don't have to.)

>It depends on what you call "open"; the upgraded server still needs 
>to process both incoming SYNs and respond to them both. Even without 
>allocating extra memory, that's a different amount of work than 
>silently keeping the OOB supplement.

No it's not. It's a straight discard of that SYN, against one 'if' statement:
         if (SYN-OP-SIS-supported && incoming SYN-L flag) discard

>IMO, this can be a fix of SYN-EOS DS rather than a separate 
>approach, but it's your call.

THere is a huge amount more complexity in DS (& OOB), because of the 
attempt to tie together two segments. Treating them as alternatives 
cuts through a load of crap.

>That's a copy operation that slows things down, and AFAICT serves no 

...other than proxy traversal.

>Yes, but that's entrenched in TCP and UDP processing; you're adding a new one.
>

The headers of /all/ segments contain no hint that anything different 
is happening.

Bob

---

From: Joe Touch <[email-masked]>
Date: Mon, 21 Jul 2014 14:21:50 -0700

> I don't think you can have read it. It is cleaner, not messier, ...

I consider acting on a SYN/ACK-L as if it were a RST messier.

> ...because the server can explicitly know the SYN-L is from an upgraded
> client, so it can explicitly say it knows this, and not have to open
> connection state.

SYN-EOS DS already knows that too. I didn't understand why the 
corresponding SYN in the main body didn't have the option.

> Then the client explicitly knows that the server knows.

It only knows when the other connection succeeds or gets a RST (or 
SYN/ACK-L) back. Until then, it doesn't know what kind of server it's 
dealing with.

> middlebox traveral is likely to be very comprehensive - maybe 100%).

Yeah, but it a trivial difference; as I said, it's basically what is 
already in SYN-EOS DS, so I had been assuming it as any dual-SYN solution.

> That's a good idea. I'll change it so the server sends RST instead of

But then you're basically just back to SYN-EOS DS except that the SYNs 
are mutually exclusive.

A server still may need to cache the SYN-L because it can't know that 
the upgraded SYN will make it through the middlebox (it could have 
blocked it because it's on another port, or sent it somewhere else).

I.e., you still have the endpoint fate-sharing problem here.

> (I obviously didn't think too hard about this part - I've just realised
> I didn't even define the SYN/ACK-L segment. Now I don't have to.)
>
>

You can't just jump to that conclusion; what happens if the other SYN is 
blocked or went to a different endpoint (that might not support SYN-OP-SIS)?

> attempt to tie together two segments. Treating them as alternatives cuts
> through a load of crap.

You still need to tie the segments together or you might end up never 
connecting in some cases (e.g., when a middlebox allows the legacy 
version through but scrambles the upgraded version).

So sure, we can easily put the one new idea here in the other doc - one 
that, FWIW, we did consider - that the options are mutually exclusive, 
not merged.

I.e.: DS:
	legacy uses only SYN-D options.
	upgraded uses only SYN-C options.

OOB:
	legacy uses only SYN options.
	upgraded uses only OOB options.

In both cases, you want the supplement to be a strict superset of the 
options in the legacy case.

> ...other than proxy traversal.

I don't see it helping any more than putting the options at the head. 
What am I missing? I didn't check whether you lie about the TCP segment 
size, but if you do a server might be correct in truncating those 
options off the end.

> The headers of /all/ segments contain no hint that anything different is
> happening.

Sure they do - the magic number. You're just creating a new field that 
you hope nobody steps on, rather than using one that's already defined 
for that purpose.

Joe

>>>>> meeting -

---

From: Bob Briscoe <[email-masked]>
Date: Wed, 23 Jul 2014 05:42:42 +0100

Joe,

>corresponding SYN in the main body didn't have the option.

The main solution is designed to work without any new TCP options in 
the header before the payload. Then it will (naturally) work if 
middleboxes strip options. And it will work through split connections 
that don't pass options on.

>SYN/ACK-L) back. Until then, it doesn't know what kind of server 
>it's dealing with.

No. In the alternative solution (appendix) the client knows (that the 
server knows that the client is upgraded) immediately the response 
returns, because the protocol requires the response to the SYN-L from 
an upgraded server to be different to that from a legacy server.

That's why there's a wait shown in the main solution, but not in the 
alternative solution.

>But then you're basically just back to SYN-EOS DS except that the 
>SYNs are mutually exclusive.
>
>A server still may need to cache the SYN-L because it can't know 
>that the upgraded SYN will make it through the middlebox (it could 
>have blocked it because it's on another port, or sent it somewhere else).
>

Nope. There is now no assumption that the two upgraded servers are 
even the same physical server. They have the same IP address & port, 
but they are serving two completely independent connections from 
different source ports.

>You can't just jump to that conclusion; what happens if the other 
>SYN is blocked or went to a different endpoint (that might not 
>support SYN-OP-SIS)?

See above. The design is different from SYN-EOS DS: servers don't 
know or care about other connections.

The client is the only node responsible for coordinating its activity 
on the two connections. If one connection doesn't work, the client 
uses the other.

>You still need to tie the segments together or you might end up 
>never connecting in some cases (e.g., when a middlebox allows the 
>legacy version through but scrambles the upgraded version).

I've added text for the fall-back if neither connection returns 
anything useful (draft...01 just submitted).

>So sure, we can easily put the one new idea here in the other doc - 
>one that, FWIW, we did consider - that the options are mutually 
>exclusive, not merged.
>
>I.e.: DS:
>In both cases, you want the supplement to be a strict superset of 
>the options in the legacy case.

I'm currently updating it independently. I don't particularly want to 
maintain DS any more. I think 'SynOpSis' is wholly superior (altho I 
admit I haven't done a systematic comparison of every case).

SynOpSis could replace DS in the SYN-EOS doc. But currently I don't 
see enough common features that argue for these two approaches being 
in the same doc. It would make it more confusing than useful to try 
to lever them into the same doc. But I'm prepared to be convinced otherwise.

>>>That's a copy operation that slows things down, and AFAICT serves no

The rules on processing order in both cases (see draft) are arranged 
to allow some of the extra options in the payload to be processed 
before regular header options, if required. So, even if the extra 
options were at the front of the payload, you would not be able to 
just run on from the end of the regular TCP options into those in the payload.

Anyway, to process blocks of data in memory in a certain sequence 
doesn't require them to be copied around in memory. They only have to 
referenced (pointed to) in order.

>I don't see it helping any more than putting the options at the 
>head. What am I missing? I didn't check whether you lie about the 
>TCP segment size, but if you do a server might be correct in 
>truncating those options off the end.

No lying.

Middleboxes that inspect app-layer headers expect them to be at the 
front of the payload.

>>>Yes, but that's entrenched in TCP and UDP processing; you're adding a

For a good reason.

>Sure they do - the magic number. You're just creating a new field 
>that you hope nobody steps on, rather than using one that's already 
>defined for that purpose.

I think you need to look again at the draft. The SynOpSis option is 
in the payload (at least in the spec in the main body). I.e. the 
option that says there are options in the payload is itself in the payload.

I'm about to post a revision -01, which has some text about the 
probability of a clash with this magic number.

Bob