Subject: Re: [tsvwg] I-D Action: draft-ietf-tsvwg-udp-options-13.txt

From: Joseph Touch <[email-masked]>
Date: Wed, 7 Jul 2021 21:52:41 -0700

Notes below...

> On Jun 26, 2021, at 1:32 PM, C. M. Heard <[email-masked]> wrote:
> 
> On Sun, Jun 20, 2021 at 12:36 PM Joseph Touch  wrote:
> FWIW, on this point:
> 
>> On Jun 20, 2021, at 11:28 AM, C. M. Heard  wrote:
>> 
>> An option-aware client can and should include the UDP MRSS (Maximum Reassembled Segment Size) option in its request to indicate to the remote server the largest fragmented UDP datagram that it can reassemble.
> 
> Agreed, but that doesn’t help the client send a bigger request, which should also be possible, up to the minimums we specify.
> 
> But this doesn't help unless the client knows a priori that the server accepts UDP options in general and fragments in particular. AFAICT The only way to know a priori is via explicit configuration, in which case the relevant limits (MRSS, and possibly number of fragments) can be configured too.

The only way to *know*, yes. But we don’t want to prevent an endpoint from sending messages ‘opportunistically’, i.e., in the hopes that the options are supported. UDP is not a stateful protocol, so we do not want to require a stateful handshake before using options that could be ignored. 

That’s another reason why I think it is important to allow at least some minimal fragmentation and reassembly prior to getting ’soft’ information that allows it to be larger.

> I’m wondering if we can say:
> 
> - MUST support reassembly of at least (somewhere between 3 and 10), 
> 	unless considered a constrained instance, which MUST support at least 2
> 
> This allows for minimal IoT-style instances but doesn’t open the door too widely.
> 
> I remain unconvinced that it would be good for adoption of the spec to require anything beyond the ability to accept a datagram consisting of a single UDP fragment (one that is both initial and terminal). Based on the implementation experience that I have had, the difficulty is NOT how many fragments one must reassemble but rather the requirement to implement stateful reassembly machinery in an otherwise stateless protocol. 

Reassembly isn’t anywhere near the same as handshake state. It’s local to each side.

> Despite its age, RFC 815 remains still a good read and IMO its main lesson -- that the maximum reassembled size is what needs to be bounded, not the number of fragments -- remains relevant.

Although I agree that size is the issue, the number of fragments can and should also be bounded as well. RFC 815 was useful at the time, but even the smallest IOT devices have capabilities far in excess of what was available in desktop devices of 1982. Just as IPv6 requires 1280B packets with 1500B reassembled IP, it should not be too much to assume UDP options can support something up in that range.

Joe

---

From: Joseph Touch <[email-masked]>
Date: Wed, 7 Jul 2021 22:25:30 -0700

Hi, Mike,

> On Jun 26, 2021, at 10:13 PM, C. M. Heard <[email-masked]> wrote:
> 
> On Sat, Jun 19, 2021 at 12:39 AM Joseph Touch wrote:
> Here’s a summary - I tried to catch both everything Mike provided feedback on as well as what I have proposed as a way forward.
> 
> This is much appreciated, thank you. My item-by-item responses follow.
> 
> AFAICT, there are also two things not yet addressed, in addition to ongoing debate on the changes below:
> How many frags MUST be supported 2? 4?
> My position is still that the best way forward for general adoption of the spec is not to require anything beyond the ability to accept a datagram consisting of a
> single UDP fragment (one that is both initial and terminal). I provide a brief rationale in https://mailarchive.ietf.org/arch/msg/tsvwg/dUOTDlF4x6sVijtNGhhO5JJx7RA/ <https://mailarchive.ietf.org/arch/msg/tsvwg/dUOTDlF4x6sVijtNGhhO5JJx7RA/>.

I provided a rationale in my post to your other email just now; basically, IPv6 already requires reassembly of 1280B fragments to at least 1500B, so we can too. I don’t think it’s too much to add that capability to UDP, given it’s a requirement of another stateless protocol that even IOT devices need to support (to use IPv6).
> Should we change UNSAFE from a single code point to a range (but not a flag), and if so, what range of codepoints is sufficient (32? 16?)
>  
> I can live with the current approach, but I would much prefer a range of 32 codepoints. If the current approach is retained, I would like to suggest making the description of ENCR a separate subsection so that it appears in the table of contents (it would also be good to get it in the master list of options in Section 5).

I’ll wait to see how the WG feels (anyone else?). At a minimum, yes - ENCR can be in a separate subsection (I’ll add that to my list of pending updates).
> Frag 
> Drops integrated checksum
> Includes a start pointer so all per-frag options can come before the frag data
> Terminal includes an endpointer so options can come after
> This new format means that per-frag options always come before all FRAG data, which enables zero-copy
>  
> The specification as it stands in -13 will work, but I am not convinced that it is the best solution we could have.
> 
> 1.  One of the stated motivations is to support zero-copy reassembly, by allowing a NIC to DMA the fragment data to host memory. This implies that the NIC in question would need to be able to do header-data split. However, in -13 the combination of OCS + FRAG that precedes the fragment data is of variable length, being different for terminal and non-terminal fragments. Not all NICs implement header-data split for variable length headers (see, e.g., pp. 8-10 of https://netdevconf.info/0x14/pub/slides/62/Implementing%20TCP%20RX%20zero%20copy.pdf <https://netdevconf.info/0x14/pub/slides/62/Implementing%20TCP%20RX%20zero%20copy.pdf>). Moreover, I am not convinced that this is an important use case; the conventional format, not using fragments at all, serves the data streaming applications that Joe has in mind just as well.

I appreciate that zero-copy systems may need to adapt. However, if they can’t handle variable length headers, they can’t do zero-copy in most cases either (TCP already has this ‘feature’).

> 2. I question the need to allow for every option to be specified as being allowed both per-fragment and per-datagram; most apply to one ot the other (https://mailarchive.ietf.org/arch/msg/tsvwg/LF9rUkkqkz9gNqya36SW39XgliE/ <https://mailarchive.ietf.org/arch/msg/tsvwg/LF9rUkkqkz9gNqya36SW39XgliE/>), and thus I question the need to have options both before and after the payload data in a terminal fragment.

I disagree; I don’t see a need to indicate how options are used, given they are user (application) controlled anyway. The situation is distinct from IP, in which the headers are copied. In UDP, the use of options per-fragment is not “copied” from the original; they are added on a per-fragment basis.

Further, we already have options in both places. For FRAGs, options are before the fragment - that’s the nature of how the user data fragment is hidden so it is not visible to legacy receivers. However, once (safely) reassembled, they can - and IMO should - appear exactly as they would if fragmentation had not occurred. In that case, UDP options would *fllow* the datagram. 

IMO, that’s why the pre-fragment and post-datagram format is not only appropriate, but the best way to behave the way the system does in the absence of fragments.

> This is actually a relatively new feature, having been introduced (implicitly) in -09 without discussion on the list;

Actually, it goes back further than that; we only described it explicitly since -09. It has been an artifact of option processing ever since the introduction of the combined FRAG/LITE approach (which has been just FRAG since -09).

> in previous versions (-08 and earlier), options other than OCS were ignored except in the terminal fragment and were applied to the reassembled packet. At a minimum, this deserves a thorough discussion by the WG.

In previous versions, it was only a SHOULD that only OCS could precede FRAG/LITE.

> 3. By sandwiching the payload data in between other options, the FRAG format in -13 complicates generic checksum offload for encapsulated protocols. Granted that this is relevant only for the case of a self-contained fragment that is both initial and terminal fragment; but that case is important for enabling unsafe options.

I don’t see how this affects checksum offload, even for a self-contained fragment. OCS in each frag always goes to the end of the packet. In all FRAGs, UDP checksum stops at the UDP header. 

> Given the above, I continue to advocate for the format proposed in https://mailarchive.ietf.org/arch/msg/tsvwg/Wv--BLVMPAX6g5umok9BQsXAEGg/ <https://mailarchive.ietf.org/arch/msg/tsvwg/Wv--BLVMPAX6g5umok9BQsXAEGg/>, with the change of including a fixed length of 8 and using two codepoints to distinguish terminal and non-terminal fragments.

The only way both options could be 8 is to remove the possibility of post-frag options, or to somehow indicate the delineation between pre-frag and post-frag options some other way. I see no good reason to create a solution to this problem, vs. using the parallelism that a reassembled UDP datagram with options appears *exactly* as it would without reassembly, i.e., with UDP options after the user data.

> Finally, there is a lingering editorial matter: the following paragraph crept in during the change from -08 to -09, and it should be removed because (a) the first sentence is wrong and (b) the rest is redundant with the 2nd paragraph of the section.
> 
>    The Fragmentation option (FRAG) combines properties of IP
>    fragmentation and the UDP Lite transport protocol [RFC3828 <https://datatracker.ietf.org/doc/html/rfc3828>]. FRAG
>    provides transport-layer fragmentation and reassembly in which each
>    fragment includes a copy of the same UDP transport ports, enabling
>    the fragments to traverse Network Address (and port) Translation
>    (NAT) devices, in contrast to the behavior of IP fragments. FRAG
>    also allows the UDP checksum to cover only a prefix of the UDP data
>    payload, to avoid repeated checksums of data prior to reassembly.

That paragraph should have been removed; I missed it in this pass. I’ll add it to the pending updates.

> 
> OCS
> Uses the standard 2-byte prefix (all but NOP and EOL do)
> Added discussion of RFC 6935 regarding exception to requiring the UDP checksum and thus OCS
> Allow OCS’s checksum to be precomputed, but still check in the order options occur
> Occurs over the entire surplus area (doesn’t stop at EOL)
> OK on most points, but I strongly object to the following when OCS is mandatory (as is the case when UDP CS <> 0):
> 
>    Note that a receiver can compute the OCS checksum before processing
>    any UDP options, but that computation would assume OCS is used and
>    would not be verified until the OCS option is interpreted.
> 
> If I perform the computation before processing any options, and OCS is mandatory, it would be foolish of me to waste any more effort seeking the OCS option in the TLV chain. I already know that the option area is invalid,

How exactly do you know this? If OCS is mandatory, you need to find it (seek it in the TLV chain) in order to know whether the value you compute differs from the value in the option.

Performing the computation early just allows offloading if desired; the value computed still needs to be checked.

> and I should not try to parse potentially invalid TLVs. It is both unsafe and a waste of cycles. 

You can’t know when OCS is wrong until you find it in the TLV.

> Additionally, the following paragraph, while an improvement over the -12 version, is still not good enough when OCS is optional:
> 
>    >> When present, the OCS SHOULD occur as early as possible, preceded
>    by only NOP options for alignment.
> 
> When UDP CS == 0, either that SHOULD needs to be changed to a MUST, or the receiver needs to be excused from bothering to check OCS. I must once again question the wisdom of ever parsing a list of TLVs that are not covered by a checksum (and I think IPv6 made quite a big mistake to do so with its options).

I don’t see why SHOULD isn’t sufficient. First, it’s obvious that there could be utility in NOPs preceding OCS. Second, we don’t know what other options a user or implementer might want to occur first. You have to parse the TLV one way or the other to find OCS - even if it’s first. If it’s not, you still either find it or you don’t. Yes, earlier is better - but not MUST better. I see nothing that will not work if OCS is not first so no rationale for forcing this.

> I'd like to bring up another point that came to my attention during an off-list discussion with Tom Herbert, namely that optional checksums save no work for an implementation that has generic checksum offload; in fact, they create more work by creating more special cases. He makes the point -- convincingly, as far as I am concerned -- that optional checksums are largely a relic of the past. My preference would be to see support for UDP CS == 0 be an option that consenting endpoints may use but that are not required to be implemented.

I don’t understand what that would mean, but this argument appears to ignore the most important current use case - tunnels. Tunnel systems do not necessarily rely on offloading hardware because the packet processing occurs after the packet has already passed the interface, in many cases.

> Finally, the next-to-last paragraph still has a typo:
> 
>    As a reminder, use of the UDP checksum is optional when the UDP
>    checksum is zero. When not used, the OCS is assumed to be "correct"
>    for the purpose of accepting UDP packets at a receiver (see Section
>    7).
> 
> It should say:
> 
>    As a reminder, use of the OCS is optional when the UDP
>    checksum is zero. When not used, the OCS is assumed to be "correct"
>    for the purpose of accepting UDP packets at a receiver (see Section
>    7).

Yes, will fix.

> NOP
> Increased max in a row from three to  seven
> 
> OK
> 
> AE
> Split into AUTH (safe) and ENCR (UNSAFE)
> AUTH can depend on option data
> ENCR can depend on but not modify option data
> Only one is ever used at a time, though (that’s one reason it was presented as AE before)
> 
> OK modulo editorial comment above about ENCR
> 
> EOL
> MUST set as zero on transmit, MAY check on receipt, but MUST ignore otherwise.
> post-EOL always were covered by OCS and still are
> 
> OK
> 
> UDP Length vs extended length
> Always use the smallest format, as Mike suggested
> 
> OK with one question. The spec now says:
> 
>    >> Options using the extended option format MUST indicate extended
>    lengths of 255 or higher; smaller extended length values MUST be
>    treated as an error.
> 
> What do I do if someone sends me an option that has the extended format but with a length between 4 and 254? Do I skip over just the offending option, or do I drop the entire option area?

It might be easier to say SHOULD use the smallest format (and clearly has no choice but to use the larger formate for 255 and larger, but there’s no good reason now to prohibit these values. I think the only error is if the smaller one is below 4, which is an invalid length. Any time an invalid length is seen, option processing should cease, as per the quoted text below (from Sec 4).
> Option length errors
> Corrected to fail only on nonsensical values, otherwise skip as unknown
> 
> Section 4 still says:
> 
>    >> Option Lengths (or Extended Lengths, where applicable) smaller
>    than the minimum for the corresponding Kind and default format MUST
>    be treated as an error. Such errors call into question the remainder
>    of the option area and thus MUST result in all UDP options being
>    silently discarded.
> 
> In  order to be consistent, the words "Kind and default" should be removed from the first sentence.

Yes for default; I think Kind is still useful to retain. I.e., if you know the Kind and the length given is too small, then stop.

> Also: would it be appropriate to make an exception for FRAG? Normally the whole option area is discarded if a FRAG option is seen when there is conventional UDP data; does the rule for wrong length override that? Note that FRAG is an unsafe option; if it weren't in the base specification, we would insist that it be dropped if unrecognized.

I don’t see an exception for FRAG. It would mean the entire option area would be discarded. Given FRAG only appears (now) when there is no user data, that means the packet is basically discarded.

> Also for OCS; the assumption that it is based on the Internet checksum is pretty much baked in; if I see something with a different length, I don't know how to validate the option checksum, and so I would be inclined to drop the options.

Yes. Same issue, same result AFAICT.

> ACS
> Silently ignored if failed except if configured otherwise
> Unknown lengths treated same as bad checksum
> 
> OK
>  
> EXP
> Showed extended length format
> 
> OK
>  
> UNSAFE
> Noted extended length format also applies
> Cannot modify option data
> 
> OK modulo editorial comment about ENCR above, but I would still prefer to have a range of values.
>  
> UDP-lite
> Removed implied equivalence to FRAG, but retained remainder  as useful context
> 
> OK
> 
> Thanks and regards,
> 
> Mike Heard

---

From: Tom Herbert <[email-masked]>
Date: Thu, 8 Jul 2021 10:13:21 -0700

On Wed, Jul 7, 2021 at 10:25 PM Joseph Touch <[email-masked]> wrote:
> single UDP fragment (one that is both initial and terminal). I provide a brief rationale in https://mailarchive.ietf.org/arch/msg/tsvwg/dUOTDlF4x6sVijtNGhhO5JJx7RA/.
>
>
> 1.  One of the stated motivations is to support zero-copy reassembly, by allowing a NIC to DMA the fragment data to host memory. This implies that the NIC in question would need to be able to do header-data split. However, in -13 the combination of OCS + FRAG that precedes the fragment data is of variable length, being different for terminal and non-terminal fragments. Not all NICs implement header-data split for variable length headers (see, e.g., pp. 8-10 of https://netdevconf.info/0x14/pub/slides/62/Implementing%20TCP%20RX%20zero%20copy.pdf). Moreover, I am not convinced that this is an important use case; the conventional format, not using fragments at all, serves the data streaming applications that Joe has in mind just as well.
>
>
> 2. I question the need to allow for every option to be specified as being allowed both per-fragment and per-datagram; most apply to one ot the other (https://mailarchive.ietf.org/arch/msg/tsvwg/LF9rUkkqkz9gNqya36SW39XgliE/), and thus I question the need to have options both before and after the payload data in a terminal fragment.
>
>
> Given the above, I continue to advocate for the format proposed in https://mailarchive.ietf.org/arch/msg/tsvwg/Wv--BLVMPAX6g5umok9BQsXAEGg/, with the change of including a fixed length of 8 and using two codepoints to distinguish terminal and non-terminal fragments.
>
>
>    fragmentation and the UDP Lite transport protocol [RFC3828]. FRAG

If the OCS is in a TLV in an arbitrary position in the list, how is
wasting cycles avoided? It seems like we need to either parse the list
fishing for the OCS, or start processing TLVs and throw out any work
that was done if an invalid checksum is found.

> You can’t know when OCS is wrong until you find it in the TLV.

That presumes that the corruption causing the checksum to be invalid
doesn't affect the ability to find the OCS TLV. However, if a data
corruption is in the kind field of the OCS or if a length field of a
previous TLV then the OCS TLV might no longer be identifiable in a
packet. In these cases, the OCS is wrong however, unless the OCS is
mandatory for this packet, we don't know the OCS is wrong and we
incorrectly accept the packet. I have brought up this issue several
times that a checksum in a TLV, like OCS, cannot protect itself from
corruption; it would be great to see some discussion of this problem
in the draft.

> I don’t understand what that would mean, but this argument appears to ignore the most important current use case - tunnels. Tunnel systems do not necessarily rely on offloading hardware because the…
A very common use case of tunneling is network virtualization where VM
guests are sending TCP/UDP packets that are encapsulated by a
hypervisor in VXLAN, nvgre, etc. In this case checksum offload of the
transport checksum in the guests packets is important for performance.

---

From: Joseph Touch <[email-masked]>
Date: Fri, 9 Jul 2021 08:06:27 -0700

Hi, Tom,

> On Jul 8, 2021, at 10:13 AM, Tom Herbert <[email-masked]> wrote:
> 
>> …
>>   If I perform the computation before processing any options, and OCS is mandatory, it would be foolish of me to waste any more effort seeking the
>>   OCS option in the TLV chain. I already know that the option area is invalid,
>> 
> wasting cycles avoided?

Everything we’re doing wastes cycles by some metric, e.g., if the checksum fails or if the TLV needs to be parsed and there’s no OCS.

This issue isn’t whether it’s wasted cycles; it’s WHEN. If we force a fixed header in a fixed location, then parsing it is a waste to everyone who isn’t using OCS on every packet - which is bad design, because those are the users whose performance we should be conserving.

The approach in the doc does potentially waste cycles - but only when OCS is either far into the TLV or required and not in the TLV at all - e.g., because of corruption. Both are intended to be very rare events, so given we’re going to waste cycles one way or the other, IMO this is the better place to potentially waste them.

> It seems like we need to either parse the list

If OCS is needed, you need to process *it* first - so even if you walk the TLVs, you aren’t doing any work on them except that walk until OCS is checked. 

Note that we say OCS *SHOULD* come first, likely only after NOPs, but we don’t need to force this. If someone wants to put the OCS later, then that’s their choice.

> doesn't affect the ability to find the OCS TLV.

No; it’s a statement of fact. If you don’t find it in the TLV at all and it’s not required, it’s not wrong. If it is required (because UDP CS<>0) *AND* it’s not in the TLV, then you have an invalid packet (not an invalid checksum). Both will be detected. Again, the chance that corruption happens that destroys the TLV chain is possible but of low probability.

> However, if a data
> packet. In these cases, the OCS is wrong

It would be missing. You can’t say something that isn’t there is incorrect except for being missing.

> however, unless the OCS is
> incorrectly accept the packet.

Yes - that’s what happens.

> I have brought up this issue several

An error in the TLVs is likely to cause the chain to have a parse error too, at which point we would drop the options anyway.

Do you really think we need to discuss the case where:
	- the TLV chain has an error that hides use of OCS when it is optional
	AND
	- that TLV chain does not have a parsing inconsistency 
	(e.g., a length that is nonsense either in relation to its kind or jumps past the end of the packet)

We can discuss that, but IMO that’s a reasonable risk given it’s likelihood.

>> When UDP CS == 0, either that SHOULD needs to be changed to a MUST, or the receiver needs to be excused from bothering to check OCS.

It’s the sender’s perogative to use OCS even when UDP CS==0.

If the sender adds it, the receiver should process it if found. If the lack of a UDP CS causes undetected errors elsewhere, that’s a choice the sender made.

>> I must once again question the wisdom of ever parsing a list of TLVs that are not covered by a checksum (and I think IPv6 made quite a big mistake to do so with its options).

Doesn’t this viewpoint contradict the request to excuse the receiver you just made above?

>>   I'd like to bring up another point that came to my attention during an off-list discussion with Tom Herbert, namely that optional checksums save no
>>   work for an implementation that has generic checksum offload; in fact, they create more work by creating more special cases. He makes the point 
>>  
>>   -- convincingly, as far as I am concerned -- that optional checksums are largely a relic of the past. My preference would be to see support for UDP 
>>   CS == 0 be an option that consenting endpoints may use but that are not required to be implemented.
>> 

Encapsulation by a hypervisor that uses checksum offload. Hmm. I’ll need to think about how that works - are you sending packets between processes of a CPU by sending them out to the network card and back?

Yes, hardware integration will require changes to make UDP options work. Some may be able to do this with just reprogramming, some will require new hardware. We can’t design solutions for only the hardware optimizations that exist today.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Fri, 9 Jul 2021 15:21:53 -0700

> This issue isn’t whether it’s wasted cycles; it’s WHEN. If we force a fixed header in a fixed location, then parsing it is a waste to everyone who isn’t using OCS on every packet - which is bad des…

I don't know if it's a bad design, but I do know that IPv4 and TCP
have had a fixed checksum field that covers options for over forty
years. Not unsurprisingly, implementators have long since figured out
how to optimize checksum calculation. Checksum offload is ubiquitous
and CPUs have add-with-carry instructions of 32-bit, 64-bit, or vector
instructions to optimize checksum calculation. Also, because of the
way checksum offload works both senders and receivers of UDP options
are likely to compute the checksum over the surplus area regardless of
whether the checksum field is present-- even today, a legacy receiver
will compute the checksum of surplus area in order to offset the
checksum received from the device in checksum offload. AFAICT, no
users are complaining about Internet checksum performance.

In contrast to checksum calculation, walking TLV lists is still
considered a major problem for performance. The algorithm is an
inherently serialized loop that requires a number of conditionals
(i.e. we need to switch on the type and we need to check the length of
each TLV to make sure it is in bounds). For instance, walking over
sixty-four bytes containing with say eight TLVs is more work than it
would take to compute the checksum over those same bytes. If we need
to walk a TLV list twice, the first to find the OCS and second pass to
actually process the TLVs, I believe it is a significant performance
hit.

Tom

---

From: Joseph Touch <[email-masked]>
Date: Fri, 9 Jul 2021 17:15:01 -0700

Hi, Tom,

> On Jul 9, 2021, at 3:21 PM, Tom Herbert <[email-masked]> wrote:
> ...
> years.

The field location is irrelevant; the issue for offload *calculation* is the location of the area being covered. For OCS, it’s the entire surplus area, which does not require TLV parsing to determine.

Note, though, that IP may be in a fixed place, but covers only the IP header. The more relevant example is TCP, which is NOT fixed relative to the IP header (because there could be IP options).

> Not unsurprisingly, implementators have long since figured out
> instructions to optimize checksum calculation.

Note: the OCS checksum start is just as well known as it is for TCP - once the UDP offset is known, the OCS always covers exactly the same area between the UDP Length and the end of the IP packet. It’s only the *check* of the OCS validation that can’t be offloaded as easily, but that’s not always offloaded either. Offload calculates the checksum; there’s not a big win in doing the check there unless bad packets are the norm.

> Also, because of the

Sure, but that doesn’t change here either - as noted. Wherever OCS is placed, the checksum always covers the whole “surplus” area.

> considered a major problem for performance.

And that’s still required for TCP and IP. We’re no different. That has no impact on checksum offload for UDP, only in option processing.

> The algorithm is an

And we have lived with that for years with TCP. The only difference here happens *outside* of offload optimization.

Any device that offloads the rest of transport processing already walks TCP TLVs and can walk UDP ones just as quickly (or slowly).

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 10 Jul 2021 08:19:08 -0700

> And that’s still required for TCP and IP. We’re no different. That has no impact on checksum offload for UDP, only in option processing.
TCP and IPv4 do not require walking their respective options to
validate the checksum,  UDP options does at least when UDP checksum is
non-zero. If processing UDP options walks the list twice, once to
search for a specific TLV and once to process the rest of the options,
then relative to checksum processing for TCP and IPv4 that is a
performance degradation. Maybe there are other intended methods like
provisionally processing TLVs and throwing out work when a bad
checksum is detected or scoreboarding of TLVs, but those options are
not articulated in the draft nor are there any references to
implementation that show this.

Tom

---

From: Joseph Touch <[email-masked]>
Date: Sat, 10 Jul 2021 09:09:37 -0700

Hi, Tom,

> On Jul 10, 2021, at 8:19 AM, Tom Herbert <[email-masked]> wrote:
> 
> validate the checksum,  

OK, we agree on that. So at least we’ve established the use of TLVs isn’t an offload issue.

> UDP options does at least when UDP checksum is
> non-zero. If processing UDP options walks the list twice,

Only when the SHOULD is not followed; we can certainly add that note.

An implementation could easily walk the TLV and set a flag if options other than OCS or NOP appear. The walk ignores such options until OCS and restarts if OCS works.

So we can note that this “double walk” would incur double work if:
	- options other than OCS and NOP appear before OCS
	AND
	- offloading is used

Without offloading, the walk always occurs twice: once to compute the checksum, once to process options, and the first pass can keep a copy of the OCS value to check before the second pass.

> .... Maybe there are other intended methods like

We can mention that possibility, which would be no different than deep conditional processing that many systems alr

But, again, the issue isn’t about offloading, it’s in post-offload processing, and only if the SHOULD is not followed.

At that point, yes, we could do something to avoid that possible issue without impacting those who don’t use OCS, but it’s a lot simpler than has been proposed before. It does revive the idea of a required UDP option header, but it would basically be just an aligned OCS checksum:

	- NOPs until 4-byte alignment (note that some wanted 8-byte alignment, so we have to pick)
	- OCS checksum field only (no kind, no length)

If we don’t require alignment, there’s a small amount of additional work. That might not be useful to optimize for because the UDP option space isn’t constrained the way TCP’s is, though.

That overcomes the post-offload issue for OCS, though there’s still a similar post-offload issue for other options (ENCR, AUTH) that matches the same ‘chain’ problem you’ve been concerned about that still in other protocols that use offloading for crypto, e.g., IPsec, TCP-MD5/TCP-AO, etc.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 10 Jul 2021 11:49:43 -0700

> - options other than OCS and NOP appear before OCS

What if OCS is not present? If we ignore options in the first walk to
account for the possibility that an OCS might be present, doesn't that
mean that once the walk completes and we haven't found the OCS we need
to walk again to actually process all the options?

---

From: Joseph Touch <[email-masked]>
Date: Sat, 10 Jul 2021 17:30:34 -0700

> On Jul 10, 2021, at 11:49 AM, Tom Herbert <[email-masked]> wrote:
> 

And notes when OCS isn’t present but required.

> What if OCS is not present?

See above.

> If we ignore options in the first walk to

Only if OCS is optional.  If OCS is required, if you haven’t found OCS you would stop.

If OCS is present and early, the walk stops quickly. However, if OCS isn’t required, it’s not clear that if its absence in the first few bytes should interfere with the rest of processing (which would be ignored if OCS shows up later).

>> - offloading is used

Again, it boils down to whether OCS is buried deep in the packet or not - that’s why we have a SHOULD. If we have a MUST, we have to decide now what the alignment is and force that overhead on all packets (including alignment).

Again, though, if the WG wants to push that field to the front as fixed - either always the first two bytes or always the first two X-aligned bytes (for X=4 or 8), then it’s easy to add - but we need to pick 4 or 8 now to do that. The issue is that there are no other equivalent fields that are needed, though.

Joe

---

From: "C. M. Heard" <[email-masked]>
Date: Sat, 31 Jul 2021 16:28:52 -0700

On Wed, Jul 7, 2021 at 10:25 PM Joseph Touch wrote:

> Hi, Mike,
>
> On Jun 26, 2021, at 10:13 PM, C. M. Heard wrote:
>
>> Here’s a summary - I tried to catch both everything Mike provided
>> feedback on as well as what I have proposed as a way forward.
>>
>

>
>>    - OCS
>>       - Uses the standard 2-byte prefix (all but NOP and EOL do)
>>       - Added discussion of RFC 6935 regarding exception to requiring
>>       the UDP checksum and thus OCS
>>       - Allow OCS’s checksum to be precomputed, but still check in the
>>       order options occur
>>       - Occurs over the entire surplus area (doesn’t stop at EOL)
>>
>> OK on most points, but I strongly object to the following when OCS is
> mandatory (as is the case when UDP CS <> 0):
>
> If I perform the computation before processing any options, and OCS is
> mandatory, it would be foolish of me to waste any more effort seeking the
> How exactly do you know this? If OCS is mandatory, you need to find it
> (seek it in the TLV chain) in order to know whether the value you compute
> differs from the value in the option.
>

This last statement is not true, and I think it's important to clarify that
fact.

If OCS is mandatory (because UDP CS<>0), then I can determine whether the
options area has an INVALID checksum by computing the 16-bit Internet
checksum over the options area conceptually prepended by a 2-byte options
area pseudo-header containing the options area length. If the result is not
a 1s complement zero, then I KNOW that the option checksum is not valid.
Full stop. Whether that is because the OCS TLV is absent or because it is
present and has the wrong value makes no difference; the option checksum is
not valid, and I do not need to parse a single TLV to determine that. I can
immediately stop option processing and discard the contents of the option
area.

Performing the computation early just allows offloading if desired; the
> value computed still needs to be checked.
>

If UDP CS <> 0 and the result of the above computation is a 1s complement
zero, then strictly speaking I need to look for OCS when I am looping
through the option TLVs: it is possible that there the options area by
chance happens to have a zero checksum even though no OCS TLV is present.
That is on the same level of probability as an undetected checksum error.
Little would be lost by not checking for a required-but-not-present OCS TLV
when the option checksum calculation yields zero. If you insist, I will
make that check; but please don't tell me that I need to check the option
area at all once I know, for sure, that the option checksum is invalid.

If UCP CS=0, and the connection has been configured to accept such packets
(default for IPv4, non-default for IPv6), and has also  not been configured
to require OCS (default by the current spec), then I do have to parse the
option area whether or not the option checksum calculation described above
returns  a 1s complement zero. Whether this is wise from a safety
perspective is debatable, but having been instructed by the user to do so,
I will do as I am told. (I do have to say that I'm not convinced that the
use cases where UDP CS=0 is acceptable (e.g., tunnels) will have much use
for UDP options, especially in the legacy trailer format, but that's a
debate for another thread).

Mike Heard

---

From: Joseph Touch <[email-masked]>
Date: Sat, 31 Jul 2021 18:32:43 -0700

Hi, Mike,

> On Jul 31, 2021, at 4:28 PM, C. M. Heard <[email-masked]> wrote:
> 
> This last statement is not true, and I think it's important to clarify that fact.
> 
> If OCS is mandatory (because UDP CS<>0), then I can determine whether the options area has an INVALID checksum by computing the 16-bit Internet checksum over the options area conceptually prepended by a 2-byte options area pseudo-header containing the options area length. If the result is not a 1s complement zero, then I KNOW that the option checksum is not valid. Full stop. Whether that is because the OCS TLV is absent or because it is present and has the wrong value makes no difference; the option checksum is not valid, and I do not need to parse a single TLV to determine that. I can immediately stop option processing and discard the contents of the option area.

OK - I see what you’re getting at now. We can adjust the text accordingly.

Joe