Subject: Re: [tsvwg] Alternative version of the UDP FRAG option

From: "C. M. Heard" <[email-masked]>
Date: Mon, 11 Mar 2019 21:10:51 -0700

On Mon, Mar 11, 2019 at 9:26 AM C. M. Heard <[email-masked]> wrote:
> I'd like to float a different idea, namely, putting the UDP user data
> inside the FRAG option itself.

Well, that proposal was rather obviously flawed by limiting fragment
sizes to ~240 bytes. My apologies. I withdraw the FRAG proposal in

https://mailarchive.ietf.org/arch/msg/tsvwg/JZ8ohgwMs9eRPRQ6KJDqUZTJxSk

However, I think that the following simpler version will actually work:
maintain the format of the FRAG option as currently defined, but instead
of having the option capture preceding conventional or LITE user data as
fragment data, insist that it appear ***last*** in the option list and
have it capture all remaining octets in the packet as fragment data. By
convention, if this option appears, OCS would cover all UDP options as
well as all octets in the UDP trailer that follow the FRAG option.

The following requirements would apply:

   >> When the FRAG option appears, it MUST come last in the UDP options
   list.  All remaining options in the packet are interpreted as fragment
   data.

   >> OCS, if present, covers both the FRAG option and the trailing
   fragment data.

   >> A host that wishes to signal that it is able to accept and process
   the FRAG option MAY do so by transmitting an unfragmented datagram
   with an empty terminal FRAG option whose Offset and Checksum fields
   are set to zero.

   >> Non-empty FRAG options MUST NOT be present in packets with ordinary
   UDP user data or LITE data. Any such options MUST be silently dropped.

   >> UDP options other than OCS and padding MUST NOT accompany the FRAG
   option in non-terminal fragments.  Any such options MUST be silently
   dropped.  All other options that apply to a reassembled packet must
   accompany the FRAG header in the terminal fragment.

This proposal does not suffer from the disadvantage that a legacy receiver
could misinterpret a UDP fragment as a complete datagram, as does the
currently-defined version of FRAG without LITE.  And it avoids the problem
that OCS does not cover the currently defined version of FRAG+LITE.

Note that because of their unusual property of capturing following or
preceding data, FRAG and LITE would have to be mandatory to
recognize, but I do not believe that they should be mandatory to
generate or process. An implementation that cannot process these
options should silently drop packets that contain them.

There's probably something wrong; if so, please tell me what it is.

Mike Heard

---

From: Joe Touch <[email-masked]>
Date: Tue, 12 Mar 2019 00:44:38 -0400

Frag+lite can still be checksummed after reassembly as is. We don’t want or need to do that check twice and can’t usefully string together partial sums. 

Joe

> On Mar 12, 2019, at 12:10 AM, C. M. Heard <[email-masked]> wrote:
>

---

From: "C. M. Heard" <[email-masked]>
Date: Mon, 11 Mar 2019 23:00:08 -0700

Yes, but FRAG+LITE fails the deployability test. That IMHO makes it a
non-starter.

---

From: Joe Touch <[email-masked]>
Date: Tue, 12 Mar 2019 06:08:51 -0400

That is lite alone only AFAICT. And we already know that is the risk CURRENTLY. 

Again, we need to include fixing these errors. If we let every bug persist, nothing would be deployable anymore. 

Joe

> On Mar 12, 2019, at 2:00 AM, C. M. Heard <[email-masked]> wrote:
>

---

From: Derek Fawcus <[email-masked]>
Date: Tue, 12 Mar 2019 11:47:19 +0100

> Again, we need to include fixing these errors. If we let every bug persist, nothing would be deployable anymore. 

The way I view it is that we need to get a useful sub-set of the UDP-Options
deployable, and that would break the chicken-vs-egg situation which prevents
getting other systems fixed.

So if say LITE alone requires that systems be fixed (which I think it will
due to not wanting to checksum the LITE data, yet needing the packet to be
checksum neutral), while sending segmented large UDP packets (the current
LITE+FRAG case) can be made to work in the face of the broken systems,
we shoukd do so.

I think that addition, namely restoring the ability to send large (> pMTU)
UDP payloads, which has been somewha broken by NATing of IP fragmented
UDP is worthwhile, and probably sufficient to bootstrap UDP-Options.
It is also an improvment on the IP fragmented case in that it each FRAG
has port information.

So we can probably make every use except the pure LITE data case deployable,
making them deployable should eventually result in systems being fixed,
such that pure LITE is usable.

DF

---

From: "C. M. Heard" <[email-masked]>
Date: Tue, 12 Mar 2019 09:36:04 -0700

On Tue, Mar 12, 2019 at 3:09 AM Joe Touch wrote:
> > On Mar 12, 2019, at 2:00 AM, C. M. Heard wrote:
> That is lite alone only AFAICT.

I don't think that is the case. As stated in the -07 draft (and
reiterated in subsequent email discussions), the fact that OCS
does not cover LITE data defeats its ability to compensate for
the middlebox checksum bug, whether used alone or in combination
with FRAG:

   Note that this incorrect checksum traversal feature is defeated by
   the use of LITE, whether alone or with FRAG, because the LITE area
   is deliberately not covered by OCS. It also is defeated by the use
   of a zero UDP checksum (i.e., UDP checksum disabled).

Unless I've missed something, the only proposal on the table that
allows FRAG+LITE to traverse middleboxes with the checksum bug is
to disable the UDP checksum (i.e., set it to zero), and as pointed
out by Raffaele Zullo, that has its own downsides (no protection
for the UDP length or the port numbers).

A revised OCS (that includes the pseudo-header correction) will allow
FRAG **without** LITE (as proposed in the draft) to traverse the
affected middleboxes with a non-zero UDP CS, but that method has the
following downsides:

1) A legacy host interprets FRAG without LITE as a complete UDP datagram
2) The same is true for an options-aware host if OCS fails
3) There is duplicate checksum coverage (UDP checksum covers each fragment,
   plus post-reassembly checksum contained in the terminal FRAG option)

FRAG+LITE solves all three of these problems (rather elegantly IMHO)
but unfortunately at the cost of poor middlebox traversal properties,
a fact that was not known until the work of the CCO folks.

Unlike LITE, which is a nice-to-have feature that the world has so
far managed to live without, the main reason for wanting FRAG is
because IP fragments have poor middlebox traversal properties
(especially IPv6), and for some use cases (e.g., DNSSEC), there
is no viable alternative. If IP fragmentation did not suffer
from middlebox traversal issues, we would not need FRAG.

So, from my perspective, FRAG is not very useful unless we can
solve both middlebox traversal and at least problems 1+2 above.

>>> well as all octets in the UDP trailer that follow the FRAG option.

does just that. Granted, it does not solve problem 3, but the following
variant would: omit the overall checksum from terminal FRAG option and
use a different option Kind instead. Require OCS to be present in all
fragments whenever the user UDP CS setting specifies that the UDP
checksum must be present, irrespective of the user OCS setting.

AFAICT, forcing the revised OCS to cover the data in each fragment
provides protection that is essentially equivalent to that provided
by the proposed post-reassembly checksum. For in order to deliver the
reassembled data we require all fragments to be present and fit
together exactly with no overlap. ACS is available if a stronger
post-reassembly checksum is wanted.

> Again, we need to include fixing these errors. If we let every bug
> persist, nothing would be deployable anymore.

I totally agree with that. But it can be a very long game, as the
recent DNS flag day (when major implementations finally turned EDNS0
workarounds off) illustrates.

Mike Heard

---

From: Raffaele Zullo <[email-masked]>
Date: Tue, 12 Mar 2019 17:13:40 +0000

Hello,

>    plus post-reassembly checksum contained in the terminal FRAG option)

This is true, but
1 can be solved if FRAG Option has a 2 bytes Length and carries the 
fragment inside it.
2 if the fragment is inside FRAG and OCS is not valid, the fragment is 
just discarded
3 covering each fragment with OCS is basically the same of covering the 
reassembled packet

> by the proposed post-reassembly checksum.  ...

> Mike Heard

You actually already pointed out 3
and already suggested The FRAG Option carrying fragment inside 
previously.

Thank you,
Raffaele Zullo

---

From: "C. M. Heard" <[email-masked]>
Date: Tue, 12 Mar 2019 10:18:04 -0700

> 1 can be solved if FRAG Option has a 2 bytes Length and carries the

Correct; your proposal for allowing an "escape" for two-byte
lengths would allow for this

> 2 if the fragment is inside FRAG and OCS is not valid, the fragment is

Correct

> 3 covering each fragment with OCS is basically the same of covering the

That was my assessment

> and already suggested The FRAG Option carrying fragment inside

Yes but that suggestion missed the need for a two-byte length.

Mike

---

From: Joe Touch <[email-masked]>
Date: Tue, 12 Mar 2019 15:40:04 -0700

I'm still not following the need for this alternative. 

FRAG+LITE works fine - even through broken middleboxes with the checksum
bug - if used with CS=0, which is how it ought to be used. The trailing
checksum in the last fragment is over the reassembled total (or not if
also zero) and there's no utility in checksumming the fragments
themselves. 

This still allows the UDP options of the reassembled packet to use OCS,
regardless of the reassembly checksum. 

So what's missing and why is this alternate needed? 

Joe

---

From: "C. M. Heard" <[email-masked]>
Date: Tue, 12 Mar 2019 15:56:06 -0700

On Tue, Mar 12, 2019 at 3:40 PM Joe Touch wrote:
> bug - if used with CS=0, which is how it ought to be used.

Not all of us agree that this is how it ought to be used, since CS=0 affords
no protection for the UDP header itself.

>  The trailing checksum in the last fragment is over the reassembled total
> (or not if also zero) and there's no utility in checksumming the fragments
> themselves.

My position is that the level of protection that we should strive to
achieve is what is available with conventional IP fragmentation coupled
with the standard UDP checksum. That combination protects the entire UDP
datagram, including the UDP header. The trailing checksum the terminal
FRAG option, when used with CS=0, does not do that.

A second reason for preferring this proposal to FRAG as now presented
in the draft is that it eliminates the hazard of FRAG without LITE.

Mike Heard

---

From: Tom Herbert <[email-masked]>
Date: Tue, 12 Mar 2019 16:04:48 -0700

> no protection for the UDP header itself.
Also, UDP checksums are not optional in IPv6 (except in a very narrow
use case of tunnels which is not applicable here).

---

From: Joe Touch <[email-masked]>
Date: Tue, 12 Mar 2019 16:07:59 -0700

> no protection for the UDP header itself.

Not exactly. CS=0 with nonzero fragment checksum still ends up (IMO)
implicitly validating the length of the payload that results anyway -
and OCS on the reassembled set (i.e., OCS as the first UDP option in the
reassembled payload) would provide a check on the options. 

The only thing missing is protection of the port numbers - which get
rewritten and recomputed many times inside the net in many cases, to the
point that I don't think it even makes sense to consider that an E2E
protected field anymore. 

> in the draft is that it eliminates the hazard of FRAG without LITE.

Understood, but AFAIR your proposal ends up computing checksums multiple
times over the same data. 

And no, those checksums can't be combined to save work - that undermines
the whole point of a reassembly checksum. 

I.e., we're not really giving up much (in terms of protection, see
above) but we gain a LOT (much less work - enough that will end up
mattering in cases with high reassembly load, such as DNS servers, IMO).

Joe

---

From: Joe Touch <[email-masked]>
Date: Tue, 12 Mar 2019 16:13:59 -0700

On 2019-03-12 16:04, Tom Herbert wrote:

> On Tue, Mar 12, 2019 at 3:40 PM Joe Touch wrote: I'm still not following the need for this alternative.
> 

By adding our own reassembly checksum, we're in the spirit of RFC 6936 -
notably the requirement in Section 5, item #5.

---

From: Tom Herbert <[email-masked]>
Date: Sat, 16 Mar 2019 09:06:23 -0700

>    list.  All remaining options in the packet are interpreted as fragment
Hi Mike,

Thinking about this, it occurs to me be that the LITE option isn't
needed. The assumption in the UDP options draft is that a receiver
needs the UDP payload to immediately follow the UDP header, but the
UDP payload can be anywhere in the surplus area as long as it's
aligned to four bytes. A receiver will know how to handle it and
deliver the UDP data to the application (e.g. by maintaining a pointer
to the data).

So that allows a format like:

UDP header (Length=8) | Surplus area header | Options | Payload

The surplus area header contains the header length and a checksum
covering the surplus space (four bytes altogether). The three headers
can thought of as an extended UDP header, so the format becomes:

Extended UDP header | Payload

Which looks a whole lot like any other protocol format with a variable
length header such as TCP or IPv4.

Tom

---

From: Joe Touch <[email-masked]>
Date: Sat, 16 Mar 2019 11:21:32 -0700

> On Mar 16, 2019, at 9:06 AM, Tom Herbert <[email-masked]> wrote:
> Hi Mike,
> 
> needed.

AFAICT, there is no LITE option the way you have been trying to evolve it. 

> The assumption in the UDP options draft is that a receiver

That’s DOA for legacy receivers.

It also basically kills zero-copy.

> length header such as TCP or IPv4.

There needs to be a justification for giving up the two features above, something beyond “looks”.

I don’t recall seeing one yet - if there is, can you remind me so I can include it in the summary of these excursions?

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 16 Mar 2019 11:37:35 -0700

> That’s DOA for legacy receivers.

Legacy receivers see a UDP datagram with zero payload, just like LITE.

> It also basically kills zero-copy.

Exactly how does it do that?

> I don’t recall seeing one yet - if there is, can you remind me so I can
> include it in the summary of these excursions?
>
> Joe
>
>

---

From: Joe Touch <[email-masked]>
Date: Sat, 16 Mar 2019 12:06:33 -0700

> On Mar 16, 2019, at 11:37 AM, Tom Herbert <[email-masked]> wrote:
> 
> 
> 

I misunderstood payload to also include cases where Len > 8. Fair enough.
> Exactly how does it do that?

Zero copy UDP would need to I’ve the lite payload after it has already been placed in memory. That’s not true for the current approach (it was a design goal, in fact, to allow it).

Joe

---

From: Tom Herbert <[email-masked]>
Date: Sat, 16 Mar 2019 13:20:52 -0700

> Zero copy UDP would need to I’ve the lite payload after it has already been placed in memory. That’s not true for the current approach (it was a design goal, in fact, to allow it).

Joe,

Zero-copy can be used for both send and receive. A good background
description is in https://lwn.net/Articles/726917/

Sending is the easier of the two. Zero-copy send just needs simple
scatter-gather support. There are two buffers, one contains packets
headers and the other contains the data (e.g. a page from the page
cache). Packet in metadata (e.g. an skbuf) looks like
Header_buffer->data_buffer. The protocol headers are arbitrary (TCP,
UDP, IPv6, encapsulation, ULP headers, etc.). Protocol trailers
complicate this since the metadata now looks like
Header_buffer->data_buffer->trailer_buffer. I'm not sure that is
easily supported with current implementations. Also note, in zero copy
we're not allowed to touch the data memory so the byte swap done in
LITE can't be done in the data buffer.

Receive zero copy works in two modes: mapping receive buffers and
header data split. Mapping receive buffers (i.e. to userspace) allows
zero copy. The application gets pointers to data and extent, but they
also can access the headers and possibly data that from previous
received that wasn't overwritten-- so there are security concerns. The
data is rarely aligned to what is most useful for the application
(like we might want the receive data for a disk block to be page
aligned). Header-data split is intended to solve that problem, however
it requires the network device (NIC) to understand the ULP and locate
the application data (naively spitting out UDP or TCP data like some
early NICs did doesn't help). Programmable devices might be help solve
this problem. For protocol trailers, there is a new convolution since
now the device would need to do header-data-trailer split.

A related mechanism is parsing buffer. Parsing buffers are used in
hardware devices that want to inspect the headers of different layers
in a packet. It's basically a cache that contains the first N bytes of
a packet that can be processed. N is something like 128, 256, or more
recently 512 bytes. If the headers they device is interested in is
beyond the extent of the parsing buffer then the device may take some
undesirable action like dropping the packet or relegating it to a slow
software path. Protocol trailers are likely to be a problem for
devices with parsing buffers that want to inspect the trailers.

Tom

---

From: Derek Fawcus <[email-masked]>
Date: Sat, 16 Mar 2019 23:30:48 +0100

> > UDP header (Length=8) | Surplus area header | Options | Payload

Tom,
   I underand this suggestion to be an proposal for an alternate way of
encoding LITE data - i.e. providing a UDP-Lite like service.

If that is incorrect, then please ignore the following.

> Legacy receivers see a UDP datagram with zero payload, just like LITE.

Actually, that is not what LITE does.

LITE as Joe has it (and also my proposed hack to your framing) would
provide the following.

Assume a UDP-Lite like payload, with some payload having checksum
coverage, some being unprotected.

1) Two new peers communicating would see the expected UDP-Lite behaviour.
   The coverred data should arrive, the uncovered data may arrive
   corrupted.

2) For a legacy peer receiving from a new peer, they would only
   receive the portion of the payload having checksum coverage.
   If the packet was sent with UDP CS=0, they'd still receive
   the same data, but without checksum coverage.

   i.e. in effect the packet would arrive truncated, with all of
   the data beyond the coverage length discarded.  So not only
   is it 'corrupted', but the length information is lost.

Depending upon what use is being made of the LITE data,
i.e. some metadata in the checksummed area, that loss may
be significant.  However I'm not sure if it is useful
for a legacy application (as opposed to a legacy UDP stack).

So in effect, the legacy peer only sees the portion of the packet that
is potentially coverred by the checksum coverage field in the UDP-Lite RFC.

With this proposal,  they'd see a zero length packet.

So you need to consider LITE alone separate from LITE+FRAG.
The lattr is currently propoposed for sending Segmented UDP data,
and would have the behaviour you mention.

This is where Mike is suggesting an alternate encoding for
Segmented data using a new FRAG alone scheme; hence in
effect splitting LITE and FRAG in to distinct pure use
cases.

DF

---

From: Tom Herbert <[email-masked]>
Date: Sat, 16 Mar 2019 17:26:39 -0700

> If that is incorrect, then please ignore the following.
Derek,

It's more accurate to say the proposal is a means to extend the UDP header
(emphasis on word "header" here as opposed to using a trailer). The format
is independent of whether a fragment is carried or not. Since the UDP
length is 8, the standard UDP checksum doesn't cover payload inside surplus
area, so the extended header has a checksum covering the payload and
extended header beyond UDP header (ie options would always be covered by
checksum in the same way the IPv4 and TCP options are).

I will post a revised draft for this once upload opens.

Tom

---

From: "C. M. Heard" <[email-masked]>
Date: Mon, 18 Mar 2019 07:42:51 -0700

> length header such as TCP or IPv4.

A major downside to this approach is that is does not let you add
"optional to process" options such as MSS, Echo Request, and Echo
Response to UDP datagrams that are intended to be processed normally
by legacy receivers that do not understand UDP options or the extended
UDP header format. You can do that with the option trailer as
currently proposed.

Mike Heard

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 08:13:47 -0700

> UDP header format. You can do that with the option trailer as

Mike,

The converse is also true. We can't put options in a trailer that
*must* be processed by the receiver (fragmentation, compression,
security, etc.).

Tom

---

From: Gorry Fairhurst <[email-masked]>
Date: Mon, 18 Mar 2019 15:40:29 +0000

I think I missed something between these emails....

On 18/03/2019, 15:13, Tom Herbert wrote:
> On Mon, Mar 18, 2019 at 7:43 AM C. M. Heard<[email-masked]>  wrote:
Right, so this really re-designs UDP as a sublayer to another transport. 
To me, this looks very like an encaps like DCCP-in-UDP or GRE-in-UDP, 
etc. So this isn't an "option" it's an encapsulation.
> *must* be processed by the receiver (fragmentation, compression,
Why this? I thought that if you make a request to negotiate to use say 
enhanced integrity checking or some security option, then you can 
require the option to be present at the receiver?
Am I misunderstanding something?

Gorry

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 08:58:08 -0700

> require the option to be present at the receiver?

Gorry,

How does negotiation work with a transport protocol that is stateless?
Negotiation implies state is maintained between two endpoints.

Tom

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 09:27:14 -0700

> Negotiation implies state is maintained between two endpoints.
Also, if there is a negotiation then there communicating endpoint is
known to not be a legacy receiver so the extended header can be used.
Then if the packet is received by some other legacy node (e.g. because
of VIP, address corruption, peer rebooted and state is lost) the
packet is "dropped" (a zero length UDP datagram is received by the
peer).

Tom

---

From: Gorry Fairhurst <[email-masked]>
Date: Mon, 18 Mar 2019 18:09:49 +0000

On 18/03/2019, 16:27, Tom Herbert wrote:
> On Mon, Mar 18, 2019 at 8:58 AM Tom Herbert<[email-masked]>  wrote:
>> On Mon, Mar 18, 2019 at 8:40 AM Gorry Fairhurst<[email-masked]>  wrote:
So I wa sthinking that the app "knows" what is "negotiated". It could be 
that the app decides it needs security or enhanced integrity check and 
therfore configures to add this at the sender and check at the receiver. 
Whether this "knowing" is hard-coded or uses an upper layer handshake 
isn't so significant to me. An upper layer handshake/protocol could also 
include some sort of fall-back.

For an apps that is itself stateless it just has to be designed to use a 
UDP Option or not. In the same way that it chooses TCP or could use SCTP 
etc.
Gorry

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 13:54:34 -0700

Gorry,

If negotiation is an integral mechanism in UDP options then we really
need the specification for it.

For important options received in a packet (frag, security, integrity
check, etc.) the requirements are straightforward: either the option
is processed and appropriately verified, or the packet must be
dropped. An alternative that allows a receiver to just ignore them and
still receive the data like nothing happened is a non-starter.

For UDP options this means:

1. If there are important UDP options present then the receiver must
process the option space or drop the packet. For this reason,
important options cannot be in trailers (legacy mode in UDP options
draft).
2. If there is an important option that is unknown to the receiver or
can't be processed by the receiver then the packet must be dropped. In
other protocols (e.g. DO, HBH options in IPv6) the option type
includes an indication of what to do if type is unknown to the
receiver (basically skip option or drop). UDP options should adopt
this.
3. Important options themselves need to be protected. We can't allow a
single bit corruption to make an important option just disappear. This
is a motivation for options to always be covered by a checksum. There
is a peculiarity that should be documented in that the checksum might
be used to protect an option holding a stronger integrity check (like
a CRC option).

Tom

---

From: Joe Touch <[email-masked]>
Date: Mon, 18 Mar 2019 17:32:01 -0700

I'm trying to catch up with all the proposals and create a summary.

That said:

1) the notion of soft state and its impact on the protocol is already
mentioned in the draft, as are its limitations

2) we definitely need to stick to some design principles. Some are
already proposed in the draft, but the discussion of late has strayed
far afield of those. In particular, the draft already has a list of
rules for when to drop packets based on various option properties.

If we want to reopen that can of worms, so be it - but until we do, we
need to operate within those parameters. That includes rules for when to
drop (largely determined by receiver configuration of a socket, never
determined by what a sender adds or a flag in the fields).

Joe

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 18:33:58 -0700

> mentioned in the draft, as are its limitations

Is a normative description of UDP option negotiation forthcoming?

> rules for when to drop packets based on various option properties.

But other existing standard protocols that have options already use a
certain set design principles (like skip option bit in HBH and dest
options). It's not clear to me at least why those aren't being followed.

Tom

---

From: Joe Touch <[email-masked]>
Date: Mon, 18 Mar 2019 19:00:31 -0700

On 3/18/2019 6:33 PM, Tom Herbert wrote:
>
>
> On Mon, Mar 18, 2019, 5:32 PM Joe Touch <[email-masked]
> <mailto:[email-masked]>> wrote:
>

We decided on soft state a while ago instead. That's already in the
current descciption.

> options). It's not clear to me at least why those aren't being followed.

Because we're starting with "all options can be silently ignored" to
support consistency with legacy receivers (at least until soft state is
established) . That's NOT where other protocols start. There are several
other places where we diverge (trailer, optional core checksum, etc.).

Joe

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 19:11:41 -0700

> other places where we diverge (trailer, optional core checksum, etc.).

Then you can only send options that can be ignored. If the idea is that
soft state somehow allows sending of options that can't be ignored, that's
fine, but we need the normative description of how soft state works to
evaluate if the requirements are can be meant. This has to include edge
condition handling. UDP is stateless, so inferring connection state from a
5-tuple is perilous. For instance, after a NAT state eviction one side sees
an unchanged tuple, and the other side sees a completely new tuple and
might even be a different host thanks to VIP. How does soft state handle
that?

Joe

---

From: Joe Touch <[email-masked]>
Date: Mon, 18 Mar 2019 19:15:53 -0700

> On Mar 18, 2019, at 7:11 PM, Tom Herbert <[email-masked]> wrote:
> 
> 
> 
> On Mon, Mar 18, 2019, 7:00 PM Joe Touch <[email-masked] <mailto:[email-masked]>> wrote:
> 
> 
>> On Mon, Mar 18, 2019, 5:32 PM Joe Touch <[email-masked] <mailto:[email-masked]>> wrote:
> We decided on soft state a while ago instead. That's already in the current descciption.
> 
>> 
>> But other existing standard protocols that have options already use a certain set design principles (like skip option bit in HBH and dest options). It's not clear to me at least why those aren't being followed.
> Because we're starting with "all options can be silently ignored" to support consistency with legacy receivers (at least until soft state is established) . That's NOT where other protocols start. There are several other places where we diverge (trailer, optional core checksum, etc.).
> 
> 
> Then you can only send options that can be ignored.

You can’t force the behavior a receiver to act other than a legacy UNTIL you get soft-state confirmation otherwise, yes.

> If the idea is that soft state somehow allows sending of options that can't be ignored, that's fine, but we need the normative description of how soft state works to evaluate if the requirements are can be meant. This has to include edge condition handling. UDP is stateless, so inferring connection state from a 5-tuple is perilous. For instance, after a NAT state eviction one side sees an unchanged tuple, and the other side sees a completely new tuple and might even be a different host thanks to VIP. How does soft state handle that?

It won’t work as you want (force drop) until the next ‘refresh’. That’s how soft-state works. 

Joe

---

From: Tom Herbert <[email-masked]>
Date: Mon, 18 Mar 2019 19:32:40 -0700

On Mon, Mar 18, 2019, 7:15 PM Joe Touch <[email-masked]> wrote:

> You can’t force the behavior a receiver to act other than a legacy UNTIL
> you get soft-state confirmation otherwise, yes.
>

> If the idea is that soft state somehow allows sending of options that
> can't be ignored, that's fine, but we need the normative description of how
> soft state works to evaluate if the requirements are can be meant. This has
> to include edge condition handling. UDP is stateless, so inferring
> connection state from a 5-tuple is perilous. For instance, after a NAT
> state eviction one side sees an unchanged tuple, and the other side sees a
> completely new tuple and might even be a different host thanks to VIP. How
> does soft state handle that?
>
>

There's no guarantee between consecutive packets in UDP that the
destination is the same host. Important options must always be sent in a
format that legacy receivers drop. That is rule #1. Rule #2 is that
receivers must drop important options they don't understand. That's simply
addressed by the skip/drop bit in type. Rule #3 is that important options
need integrity check, hence a checksum. These rules are sufficient to meet
the requirements without depending on an external control plane or
configuration.

---

From: Joe Touch <[email-masked]>
Date: Mon, 18 Mar 2019 20:52:54 -0700

> On Mar 18, 2019, at 7:32 PM, Tom Herbert <[email-masked]> wrote:
> ...
> 
> There's no guarantee between consecutive packets in UDP that the destination is the same host.

This is an Internet protocol, which means that it is the responsibility of the hosts that share a single IP address to act as one - not the responsibility of a protocol to overcome that challenge if not supported.

Soft state accomplishes this; the idea is to only do things that you think the other end can tolerate, with the expectation that nothing severe should ever happen, regardless.

> Important options must always be sent in a format that legacy receivers drop. That is rule #1.

They’re in the surplus area; legacy receivers will ignore them, not “drop” the packets they arrive in. This is a known hazard of the LITE option; any receiver that counts packets (i.e., that interprets zero-length packets as having meaning) will be affected by the current proposal for LITE with a zero payload.  We’ve agreed to live with that, though.

> Rule #2 is that receivers must drop important options they don't understand.

Legacy receivers drop all options. There are no “important” options as you define them above; there are “mandatory to implement” options, i.e., if you speak UDP options you must speak those, but that’s it.

> That's simply addressed by the skip/drop bit in type.

A legacy receiver can already “skip all options” and accept a packet, so having a “drop” flag would have an unpredictable effect. What’s the point of that?

> Rule #3 is that important options need integrity check, hence a checksum.

There are no important UDP options, as noted above. 

> These rules are sufficient to meet the requirements without depending on an external control plane or configuration.

External configuration is always important anyway. Senders have to be configured to know what options to use on a given socket. It’s always a receiver’s prerogative to make requirements of received packets anyway. This is no different.

Joe

---

From: Gorry Fairhurst <[email-masked]>
Date: Tue, 19 Mar 2019 08:28:10 +0000

Tom, I don't agree with some of this...

On 18/03/2019, 20:54, Tom Herbert wrote:
> On Mon, Mar 18, 2019 at 11:10 AM Gorry Fairhurst<[email-masked]>  wrote:
I'm really unsure we need much extra.
> important options cannot be in trailers (legacy mode in UDP options
I don't think this is correct.
> receiver (basically skip option or drop).
That makes sense at the network layer - e.g. where a tunnel
does not know what is being transported.

For UDP Options, that operate on endpoints, I can't figure out
why coding for a sending app would add an option and code
for a receiving app would not be correspondingly updated. If they
are different versions of the endpoint code, then that's an app
problem.
> UDP options should adopt this.
You may think so, I don't.
> be used to protect an option holding a stronger integrity check (like
If the app relies on the option - then it will look for it, and discard when
it is not found. That includes if you look for a CRC. The code we have
simply throws the packet when expecting a CRC and not finding one,
as if the CRC were wrong. The checksum provides a pre-check including
the pseudo-header.

If the options space is corrupted then the UDP packet should be thrown
away. (OK, one could have LITE
Gorry

---

From: Tom Herbert <[email-masked]>
Date: Tue, 19 Mar 2019 20:37:37 +0000

Gorry,

Suppose we create a compression option whereby UDP payload is compressed
and decompressed at the receiver. The option must be processed or the
packet containing it must be dropped, lest the application receives
gibberish. Now suppose a host receives a packet with the option, but hasn't
yet implemented it so it is an unknown type. Regardless of whether the
sender is "allowed" to send the option, the robustness principle dictates
that the host needs to be prepared deal with it when it is received. The
correct behavior is that the host drops the packet. It does this because
the option is unknown and it's bad to ignore. So to ensure correct
behavior, either the bit is needed or all packets with any unknown options
need to be dropped.

Tom

> away. (OK, one could have LITE

Right, and the only way to detect a corrupted

---

From: Derek Fawcus <[email-masked]>
Date: Wed, 20 Mar 2019 00:13:09 +0100

On Mon, Mar 18, 2019 at 08:52:54PM -0700, Joe Touch wrote:

[snip - Various statements about the behaviour of legacy receivers]

I have to agree with all of that.

Also the statement which another (I forget who) made about this not
being an encap layer for other arbitrary protocols, so not a layer
over which to lay UDPv2.

We have the DNS request use case, we want to be able to send a packet
containing options expressing that we can receive Segmented UDP data.

A legacy stack, or legacy server on a new stack will not see those
options, but will reply to the basic UDP packet - possibly generating
an IP fragmented response.  A new server on a new stack will be able
to send a UDP segmented response.

There could well be other examples falling in to that scenario.

DF

---

From: Derek Fawcus <[email-masked]>
Date: Wed, 20 Mar 2019 11:07:43 +0100

> There could well be other examples falling in to that scenario.

The above got me wondering about current UDP reflected expansion attacks
using a spoofed source address, of which DNS is a case that has been
exploited.  What we're proposing with the Segmented UDP data mechanism
could be similarly exploited in the future.

So do we need some text in the security considerations section to discuss
this, or maybe even a new cookie option to allow for a form of soft state
acknowledged handshake?

Assume we have an option like:

                   +--------+-------------+-----+------+---------+--
                   | Kind=X | Len=2/4/4+n |  lifetime  |  cookie |
                   +--------+-------------+-----+------+---------+--

                             UDP Cookie option format

Where we have 3 possible lengths, one with no payload, one for sending
lifetime alone, one for sending lifetime and cookie.  The cookie when
present is of variable length.  The no payload form would simply be
used to indicate that the option is supported.

Then for users who might benefit, we could have an exchange like:

1. A -> B : UDP data | Options: Cookie(lifetime-q1)
2. B -> A : UDP data | Options: Cookie(lifetime-r1,cookie-1)
3. A -> B : UDP data | Options: Cookie(lifetime-q2,cookie-1)
4. B -> A : UDP data | Options: Cookie(lifetime-r2,cookie-2)
...
5. B -> A : UDP data | Options: Cookie(lifetime-q3,cookie-2)

at 1 A sends a message, including a desire for a cookie with lifetime q1.
at 2 B responds, including a cookie of arbitrary length and lifetime r1.
at 3 A sends a message, where the cookie inherently validates its source address.
at 4 B responds, including fresh cookie data, but now knowing it can now send
       larger reponses.

i.e. this adds an optional generic 'soft state' connection acknowledge
mechanism to UDP, which could then be used by various applications.

The above could then be combined with sending the Segmentation/FRAG options
to perform parallel negotiation of that capability,  I'd imagine that for
the DNS query case we could end up with something like:

1. A -> B | Q=A, N=example.com, EDNS-sz=Y | Options: Cookie(life); MSS(); FRAG()
2. B -> A | Q=A, N=example.com, EDNS-sz=Y, trunc | Options: Cookie(life,value1); MSS(); FRAG()
3. A -> B | Q=A, N=example.com, EDNS-sz=Y | Options: Cookie(life,value1); MSS(); FRAG()
4. B -> A | | Options: Cookie(life,value2); MSS(); FRAG(Q=A, N=example.com, A=1.2.3.4, EDNS-sz=Z)
...
n. B -> A | | Options: Cookie(life,value2); MSS(); FRAG(Q=A, N=example.com, A=1.2.3.4, EDNS-sz=Z)

For the case of a legacy server, this would probably fall back to one of
IP fragmented UDP response packet at 2 (EDNS support, no truncated response),
or opening a TCP connection at stage 3 (because stage 2 would have been a
truncated response).

i.e. rather than force the client to switch to TCP, or sending an IP fragmented
UDP response, we would be able to acknowledge that it is safe to send a large
amount of DNS response in many segmented UDP packets, that the source of the
query was not spoofed, and then the subsequent second query would trigger that.

I suspect there may be cases where we do not need to segment the response,
but since it would be significantly larger than the request,  such an
acknowledgement pattern may prove useful.

DF

---

From: Tom Herbert <[email-masked]>
Date: Wed, 20 Mar 2019 11:27:17 +0100

Derek,

You might want to look at something similar to QUIC identifiers as the
cookie. That is a much more accuate way to identify and validate a
sender of UDP than by source address which can be unreliable or
inconsistent. For instance, QUIC identifiers handle the common case of
UDP state eviction in NAT where the apparent peer source address
changes mid-flow without any indication to the endpoints that
something happened.

Tom

> ....
> ....

---

From: tjw ietf <[email-masked]>
Date: Wed, 20 Mar 2019 03:35:53 -0700

https://datatracker.ietf.org/doc/rfc7873/

You know of the DNS cookies standard right?

Tim

From my high tech gadget

> On Mar 20, 2019, at 03:07, Derek Fawcus <[email-masked]> wrote:
>

---

From: Derek Fawcus <[email-masked]>
Date: Wed, 20 Mar 2019 12:23:42 +0100

> You know of the DNS cookies standard right?

The point was not protecting DNS per-se, but rather having
a generic mechanism usable by all applications.

Especially if UDP segmentation was going to be employed.

DF

---

From: Joe Touch <[email-masked]>
Date: Wed, 20 Mar 2019 07:25:07 -0700

> On Mar 19, 2019, at 1:37 PM, Tom Herbert <[email-masked]> wrote:
> 
> Gorry,
> 
> Suppose we create a compression option whereby UDP payload is compressed and decompressed at the receiver.

See the rules in Section 7 - which are there specifically to avoid this sort of tangle.

Joe

---

From: Joe Touch <[email-masked]>
Date: Wed, 20 Mar 2019 07:26:32 -0700

> On Mar 20, 2019, at 3:07 AM, Derek Fawcus <[email-masked]> wrote:
> 

Soft state can be accomplished in a variety of ways; there’s no reason to force a single way of doing this.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Wed, 20 Mar 2019 15:34:17 +0100

On Wed, Mar 20, 2019 at 3:25 PM Joe Touch <[email-masked]> wrote:
>From section 7:

>> At the sender, new options MUST NOT modify UDP packet content
   anywhere except within their option field; areas that need to remain
   unmodified include the IP header, IP options, the UDP body, the UDP
   option area (i.e., other options), and the post-option area.

So that would seem to mean we'll never be able to add any interesting
options like the payload compression I described.

---

From: Joe Touch <[email-masked]>
Date: Wed, 20 Mar 2019 07:58:45 -0700

> On Mar 20, 2019, at 7:34 AM, Tom Herbert <[email-masked]> wrote:
> 

Yes, but for a very specific reason.

If you do, you then have to decide on what content every other option would operate - pre-compression or post. I suspect you’d say pre, but if more than one option does that, you’re dead.

Joe

---

From: Tom Herbert <[email-masked]>
Date: Wed, 20 Mar 2019 16:06:54 +0100

Joe,

The order of the options can dictate how the operations are applied to
the data. In any case, I think this is unnecessarily limiting the
extensibility of the protocol, and it's divergent compared to other
protocols containing options like destination, HBH options, Geneve
options, TCP, that don't have this limitation. It will be interesting
to see what the consensus of the WG will be on this.

Tom

---

From: Gorry Fairhurst <[email-masked]>
Date: Wed, 20 Mar 2019 15:09:29 +0000

On 20/03/2019, 14:58, Joe Touch wrote:
>
>> On Mar 20, 2019, at 7:34 AM, Tom Herbert<[email-masked]>  wrote:
>>
>> On Wed, Mar 20, 2019 at 3:25 PM Joe Touch<[email-masked]>  wrote:
>>>
>>>
>>> On Mar 19, 2019, at 1:37 PM, Tom Herbert<[email-masked]>  wrote:
>>>
>>> Gorry,
>>>
I'm not so sure we can "never" do this - but I agree we should choose 
not to do this now. UDP-Options already provides lots of functions. I'm 
very keen on getting some things well defined and implemented and then 
thinking - rather than just trying to design for every possibility.

Gorry