Subject: [tsvwg] Size of OCS checksum, and should OCS be optional?

From: Derek Fawcus <[email-masked]>
Date: Sat, 3 Mar 2018 14:04:56 +0000

On Fri, Jan 19, 2018 at 07:18:41PM -0800, [email-masked] wrote:
> 
> A New Internet-Draft is available from the on-line Internet-Drafts directories.
> This draft is a work item of the Transport Area Working Group WG of the IETF.

Two of the points raised before adoption were:
  a) if the OCS field should be optional
  b) if the checksum over the otions (which OCS provides) should be 16 bits
see this thread: https://www.ietf.org/mail-archive/web/tsvwg/current/msg14926.html

This effectively got deferred until after adoption.

I was proposing that the current OCS option be discarded, and replaced with
a fixed length 16 bit checksum field at the start of the surplus area.
This would then use the usual internet checksum algorithm, such that the
whole of the surplus area, including this checksum, should sum to zero.
I also suggested how this would work when the FRAG mechanism was in use.

The main reason for this was simplicity for implementors, in that they'd not
have to write and verify a new checksum routine, but could use their
existing algorithm.  It would also be simpler to implement in that the
checksum would be in a known fixed location, hence verification would be
simpler.

In theory, if one did not wish to use a checksum, one could store the
0x0000 value there, and always use 0xffff to represent a 1's complement
value of zero.

The cost of the above is that one always consumes 2 bytes from the surplus
area to represent this, even if one does not wish to checksum the options
area.  Whereas if one does wish to checksum the options, it consumes the
same space as the current scheme.  I'd argue that for robustness reasons,
one would almost always wish to checksum the options area.  I'd suggest
that the above scheme is actually simpler than the current one.

So I am again proposing:

1) Remove the OCS option.
2) Add a fixed length 16 bit checksum field at a known location
   (The start of the surplus area).
3) Potentially allow one to store 0x0000 in that field to indicate the
   options themselves are not protected by a checksum.

How do others view this?

DF

---

From: Derek Fawcus <[email-masked]>
Date: Sat, 3 Mar 2018 14:18:05 +0000

> I also suggested how this would work when the FRAG mechanism was in use.

That is a typo, it should have said LITE header, not FRAG mechanism.

DF

---

From: Tom Jones <[email-masked]>
Date: Sat, 3 Mar 2018 16:25:28 +0000

Hi Derek,

I have an implementation for FreeBSD (and 3 others to support that work)

comments inline

On Sat, Mar 03, 2018 at 02:04:56PM +0000, Derek Fawcus wrote:
> existing algorithm.  

The existing 16 bit routines I have looked at are tuned assembly
available for all platforms. 

The draft suggests "folding over" the result of a 16 bit calculation
which is probably a similar amount of code to writing an 8 bit sum.

> It would also be simpler to implement in that the checksum would be in
> a known fixed location, hence verification would be simpler.
> 

I am against allowing 0 checksums for the option space.  

I see the option space overhead as always being 3 bytes (OCS+EOL) and
most of the time being 4 bytes (OCS+NOP+EOL).

>    (The start of the surplus area).

I am happy with this suggestion. 

I would prefer using the already implemented 16 bit checksums, less code
is better.

>    options themselves are not protected by a checksum.

I do not think a 0 checksum a good idea.

- [tj]

---

From: Derek Fawcus <[email-masked]>
Date: Sat, 3 Mar 2018 16:40:02 +0000

> I am against allowing 0 checksums for the option space.  

I'd tend to agree, but had to mention it in case someone else believes
there is a sensible case for sending packets sans OCS in the current
scheme.

> I would prefer using the already implemented 16 bit checksums, less code

I had in mind simply using the well known 1's complement of
the 1's complement sum of the data; as used in the IPv4 header, UDP header,
TCP header etc.

DF

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 08:53:15 -0800

HI, Derek,

As I mentioned, there are queued updates not yet applied to the currently posted version. They will be incorporated in the next release.

Joe

> On Mar 3, 2018, at 6:04 AM, Derek Fawcus <[email-masked]> wrote:
>

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 08:54:21 -0800

Hi, all,

> On Mar 3, 2018, at 8:25 AM, Tom Jones <[email-masked]> wrote:
...
> which is probably a similar amount of code to writing an 8 bit sum.

It is the following operation:

	// sum here is the 16 bit value
	sum = ((sum && 0xff00) >> 8) + (sum && 0x00ff);
	// first foldover, but it might have a carry, so do it one more time
	sum = ((sum && 0xff00) >> 8) + (sum && 0x00ff);
	// second foldover is done

It should compile to roughly an additional 6 opcodes that in 2-way parallelism could be computed in 4 instruction cycles.

(I can add that to the doc)

> I am against allowing 0 checksums for the option space.  

At best, the default should be that the checksum is used.

> I am happy with this suggestion. 

The use of a fixed location is just the typical trade-off between space and complexity. Using an optional checksum allows its removal to save space.
I don’t have a strong position as to how to pick between the two.

The primary reason for the foldover, FWIW, was to save space (by adding a few opcodes and weakening the sum).

> I would prefer using the already implemented 16 bit checksums, less code

Others raised concerns about using the existing IP checksum, but it would have the benefit of potential support using existing accelerator hardware.

> I do not think a 0 checksum a good idea.

IMO, the sum needs to be optional, regardless of mechanism.

Even with IPv6 we see many places where UDP checksums are disabled (largely tunnel uses). Not having that potential here would be problematic for some intended users.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 09:00:13 -0800

> On Mar 3, 2018, at 8:40 AM, Derek Fawcus <[email-masked]> wrote:
> 

OCS as described in the current code *is* that checksum, except as follows:

1) it wasn’t inverted after the end of the sum
2) it was folded over to help the OCS option maintain 16-bit alignment, and because the additional power of the 16-bit value is not needed

All of that is “post processing”; even existing code or hardware can be used by simply inverting the result and then folding the result over.

Inverting the *final* result is required if the OCS field is required but its use is optional.

Here’s how it would work with existing code:
	ics = internetsum(data)
	ics = ~ics
	ics = foldover(ics) 	// see previous email for code)
	ics = ~ics

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 3 Mar 2018 12:52:58 -0800

On Mar 3, 2018 8:54 AM, "Joe Touch" <[email-masked]> wrote:

Hi, all,

...

It should compile to roughly an additional 6 opcodes that in 2-way
parallelism could be computed in 4 instruction cycles.

So I am again proposing:

The use of a fixed location is just the typical trade-off between space and
complexity. Using an optional checksum allows its removal to save space.
I don’t have a strong position as to how to pick between the two.

The primary reason for the foldover, FWIW, was to save space (by adding a
few opcodes and weakening the sum).

Others raised concerns about using the existing IP checksum, but it would
have the benefit of potential support using existing accelerator hardware.

The benefit is more likely from using optimized routines to do checksum
that HW offload. Checksum offload probably doesn't help to compute the
options checksum, but it will need to be considered. For instance, if NIC
returns checksum over IP packet in rx, the host will need to compute csum
over options to verify udp csum regardless of whether csum is enabled in
options.

Tom

Even with IPv6 we see many places where UDP checksums are disabled (largely
tunnel uses). Not having that potential here would be problematic for some
intended users.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 3 Mar 2018 12:58:36 -0800

Hi, all,

...

So I am again proposing:

Joe,

Zero UDPv6 checksum can only be used in tunneling if conditions of RFC6935
and RFC6936 are met. The requirements to use this or actually fairly
strict, and it is not the intent that this is the default for tunneling.

Tom

Joe

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 13:04:59 -0800

On 3/3/2018 12:58 PM, Tom Herbert wrote:
> Zero UDPv6 checksum can only be used in tunneling if conditions of
> RFC6935 and RFC6936 are met. The requirements to use this or actually
> fairly strict, and it is not the intent that this is the default for
> tunneling.

For tunneling anything based on IP or UDP - even if encapsulated via an
intermediary (e.g., GRE), it would be fine according to those
conditions, and those are the bulk of such tunnels.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 13:07:33 -0800

On 3/3/2018 12:52 PM, Tom Herbert wrote:
> ...
>
> The benefit is more likely from using optimized routines to do
> checksum that HW offload.

There is optimized for many different checksums already, including the
ones proposed for the alternate checksum. However, there's no benefit
regarding the one proposed for OCS - it's already ones complement with
minor post-processing.

> Checksum offload probably doesn't help to compute the options
> checksum, but it will need to be considered. For instance, if NIC
> returns checksum over IP packet in rx, the host will need to compute
> csum over options to verify udp csum regardless of whether csum is
> enabled in options.

The NIC shouldn't do a checksum over the IP packet anyway - the UDP
checksum doesn't include the whole IP header.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 3 Mar 2018 13:13:49 -0800

On Mar 3, 2018 1:05 PM, "Joe Touch" <[email-masked]> wrote:

Look at RFC8086 (GRE over UDP) section 6.2.

Tom

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 3 Mar 2018 13:21:46 -0800

On Mar 3, 2018 1:07 PM, "Joe Touch" <[email-masked]> wrote:

Not to the extent that IP checksum has been optimized.

Joe,

That's exactly what we want NICs to do. The alternative is the NICs does
DPI to find UDP or TCP or GRE checksums (legacy method). If they do that,
they'll still miss them if there are extension headers or encapsulation.
When we get full checksum, host can easily pull it up as headers are
parsed. Any number of checksums in a packet can be verified. This technique
is pretty well established now.

Tom

Joe

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 13:57:28 -0800

On 3/3/2018 1:21 PM, Tom Herbert wrote:
> That's exactly what we want NICs to do.

Some NICs already do enough DPI to jump in at the IP payload. When the
payload isn't something easily "undone" later, the work is just wasted
and re-done in the "slow path" in software.

However, this is all somewhat moot anyway.

First, for OCS, we're already talking about using the IP checksum with
minor post processing (a one's complement 8-bit sum is the same as a
ones-complement 16-bit sum folded over, just as the 16-bit is the 32-bit
folded over).

Second, the minor differences would need to be accommodated in either
hardware or software to support these options anyway.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 14:05:37 -0800

On 3/3/2018 1:13 PM, Tom Herbert wrote:
>
>
> On Mar 3, 2018 1:05 PM, "Joe Touch" <[email-masked]
> <mailto:[email-masked]>> wrote:
>
>
>

That section already points out the permission to turn those checksums
off (which is why we want to support it as well).

And, AFAIR, that section is written to carefully advise against turning
off that checksum except in what turns out to be the most common case -
using GRE in UDP as an IP or Ethernet tunnel. In that case, the tunneled
traffic does not need any particular new protection, especially when the
GRE checksum is used instead.

So again, there's no point in UDP options being more strict than the
rest of UDP here. In both cases, the use of the checksum is recommended
by default (now anyway) and in both cases both should be capable of
being disabled if desired.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 3 Mar 2018 14:15:09 -0800

On Mar 3, 2018 2:05 PM, "Joe Touch" <[email-masked]> wrote:

That section already points out the permission to turn those checksums off
(which is why we want to support it as well).

And, AFAIR, that section is written to carefully advise against turning off
that checksum except in what turns out to be the most common case - using
GRE in UDP as an IP or Ethernet tunnel. In that case, the tunneled traffic
does not need any particular new protection, especially when the GRE
checksum is used instead.

The concern isn't so much protecting the tunneled packet, it's the fact
that IPv6 does not have a header checksum. If UDP checksum is zero there is
nothing in IP that can detect misdelivery due to corrupted destination
address. In any case, UDP checksum would be independent of the options
checksum as you point out.

Tom

So again, there's no point in UDP options being more strict than the rest
of UDP here. In both cases, the use of the checksum is recommended by
default (now anyway) and in both cases both should be capable of being
disabled if desired.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 14:21:12 -0800

On 3/3/2018 2:15 PM, Tom Herbert wrote:
> The concern isn't so much protecting the tunneled packet, it's the
> fact that IPv6 does not have a header checksum. If UDP checksum is
> zero there is nothing in IP that can detect misdelivery due to
> corrupted destination address. In any case, UDP checksum would be
> independent of the options checksum as you point out.
>
> Tom

But that's the case for existing IP over UDP tunnels, which was actually
the use case for disabling UDP checksums in the first place.

E.g., consider IPv6 or IPv4 traffic:
        app + UDP w/checksum + IPv4 w/checksum
        app + UDP w/checksum (recommended) + IPv6 (no CS)

The presumption is that the IPv6 either travels over a link that has
some sort of protection (or rare errors) or that the transport will help
prevent a problem even if it is misdelivered.

Put either of those inside UDP' + IPv6' and you're in the case where
UDP' is allowed to disable the checksum because the inner UDP already
has it.

Replace UDP' with UDP'+UDPhdr' and that's why (and when) it's similarly
OK to leave off the checksum.

I.e., *for the same places where UDP can turn of its checksum, so can
UDP-opts* (and for the same reasons - performance, largely when other
layers are already trusted to be configured to provide the needed
protection).

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 3 Mar 2018 14:41:06 -0800

On Mar 3, 2018 2:21 PM, "Joe Touch" <[email-masked]> wrote:

Joe, as I said, the requirements for using a UDPv6 checksum are listed in
great detail in RFC6936. I don't see a reason to redefine those here.

My bigger concern is still using a TLV to hold an optional checksum. If the
TLV type is corrupted then receiver would not see checksum to verify it and
hence the mechanism failed in it's primary purpose. We have a similar
problem in GUE. The answer there was that GUE is likely used with tight
coordination so it can be agreed if presence of the checksum is required.
If the protocol is used between to random nodes in Internet this is a
bigger concern.

Tom

---

From: Joe Touch <[email-masked]>
Date: Sat, 3 Mar 2018 16:30:10 -0800

> On Mar 3, 2018, at 2:41 PM, Tom Herbert <[email-masked]> wrote:
> ...
> 
> Joe, as I said, the requirements for using a UDPv6 checksum are listed in great detail in RFC6936. I don't see a reason to redefine those here.

Agreed - the point is that checksums are optional there, even with caveats. We don’t need to revisit the caveats, but i do think that those other discussions are reasons why we need OCS to remain optional.

> My bigger concern is still using a TLV to hold an optional checksum. If the TLV type is corrupted then receiver would not see checksum to verify it and hence the mechanism failed in it's primary purpose. We have a similar problem in GUE. The answer there was that GUE is likely used with tight coordination so it can be agreed if presence of the checksum is required. If the protocol is used between to random nodes in Internet this is a bigger concern.

I’m not sure I agree with your concerns; finding UDP options already relies on an uncorrupted IP header and UDP header that would not be protected if the primary UDP checksum were off. Further, if we can’t disable OCS then we’d be required to do twice the work when using ACS.

As with all TLV vs fixed header alternatives, there’s the issue of required vs. optional space. Having TLV allows the space to be saved when OCS isn’t present, and that was a concern when we discussed this issue before (as a group via email).

Finally, there’s the impact on LITE+FRAG and the way in which reassembly can preserve options. That will require deeper consideration to determine if it is possible and with what impact.

The big question, IMO, is what is the gain. Given these options are already “floating”, it’s hard to see why a “fixed header” is important to consider, IMO, but it’d be useful to hear what others have to say too, certainly.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 07:33:31 -0800

Derek,

Back to the origin of the recent thread...

> On 3/3/2018 6:04 AM, Derek Fawcus wrote:
That link points to the touch-options-05 announcement. There were many updates since then (06..09); it was 09 that was adopted and then started the tsv-options-00 sequence.

Can you provide a more specific pointer?

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 08:14:59 -0800

On Sat, Mar 3, 2018 at 4:30 PM, Joe Touch <[email-masked]> wrote:
> Agreed - the point is that checksums are optional there, even with caveats.
> We don’t need to revisit the caveats, but i do think that those other
> discussions are reasons why we need OCS to remain optional.
>
>
> coordination so it can be agreed if presence of the checksum is required. If
> the protocol is used between to random nodes in Internet this is a bigger
> concern.
>
>
> I’m not sure I agree with your concerns; finding UDP options already relies
> on an uncorrupted IP header and UDP header that would not be protected if
> the primary UDP checksum were off. Further, if we can’t disable OCS then
> we’d be required to do twice the work when using ACS.
>
Joe,

I think the point of having a checksum in the options is that the
options can be validated as being correct independent of anything
else. For instance, there is no need to assume that the packets is
verified by a checksum or CRC at a lower layer. UDP checksums are
optional in IPv4, and in IPv6 there's no checksum in the IPv6 header
so the header could be quite corrupted and UDP options still are
found. Corruption in the header could also include the IP length field
which means the presence option space is incorrectly inferred. If
checksum were required this could be used to validate that the options
are actually UDP options (like a magic number essentially)

> As with all TLV vs fixed header alternatives, there’s the issue of required
> vs. optional space. Having TLV allows the space to be saved when OCS isn’t
> present, and that was a concern when we discussed this issue before (as a
> group via email).
>
You may want to work out the probabilities of an undetected data
corruption in the options. For instance, if someone is using a 32 bit
CRC then they would expect a very low probability of not detecting a
corruption (something like 1/2^32). If the CRC is in an optional TLV
such that corruption of the type field will causes the CRC to be
missed, then probability of missing corruption of options is higher.
There's no reason that the type field is any less susceptible to
corruption that any other field, so establishing the probability is
missing a corruption in this case should be quantifiable (it is
probably be related to number of bytes in options).

Tom

> Finally, there’s the impact on LITE+FRAG and the way in which reassembly can
> preserve options. That will require deeper consideration to determine if it
> is possible and with what impact.
>
> The big question, IMO, is what is the gain. Given these options are already
> “floating”, it’s hard to see why a “fixed header” is important to consider,
> IMO, but it’d be useful to hear what others have to say too, certainly.
>
> Joe
>
>

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 16:30:13 +0000

On Sat, Mar 03, 2018 at 04:30:10PM -0800, Joe Touch wrote:
> > My bigger concern is still using a TLV to hold an optional checksum.

That is actually my largest concern, and why I'd prefer a fixed header,
since it allows the whole verification to use preexisting logic,
rather than custom logic.

I'd like to be able to do a simple scan over the options area and validate
it, without having to parse the TLVs.  Hence I could use a two pass approach
to this if it made sense, validating without parsing.

As an example, compare the two routines at the end of this message.
For simplicity, I assume a machine which can perform unaligned access;
I've also made the TLV form deal a byte at a time, doing 16 bits at
a time would be more complex.  I've also ignored the LITE header issues,
as the impact of it would be the similar for both routines.

Of the two, the first (validate_options_fix) could simply be replaced
with a call to pre-existing logic, but it looks as if validate_options_tlv
has to be custom coded.  Or maybe there is a simpler way to code the _tlv
form which I've missed?

A futher question came up when coding this:  should the OSC scheme terminate
when it sees the EOL option?  i.e. Does its checksum exclude any bytes
after EOL?  If so, then the TLV version becomes more complex.
Certainly I'm assuming with my fixed proposal that the checksum would include
such bytes after the EOL, but within the surplus.

> As with all TLV vs fixed header alternatives, there’s the issue of required vs. optional space. Having TLV allows the space to be saved when OCS isn’t present, and that was a concern when we discus…

I don't recall that being a concern, but then memory is fragile.
Either way I don't see those 2 extra bytes as being significant,
and as Tom points out, it may even be 2 fixed vs 3/4 variable.

> Finally, there’s the impact on LITE+FRAG and the way in which reassembly can preserve options.
> That will require deeper consideration to determine if it is possible and with what impact.

I view that portion as a trivial extension.  One does some initial
set up at the start of the routine, then the rest of the loop is
the same.

> The big question, IMO, is what is the gain.

Hopefully the two code examples below highlight that.

DF

bool validate_options_fix (uint8_t *bp, unsigned len)
{
        uint32_t chk = 0;
        uint16_t *wp = (uint16_t *)bp;

        if (len & 1) bp[len] = 0; /* Cheat - assume safe to write */
        len /= 2;

        while (len--)
                chk += *wp++;

        /* fold over result */

        return (chk == 0) || (chk == 0xffff);
}

#define OPT_OSC 2
bool validate_options_tlv (uint8_t *bp, unsigned len)
{
        uint16_t chk = 0;
        uint8_t osc;

        while (len--) {
                if (*bp == OPT_OCS) {
                        if (len < 1)
                                return false;
                        chk += OPT_OCS;
                        --len, ++bp;
                        osc = *bp++;
                        continue;
                }

                chk += *bp++;
        }

        /* fold over result */

        return osc == chk;
}

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 08:31:16 -0800

> On Mar 4, 2018, at 8:14 AM, Tom Herbert <[email-masked]> wrote:
….
> else.

That property is not possible for UDP options, nor for UDP in general. If the IPv6 header is corrupted, its length may be wrong and thus the UDP header. If the UDP header is wrong (directly or by IP header error), then the location (and thus content) of the UDP options will be wrong. It thus isn’t important to ensure that the UDP options themselves have some sort of “context independent” property that they already inherently lack.

> For instance, there is no need to assume that the packets is
> found.

IPv6 is basically a TLV chain itself.

> Corruption in the header could also include the IP length field
> which means the presence option space is incorrectly inferred.

Or options are cut off prematurely as well.

> If

Agreed - that’s they’re SHOULD use (and default on), but (for exactly the same reasons) some users don’t want the cost of doing these checks just for UDP checksums when they’re disabled at the IP (v6) and UDP levels.

But we already allow IP(v6) and UDP to turn this off and the same exact reasons apply here.

> probably be related to number of bytes in options).

The probabilities depend on the TLV chains that get you there in the first place too.

However, the primary assumption for OCS is that there is no reason that these options require something beyond what IPv4, UDP, and TCP already use. If you want stronger protections, then you want to use ACS.

And my assumption is that the risk of folding over the OCS to one byte is commensurate with the anticipation that the options are typically smaller than the typical payload. If we don’t think byte alignment or space is an issue, simply don’t fold it over.

Joe

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 16:36:56 +0000

On Sat, Mar 03, 2018 at 04:30:10PM -0800, Joe Touch wrote:
> 
> Further, if we can’t disable OCS then we’d be required to do twice the work when using ACS.

I don't believe that is correct.
ACS protects the actual UDP data payload, whereas OCS protects the options within the surplus.

The draft says:
   The Alternate Checksum (ACS) is a 16-bit CRC of the UDP payload only
   (excluding the IP pseudoheader, UDP header, and UDP options).

So I could well see wanting to have ACS and OCS in use, as they serve different purposes.

DF

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 08:41:33 -0800

> On Mar 4, 2018, at 8:30 AM, Derek Fawcus <[email-masked]> wrote:
> 

The options are in a variable location depending on a field in the UDP header.

That issue is overlooked for ‘fast-path’ IP headers because a very high percent of UDP headers are in a fixed location, but that’s not true for option headers, so the hardware already has a TLV-like complexity.

> it, without having to parse the TLVs.

That doesn’t seem feasible as follows:
	- it will burn space when OCS isn’t used (and yes, this is a concern)
	- it needs space to indicate the start and/or end of OCS coverage
		or we would have to remove LITE
	- we would need to find a new way to incorporate LITE
		notably that involves not needing to recopy the entire LITE
		region after option processing

If you have a proposed solution that preserves all of these and supports the existing properties, please post it.

Until then, AFAICT, we have what we have.

...

> I view that portion as a trivial extension.  

Fragmentation and reassembly is one of the primary use cases - it is key to allowing fragmentation to traverse NATs because UDP-level frag would preserve the info NATs use for rewriting.

LITE+FRAG is a very important development because it is backward compatible without injecting partial payloads to the legacy endpoint.

So yes, any solution that replaces TLV with a fixed header would need to support that.

Joe

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 16:43:10 +0000

Joe,

Not easily.

I suffered a catastrophic system failure on the machine used for mailing list
participation, and lost my local archive.

So I've have to search the above email archive to find it.

I vaguely recall you stating in a message that you'd prefer to discuss
these topics after adoption.

DF

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 08:43:29 -0800

> On Mar 4, 2018, at 8:36 AM, Derek Fawcus <[email-masked]> wrote:
> 

Sorry - mistyped. ACS won’t relieve the work of doing the UDP checksum if that’s done for the entire packet.

If we want something stronger than OCS, then that would have the same property as ACS/UDP-cs interaction this way.

Joe

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 16:54:37 +0000

On Sun, Mar 04, 2018 at 08:41:33AM -0800, Joe Touch wrote:
> That issue is overlooked for ‘fast-path’ IP headers because a very high percent
> of UDP headers are in a fixed location, but that’s not true for option headers,
> so the hardware already has a TLV-like complexity.

Who said I was worried about hardware implementation?
I'm interested in high speed s/w implementations.

So the cost of finding the start of the surplus is trivial, as all it
invoves is reading from a fixed location in the UDP header.  c.f. TCP options.

> 	- it will burn space when OCS isn’t used (and yes, this is a concern)

That is for people to weigh up.

> 		or we would have to remove LITE

Nope.  Use the existing swap scheme, and have the checksum cover from the
start of the LITE header in figure 10 through to the end of the surplus
area.

> If you have a proposed solution that preserves all of these and supports the existing properties, please post it.

That was mentioned in the discussion on draft 5, one uses a fixed header at the
start of the surplus, the first two bytes being the checksum field.

Then for the LITE case, one uses the same 'swap some bytes' scheme you already
describe, but rather than swap 4 bytes, one swaps 6 bytes.

> > I view that portion as a trivial extension.  

I mean a trivial extension to the code I posted.  It would simply work with you existing swap scheme.

> Fragmentation and reassembly is one of the primary use cases - it is key to allowing fragmentation
> to traverse NATs because UDP-level frag would preserve the info NATs use for rewriting.
> 

I believe it would, as the only thing being replaced is the OCS option, the rest of
the TLV scheme for the options would be preserved.

DF

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 08:59:15 -0800

> That property is not possible for UDP options, nor for UDP in general. If the IPv6 header is corrupted, its length may be wrong and thus the UDP header. If the UDP header is wrong (directly or by I…
Right, so if the length field becomes corrupted, or a sender puts
other random stuff in the surplus area, or a checksum TLV is
corrupted--  then what is the mechanism that a receiver uses to
identify the corruption so that it does not incorrectly process the
bits as UDP options? It seems something like a fixed checksum and/or
magic numbers are needed to be robust.

Tom

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 09:17:51 -0800

Joe,

I don't understand your point about hardware already having "TLV-like
complexity". We know that TLVs are extremely difficult and expensive
to process in a performant hardware data path.The failure of IPv4
options and HBH options in IPv6 demonstrate that.  Can you clarify
exactly what hardware and capabilities you're referring to?

Thanks,
Tom

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 10:01:23 -0800

> 
> On Mar 4, 2018, at 8:43 AM, Derek Fawcus <[email-masked]> wrote:
> 

I recall that too, but I thought y tracking of pending issues indicated we had.

Joe

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 18:01:55 +0000

BTW - The option Kind numbers in some of the diagrams are out of
      sync with those in the table at the start of section 5.

> I mean a trivial extension to the code I posted.  It would simply work with you existing swap scheme.

Below is a more complete verification routine for the scheme I propose,
untested of course, but it should show how what I have in mind would work.

All it does is validate the options in the packet, and covers the LITE
case, hence should also cover the LITE+FRAG case.  I simply delete the
OCS option, add a fixed header for a 16 bit checksum, and keep everything
else the same TLVs and all (except 4 vs 6 bytes for LITE processing).

Note that this assumes the checksum covers the whole surplus area, and
so also includes bytes after a EOL option.

You shoudl also note that all of the extra logic is initial set up
and verification, it then falls in to the common existing checksum
algorithm.

One thing I noticed in coding this is that there is a minimal LITE length
which can be carried, currently 4 bytes, and then 6 bytes in my scheme.
To carry less, the 'swap bytes for LITE' would have to be replaced with
a more complex case handling overlapping ranges,  which I don't view as
worthwhile.  It would however be worth calling this out in the document.

DF

#define OPT_LITE 2
#define OPT_LITE_LEN 4 /* bytes */

/*
 * dp points to start of UDP payload, dlen is UDP payload length.
 * plen is IP payload length.
 * Assumed that dlen vs plen validity already verified.
 */
bool validate_options_chk (uint8_t *dp, uint16_t dlen, uint16_t plen)
{
        uint16_t slen = plen - dlen - 8;
        uint8_t *sp = dp + dlen;
        uint16_t *wp = (uint16_t *)sp;

        if (slen == 0)
                return true; /* No options */
        if (slen < 2)
                return false; /* Too short */
        if (slen & 1) sp[slen++] = 0; /* Cheat - assume safe to write */
        slen /= 2;

        uint32_t chk = *wp++; --slen;
        if (chk == 0) return true; /* Unprotected */

        /* Account for LITE header, skip to remaining options */
        if ((slen > OPT_LITE_LEN / 2) && sp[2] == OPT_LITE && sp[3] == OPT_LITE_LEN) {
                chk += wp[1]; chk += wp[2];

                uint16_t oo = (s[4] * 256) | s[5];
                if (oo < 8 + dlen + 2 + OPT_LITE_LEN) return false;
                if (oo > plen - 2 - OPT_LITE_LEN) return false;

                wp = (uint16_t *)(dp + oo - 8 + (2 + OPT_LITE_LEN));
                slen -= OPT_LITE_LEN / 2;
        }

        /* Everything from here is normal checksum algorithm */
        while (slen--)
                chk += *wp++;

        /* fold over result */

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 10:12:59 -0800

> On Mar 4, 2018, at 9:17 AM, Tom Herbert <[email-masked]> wrote:
> 
> Joe,
> 
> complexity”.

> We know that TLVs are extremely difficult and expensive
> options and HBH options in IPv6 demonstrate that.

Hardware support is only one part of the reason they’re not supported. NAT traversal and cost savings by vendors (i.e., the lack of a compliance process) is also part. It isn’t easy to determine which is the driving factor.

>  Can you clarify
> exactly what hardware and capabilities you're referring to?TCP options already are TLV.

TCP options already are TLV.

As are IPv6 options, which means finding the transport header involves TLV traversal.

I.e., getting *to* the option field involves processing a chain of one or more unprotected TLV fields anyway.

Again, if you expect the checksum and don’t get it (via out of band info), then you would drop the packet as corrupt anyway.

Additionally, as per the other part of this thread, there’s no way to jump right into hardware use of the OCS. We still have the LITE swap to contend with, at a minimum, and that might not be word-aligned as well.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 10:19:15 -0800

Hi, Derek,

> On Mar 4, 2018, at 8:54 AM, Derek Fawcus <[email-masked]> wrote:
> 

I’m not sure how that works.

If the OCS always comes first, when you hit it you stop and compute the checksum.

However, OCS doesn’t “come first” with LITE - LITE comes first.

So we need a fixed field (for the same reason) to always indicate whether LITE is present and the swap needs to happen before the checksum proceeds.

> worthwhile.  It would however be worth calling this out in the document.

So you’re saying at least that the minimum overhead for all options goes from zero bytes (in the current scheme) to 6 (2 for the checksum, 4 for LITE even when it isn’t used). And you have to handle LITE processing or at least checking even when you’re not using it at all.

I don’t see that as forward progress.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 11:10:02 -0800

> On Mar 4, 2018, at 10:50 AM, Derek Fawcus <[email-masked]> wrote:
> 
> On Sun, Mar 04, 2018 at 10:19:15AM -0800, Joe Touch wrote:
> Note I am suggesting to remove the OCS option.

You’re just requiring it as being first, i.e., removing the “O”. The rest is largely the same which is why I’m saying it that way, but agreed that your plan is to make it mandatory. We could call the difference OCS vs MCS (mandatory).

> 
> Have you looked at the code I included?
> Or should I try and express that algorithm in some other fashion?

It would be useful to show headers first, code later. Code changes; header can’t.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 11:29:47 -0800

> You’re just requiring it as being first, i.e., removing the “O”. The rest is largely the same which is why I’m saying it that way, but agreed that your plan is to make it mandatory. We could call t…
I think it's more like that becomes part of a fixed header in the
beginning of the options space. And if you have the checksum there,
then the length of the space should also be there so that the checksum
can be validated without having to parse all the options to find EOL.

Tom

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 11:33:04 -0800

> On Mar 4, 2018, at 11:29 AM, Tom Herbert <[email-masked]> wrote:
> 
> On Sun, Mar 4, 2018 at 11:10 AM, Joe Touch <[email-masked] <mailto:[email-masked]>> wrote:
>> 
>> 

Then you also need to know where the start is too to have enough info for the swap.

That’s 6 bytes and that’s quite a hefty overhead if you don’t want the CS at all. And all the processing you do seems the same either way… you still have to check to see if a swap is needed and whether CS == unused.

That’s the set of problems AFAICT - space is very high and processing doesn’t seem to win much.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 11:46:54 -0800

On Sun, Mar 4, 2018 at 11:33 AM, Joe Touch <[email-masked]> wrote:
> You’re just requiring it as being first, i.e., removing the “O”. The rest is
> largely the same which is why I’m saying it that way, but agreed that your
> plan is to make it mandatory. We could call the difference OCS vs MCS
> (mandatory).
>
> That’s 6 bytes and that’s quite a hefty overhead if you don’t want the CS at
> all. And all the processing you do seems the same either way… you still have
> to check to see if a swap is needed and whether CS == unused.
>
The win is to increase the probability that the UDP options are
correctly interpreted. One potential issue with this proposal is that
it retroactively defines the slack space to have certain semantics.
There may be implementations out there that are now creating non-zero
slack space, and I don't think it's possible to retroactively declare
that those are out of protocol conformance.

Personally, I am much more concerned about a protocol being correct
and robust than saving a couple of bytes of header. IMO there should
be a means to validate that the bits in a slack space are indeed well
formed UDP options with high probability.

Tom
.

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 11:59:09 -0800

> On Mar 4, 2018, at 11:46 AM, Tom Herbert <[email-masked]> wrote:
> 

They are until they’re defined as in. 

Ie UDP is a standard. This doc extends that with a new one. There are no other similar extensions underway and none have already been approved.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 12:22:51 -0800

> They are until they’re defined as in.
?  From section 9 of the draft" :It has always been permissible for
the UDP Length to be inconsistent with the IP transport payload length
[RFC768]"

> Ie UDP is a standard. This doc extends that with a new one. There are no other similar extensions underway and none have already been approved.
What does "approved" mean? If someone is using the slack space for
their own purposes in their network then that is their business. AFAIK
there is no RFC that say they are breaking anything and they don't
need approval to do that. But, if UDP options are deployed things
could then break things in these environments, That risk needs to be
considered and proper mechanisms are used to mitigate the risk. If
nothing else, these issues will be raised again when someone suggests
to implement support in Linux and other OSes. Even if something is
completely correct protocol-wise, we can't arbitrarily break things
for real users.

Tom

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 12:25:51 -0800

> On Mar 4, 2018, at 12:22 PM, Tom Herbert <[email-masked]> wrote:
> 

Yes, but this doc is the first and only specified use thereof.

> What does "approved" mean?

Standard in the Ietf.

We can’t and don’t define standards to specify the use of those who don’t follow standards.  

> If someone is using the slack space for

We don’t.  Others do, and there is no way to ever prevent that.

Joe

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 20:30:32 +0000

> > can be validated without having to parse all the options to find EOL.

Well, I am obviously proposing that the whole of the surplus/slack area
then becomes UDP options.  So there would be no need for an additional
length field.

In terms of an implementation (slackU) which currently makes use of the
surplus/slack area, well they already can't guarentee that an unknown
peer will even recognise it, they might just dump anything beyond the
UDP payload.

So from that perspective, I'd say it makes things no worse for that implementation,
as they never had any basis to expect its use to be interpreted.

So if be call a implemention using UDP options optU; there would only
seem to be a few potential issues:
   1) slackU sending to optU, optU needs to ignore/discard the surplus area.
   2) optU sending to slackU, slackU will possibly misinterpret the options.
      (but it already had this issue, as a current implementation could send
       junk in the surplus area)
   3) wanting to upgrade a slackU box to understand optU, while still being
      compatible with another (identical) slackU stack.  For that a well
      known checksum would/could help to distinguish cases.  But is this
      case really one we should worry about.

So case 1 would seem to be the only one in scope for worrying about in this
draft.  If a checksum is used, it would give some protection; if omitted then
the application is taking its chances (unless communicating with a known
compatible stack).

> formed UDP options with high probability.

That would be possible with what I propose, as long as the application
stored a non 0x0000 value in the checksum.  If they chose to use the
0x0000 value, then they're taking their chances.

Well with what I'm proposing, one could verify that the bytes in the
surplus are potentially valid options (due to the checksum), before then
going on to parse the options, when stricter validation could occur.

DF

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 21:41:56 +0000

> It would be useful to show headers first, code later. Code changes; header can’t.

The problem with that is such code then becomes inherently non portable,
such that it isn't really safe to write the code in such a form.

Anyway - here is a version which should work on a system offering packed
structures, unaligned accesses, and the common zero length array extension.

Hopefully I've not added any errors in applying structures.

DF

#define UDPHDR_LEN 8
#define CHK_LEN 2
#define OPT_LITE 2

struct surplus {
        uint16_t checksum;
        union {
                uint16_t words[0];
                uint8_t tlv[0];
        } u;
};

struct opt_lite {
        uint8_t type;
        uint8_t len;
        uint16_t offset;
};

/*
 * dp points to start of UDP payload, dlen is UDP payload length.
 * plen is IP payload length.
 * Assumed that dlen vs plen validity already verified.
 */
bool validate_options_chk (uint8_t *dp, uint16_t dlen, uint16_t plen)
{
        uint16_t slen = plen - dlen - UDPHDR_LEN;
        struct surplus *sur = (void *)(dp + dlen);
        struct opt_lite *lite = (void *)sur->tlv;

        if (slen == 0)
        if (slen < sizeof *sur)

        /* Cheat - assume it is safe to write one extra byte */
        if (slen & 1)
                sur->u.tlv[slen - CHK_LEN] = 0;
        slen /= 2;

        uint32_t chk = sur->checksum; --slen;
        if (chk == 0) return true; /* Unprotected */

        wp = sur->u.words;

        /* Account for LITE header, skip to remaining options */
        if ((slen * 2 >= sizeof *lite) && lite->type == OPT_LITE && lite->len == sizeof *lite) {
                chk += wp[0]; chk += wp[1];

                uint16_t oo = ntohs(lite->offset);
                if (oo < UDPHDR_LEN + dlen + CHK_LEN + sizeof *lite) return false;
                if (oo > plen - CHK_LEN - sizeof *lite) return false;

                wp = (uint16_t *)(dp + oo - UDPHDR_LEN + (CHK_LEN + sizeof *lite));
                slen -= sizeof *lite / 2;
        }

        /* add the fold over of chk here */

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 13:51:15 -0800

> On Mar 4, 2018, at 1:41 PM, Derek Fawcus <[email-masked]> wrote:
> 

The doc won’t be specifying normative code. I’m not aware of RFCs that do - they provide (at best) examples.

We need specify headers and procedures and leave implementation details to implementers.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 14:25:53 -0800

> We can’t and don’t define standards to specify the use of those who don’t follow standards.
Who is not following the standards? As you said in the draft it has
always been permissible for the lengths not to match, so someone may
already be beneficially using this like the draft is proposing. Slack
space was never reserved for future use. We don't know if anyone is
using it, but if they are it would conform with the standards AFAICT.
So it's incumbent not to break them by retroactively declaring they
are doing something, possibly for many years, as wrong and not
approved.

Tom

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 14:36:50 -0800

> On Mar 4, 2018, at 2:25 PM, Tom Herbert <[email-masked]> wrote:
> 
> Who is not following the standards?

Whoever else is actually using that spare area.

> As you said in the draft it has
> always been permissible for the lengths not to match,

That explains why we’re not breaking UDP by trying to use it optionally - not that all uses of that space are hereby validated.

> Slack
> space was never reserved for future use.

Our doc only reminds us that it was not prohibited from future *specified* use, and that’s what we’re doing.

It was never authorized for un-specified uses.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 15:01:07 -0800

Joe,

I'm having a hard time finding what the standards say in this area. RFC768
defines UDP length, but says nothing more about this. Please provide
specific references to the operative RFCs with standards that would  be
violated.

Thanks,
Tom

> always been permissible for the lengths not to match,

That explains why we’re not breaking UDP by trying to use it optionally -
not that all uses of that space are hereby validated.

> space was never reserved for future use.

Our doc only reminds us that it was not prohibited from future *specified*
use, and that’s what we’re doing.

Joe

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 15:09:46 -0800

> On Mar 4, 2018, at 3:01 PM, Tom Herbert <[email-masked]> wrote:
> 
> 
> 
> On Mar 4, 2018 2:36 PM, "Joe Touch" <[email-masked] <mailto:[email-masked]>> wrote:
> 
> 
> > On Mar 4, 2018, at 2:25 PM, Tom Herbert <[email-masked] <mailto:[email-masked]>> wrote:
> >
> > On Sun, Mar 4, 2018 at 12:25 PM, Joe Touch <[email-masked] <mailto:[email-masked]>> wrote:
> >> ...
> >>
> I'm having a hard time finding what the standards say in this area. RFC768 defines UDP length, but says nothing more about this. Please provide specific references to the operative RFCs with standards that would  be violated.

You’re looking for something that is defined by its absence.

1) RFC 768 does not prohibit use of the area, BUT DOES NOT DEFINE A SPECIFIC USE either
2) there are no other RFCs (except this one, when published as such) that define a specific use

Thus any specific use (other than ones documented by us here) would be not be a standard. We don’t need to thus *support* that particular (not yet authorized) use.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sun, 4 Mar 2018 19:46:54 -0800

Joe,

I don't understand the concept of something being defined by it's absence.

In any case, I will suggest a four byte header in the options space:

header type: 1 byte
length: 1 bytes
csum: 2 bytes

The header type allows alternate formats, so if someone is already
using the slack space they can define a type for it. The length is
just the length in bytes not including first four bytes (I don't see
any legitimate reason to make it more than 255 bytes max). csum is the
normal 1-s complement checksum calculated from the header type byte
through the length + 4.

IMO checksum should always be set since it's only over a small amount
of data and as I mentioned it's likely that a host will need to
compute the checksum anyway in checksum complete processing. If it is
desirable for it to be optional then zero could be used.

The value of this header is that it provides a consistent means to
verify with pretty good probability that UDP options are correctly
formed. Also, it allows other formats in the slack space to be
defined. The cost is four bytes of overhead, but as I said before I
believe that is inconsequential compared to the assuring correctness
of the protocol.

Tom

---

From: Derek Fawcus <[email-masked]>
Date: Sat, 3 Mar 2018 14:18:05 +0000

DF

---

From: Derek Fawcus <[email-masked]>
Date: Sun, 4 Mar 2018 18:50:41 +0000

So we'd have a fixed 2 byte field, followed by a bunch of TLV options.
When LITE is being used, LITE would be the first TLV in the TLV section.

> So we need a fixed field (for the same reason) to always indicate whether LITE
> is present and the swap needs to happen before the checksum proceeds.

If the checksum is in a fixed field up front, and there is no OCS option,
the the code I posted shows how the checksum can be verified without first
performing the swap.

> So you’re saying at least that the minimum overhead for all options goes from zero bytes (in the current scheme) to 6 (2 for the checksum, 4 for LITE even when it isn’t used).

No - I am saying two things:

1) with the current scheme, due to the 'swap logic', there have to be at
   least 4 bytes of LITE data when it is being used without FRAG.
2) with my scheme, the same LITE without FRAG would imply there would have
   to be at least 6 bytes of LITE data.

Now looking at it again, I may have been misinterpreting how LITE+FRAG
is to be used.  I was reading it as still performing the same 'swap some bytes'
logic as used for LITE alone.  However looking again at Figure 8, maybe
you mean 'slide the LITE ahead of the 'LiteFrag'.  Please clarify.

I believe the LITE+FRAG case should still work if the 'swap some bytes'
approach for LITE alone was used in the encoding/decoding first step.

If the 'swap some bytes' scheme is to be used, then it would likewise
imply that would have to be at least 4 bytes within the 'LiteFrag' using
the current scheme, and 6 bytes there with my scheme.  I do not see that
as a problem in the use case with either approach, as it simply affects
how one would generate fragments.

As to the minimal overhead in general.  In the current scheme it is zero,
in my scheme it would be two.

> And you have to handle LITE processing or at least checking even when you’re not using it at all.

That is no diferent from the current scheme, where one always has to check
the start of the surplus area to see if it states with a LITE header.

(I did rather assume that most people would be able to comprehend C :-)

DF

---

From: Joe Touch <[email-masked]>
Date: Sun, 4 Mar 2018 21:10:07 -0800

> Have you looked at the code I included?

No, and I do not plan to. Again, we’re not standardizing code.

> Or should I try and express that algorithm in some other fashion?

As I noted, it is useful to show a header and explain the approach as in a spec, not an algorithm.

Joe

---

From: Derek Fawcus <[email-masked]>
Date: Mon, 5 Mar 2018 13:27:09 +0000

> No, and I do not plan to. Again, we’re not standardizing code.

The point in posting the code was not to have it standardised, it was an
attempt to achieve clarity regarding my proposal.

We had the following in prior exchanges:

Joe Touch wrote:
> > Derek Fawcus

> > If you have a proposed solution that preserves all of these and supports the existing properties, please post it.

The point of the posted code was to supply proof that what I suggested in terms
of checksum could be trivially made to cope with the uses of the LITE header,
and would not involve any re-copying of data.

What one then does in processing the options would entail whatever copying it
requires, but the checksum per-se would not add to that.

DF

---

From: Joe Touch <[email-masked]>
Date: Mon, 5 Mar 2018 06:59:10 -0800

> On Mar 5, 2018, at 5:27 AM, Derek Fawcus <[email-masked]> wrote:
> 

OK, so (again) without looking at the code (because it isn’t helpful here), I’m assuming the following:

- the CS comes first
- when LITE is seen, it is “jumped over” rather than being processed by the CS
- nothing else would need to change

In that case, we still have two problems:

1) the CS can’t be word-aligned (we can’t start with 1-3 NOPs)
2) we always burn 2 bytes even when CS is unused

The only benefit proposed so far is that this would be “stronger” than using CS as TLV after LITE or wherever it appears and a performance argument.

When CS is turned off, it doesn’t need to be stronger. When CS is turned on, it would be required only when both ends had already negotiated it as required, in which case there is no strength benefit either.

As to performance, we are trading an opcode (checking to see its type) vs. the ability to align it (much more important for performance) and space (a key issue as well).

Again, my view is that space is the driving issue and that strength/protection is not sufficiently impacted.

Joe