Subject: Re: [core] WG Last Call on draft-ietf-core-new-block

From: Christian Amsüss <[email-masked]>
Date: Wed, 17 Feb 2021 01:25:55 +0100

Hello Jon,
and hello Michael (grep for MCR, first point could use your response),

thanks for your responses and updates; on these concrete points, the
only that remain are:

> > * "If there is insufficient space to create a response PDU": I don't
> >   understand what that means. (Where are request options reflected
> >   back?).
> 
> [Jon] This was triggered by a question by Michael Richardson " So, given a
> Christmas-Tree-Packet (largest packet, every possible option space used,
> every extension turned on...) how much data can I get back? :-)" and not
> fully thought through.
> It could happen though with Location-Path, Location-Query, Q-Block2, ETag,
> Size2 and possibly Maxage, Content-Type, Hop-Limit or OSCORE  in response to
> a POST.
> OLD
>    If there is insufficient space to create a response PDU with a block
>    size of 16 bytes (SZX = 0) to reflect back all the request options as
>    appropriate, a 4.13 (Request Entity Too Large) is returned without
>    the Size2 Option.
> NEW
>    If there is insufficient space to create a response PDU with a block
>    size of 16 bytes (SZX = 0) to send back all the response options as
>    appropriate, a 4.13 (Request Entity Too Large) is returned without
>    the Size1 Option.

I think that is a corner case that deserves an error in *every* CoAP
based protocol and is not specific to it; MCR do you think that this
comment needs to be resolved in this way?

> > * "For NON transmissions": This seems to imply that the full exchange of
> >   a body is either NON or CON; I don't see where that'd come from. I'd
> >   have expected to read something like "Each individual request can be
> >   NON or CON independent of the others. In particular, it can be
> >   convenient to send the ultimate payload...".
> 
> [Jon]The DOTS environment will only be using NON.  To make Congestion
> Control simple,
> the expectation is that all transmissions are NON or (not recommended) are
> all CON. The draft now generally records this expectation.

Then why spend time talking about CON in the first place, and risk that
things go awry in a case that's neither tested nor really specified for?

It may be worth considering (ie. working group discussion; next interim
maybe?) to just state that this works with NON only.

I do see potential for the use of CON and NON mixed (in particular, the
"but it doesn't have a dual version for server pushes" you dread of
No-Response problem might go away), but if it's not explored to fruition
in the problem set out for this document, confirmable messages may be
better ruled out at all rather than getting second-class treatment.

> > Caching:
> > 
> > * "are not part of the cache key": How about "are removed as part of the
> >   block assembly and thus do not reach the cache"?
> 
> [Jon] OK.
> OLD
>    As the entire body is being cached in the proxy, the Q-Block1 and
>    Q-Block2 Options are not part of the cache key.
> NEW
>    As the entire body is being cached in the proxy, the Q-Block1 and
>    Q-Block2 Options are removed as part of the
> block assembly and thus do not reach the cache.

It may help to make the same statement about Request-Tag; then, there is
no more (IMO questionable) SHOULD about "a new Request-Tag [being]
generated", and the "Ideally" sentence can be dropped too.

> >     Generally, the all-NON and all-CON examples don't look to me like
> >     what I'd be doing with this spec; the mixed "a CON every
> >     MAX_PAYLOADS" appears much more realistic.
> 
> [Jon] It is unsafe to use CON in the  (potentially lossy) DOTS environment
> (up to 93 secs timeout per payload with the defaults).  Hence why we are
> separating out the NON / CON usage.

See above: then maybe don't do it at all.

(Also, in the "not related to previous points" follow-up mail to come,
there are some CON related questions that might be moot then).

Best regards
Christian

-- 
To use raw power is to make yourself infinitely vulnerable to greater powers.
  -- Bene Gesserit axiom

---

From: Christian M. Amsüss <[email-masked]>
Date: Thu, 18 Feb 2021 14:31:40 +0100

Picking a quick one because I don't know when I'll get to the rest:

> > * 4 the new 4.08 format: Since this is a CBOR sequence, the
> >   implementation note on telling the array length in advance does not
> >   apply. As for the CDDL, I don't know whether the array format is OK to
> >   use for the sequence, or whether the CBOR
> 
> [Jon] Not sure what you are trying to ask here.  I know we removed the
> Request-Tag from the CDDL which may have changed things.

If the array were sent in CBOR, indeed the sequence 1, 10, 20 would look
like this (courtesy of cbor.me):

83    # array(3) <--- here is where you need to know the length in advance
   01 # unsigned(1)
   0A # unsigned(10)
   14 # unsigned(20)

But as the content format is a cbor-sequence one, what you actually send
is this:

   01 # unsigned(1)
   0A # unsigned(10)
   14 # unsigned(20)

(No array header, just a sequence of self-delimited items).

So now the implementer's worst worry is that if they start writing an
item in the last byte and the item needs a u16 they gotta roll back, but
that is simple. Picking the array length in advance would be hard (and
the implementation note's suggestion of not exceeding 23 items would
apply), but by using a CBOR sequence you're already free of that.

BR
c

---

From: <[email-masked]>
Date: Thu, 18 Feb 2021 13:19:23 -0000

Hi Christian,

Thanks for taking the time to review this.

See inline [Jon]

Changes can be seen at https://tinyurl.com/new-block-latest 

Regards

Jon

> -----Original Message-----
> From: Christian Amsüss [mailto: [email-masked]]
> Sent: 17 February 2021 00:26
> To: [email-masked]; [email-masked]
> Subject: Re: [core] I-D Action: draft-ietf-core-new-block-06.txt
> 
> Hello new-block authors,
> 
> here a few notes that I didn't see fitting any of the previous threads 
> (or so I
> hope):
> 
> * "can fall back to using Block1 and Block2 Options, respectively": Even
>   though the rest says (as agreed on) that it's both-or-none, the
>   "respectively" seems to imply otherwise -- maybe just drop the word.

[Jon] "respectively" dropped
> 
> * CSM option: "There is little, if any, benefit of using these options
>   with [reliable transports]" ... and reliable transports are the only
>   thing CSMs are defined for. So why define a CSM if it's not expected
>   to be useful?

[Jon] This is here for completeness.  DOTS tries to use UDP, but falls back
to using TCP if unable to use UDP. 

> 
> * Ad Class E/U: It may be worth stating that it *is* allowed to mix
>   Block and Q-Block when one is inner and the other is outer -- for the
>   simple reason that there'd be no way to enforce anything else, for
>   proxies along the path can perform outer-blockwise transfers in
>   ignorance of the content.
> 
>   (Then, at a receiver, an outer Block option could arrive, and when
>   that's done, it should still process the inner Q-Block without erring
>   just because the two worlds met).

[Jon] Good point.
OLD
Note that if Q-Block1 (or Q-Block2) Option is included in a packet, Block1
(or Block2) Option MUST NOT be included.
NEW (moved to after the OSCORE statement)
Note that if Q-Block1 or Q-Block2 Options are included in a packet as Inner
options, Block1 or Block2 Options MUST NOT be included as Inner options.
Similarly there MUST NOT be a mix of Q-Block and Block for the Outer
options. Q-Block and Block Options can be mixed across Inner and Outer
options as these are handled independently of each other.
> 
> * 3.3 Use of the QB1 option:
> 
>   The rules for the final message are different between 2.04 Changed
>   ("token SHOULD be from the last received payload") and 2.05 Content
>   (~"MUST be the one in the final block"). Any reason for that?

[Jon] The original thinking  was that with FETCH and Observe, the server
needs a token for sending back any Observes.  The client needs to know the
exact token that will get used for matching up any Observe responses.  Hence
the MUST.  However, see next response.

> The
>   former sounds more sensible. (I originally favored the latter, but
>   then when a 4.08 comes back on the last-block request, the same token
>   would need to be used for the final successful response too, and
>   that'd be awkward -- and I'd prefer to avoid it if we can pick the one
>   rule set ("SHOULD from the last received") that allows having only one
>   response per token unless there are actually multiple blocks
>   transported on it).

[Jon] It is true that the final block can be sent, and then re-requested, so
the server does not know which token to pick for the Observe in this case.
OLD
This Response Code indicates successful receipt of the entire FETCH request
body (Section 2 of [RFC8132]) and the appropriate representation of the
resource is being returned. The token used in the response MUST be the one
in the FETCH request that has the Q-Block1 with the M bit unset. If the
FETCH request includes the Observe Option, then the server MUST use the same
token for returning any Observe triggered responses.
NEW
This Response Code indicates successful receipt of the entire FETCH request
body (Section 2 of [RFC8132]) and the appropriate representation of the
resource is being returned. The token used in the response SHOULD be from
the last received payload. If the FETCH request includes the Observe Option,
then the server MUST use the same token for returning any Observe triggered
responses so that the client can match them up.

> 
> * 3.5 Block + Observation: Has this been implemented and tested? The
>   combination of Block1(!)+Block2+Observer is already tricky with
>   regular blocks, and made harder by the semi-noresponse blocks here.
> 
>   Unless you have a use case for it, I'd ask to see this implmeneted
>   before it is published, or else to leave this as "interactions are up
>   to further specification" (with a corresponding note in the
>   ups-and-downs list) in the interest of getting this on speedily (given
>   this document's purpose is to get the DOTS use case running).

[Jon] Yes, this has been implemented and tested.  
> 
> * The 2.31 Continue rules: Why not send it with CON? A 2.31 Continue is
>   just as compact as an ACK, and can convey to the client that all
>   packages up to that point have been received, so it doesn't need to
>   retransmit the earlier ones even though the corresponding ACK may have
>   gotten lost.

[Jon] For DOTS, we have to have the entire conversation for the transmission
of the telemetry data as NON, as there could be a flooded pipe in one
direction because of a DDoS attack.

> 
> * The new QB2 M-bit rules depend on MAX_PAYLOADS to be agreed. But 
> that
>   agreement is SHOULD only, and even that's already stretching what I'd
>   expect of a configurable CoAP parameter.

[Jon] Having the flexibility and ability to configure the actual value and
mutually agree on the new value could beneficial to DOTS (clients on low
bandwidth networks may want to tune it down as suggested as per:-

"If the CoAP peer reports at least one payload has not arrived for each body
for at least a 24 hour period and it is known that there are no other
network issues over that period, then the value of MAX_PAYLOADS can be
reduced by 1 at a time (to a minimum of 1) and the situation re-evaluated
for another 24 hour period until there is no report of missing payloads
under normal operating conditions. The newly derived value for MAX_PAYLOADS
should be used for both ends of this particular CoAP peer link. Note that
the CoAP peer will not know about the MAX_PAYLOADS change until it is
reconfigured. As a consequence of not being reconfigured, the peer may
indicate that there are some missing payloads prior to the actual payload
being transmitted as all of its MAX_PAYLOADS payloads have not arrived."

> 
>   It's also rather complicated. How is this better than a simple "M=1
>   means this block plus as many as you can comfortably send, where M=0
>   is for this one only"?

[Jon] We still need to have a concept of 'Continue' to reduce any
NON_TIMEOUT delays for every MAX_PAYLOADS for handling congestion control.
'Continue' is used in multiple places in the draft.

> 
> * "is meant to prevent amplification attacks": Could you elaborate? A
>   client permitted the use of QB2 has already some leverag on the server
>   to start attacks, and would in any case (overlaps or not) only be
>   permitted MAX_PAYLOADS on a single request by the server, no matter
>   how it requests more than that.

[Jon] A single request, containing multiple Q-Block2 with M set and the same
NUM (0 meaning all blocks is a really bad case) would otherwise (no overlap
protection) cause MAX_PAYLOADS to be sent, NON_TIMEOUT pause, next set of
MAX_PAYLOADS, NON_TIMEOUT pause etc. for quite some time.  Request packet of
1k+, each Q-Block2 being 2 bytes gives 500+ requests for lots of packets.
Yes, there are NON_TIMEOUT gaps giving respite against a single request, but
multiple requests would average things out.

> 
> * "then the body response SHOULD be restarted with a different ETag
>   Option value": That behavior sounds like a recipe for endless running
>   requests when CON is involed (which, granted, are under flow control,
>   but still don't do anything useful). Given there is also a
>   recommendation to keep the being-transmitted version alive, why not
>   just stop the transmission?  Or send just one final block of the new
>   value -- and then it's up to the client to decide whether that's a
>   representation it already knows (and just got a freshness statement
>   for) or needs to get it as a whole again?

[Jon] My implementation maintains the cached body as per previous
RECOMMENDED statement which keeps things simple.  I was then trying to cover
the non-cached copy case.  I agree with your concern.

[Jon] From the client's perspective, ETag is opaque with no way of knowing a
newly seen ETag is earlier or later.  If a NON (old) ETag is out of sequence
on arrival or there is a CON retransmit with an (old) ETag the client has to
make a decision on seeing the (old) ETag (which may be for a single packet
that holds the whole body and hence is not in the clients history).  Does
the current receipt of multiple payloads get aborted or ... when the (old)
ETag is seen?

[Jon] The new data length may be less than the previous payload, and so the
currently being transmitted block is beyond the size of the new data.

[Jon] The (needs terminating) response can be for something other than a
GET, making it a bit more problematic for the client to continue -
especially if there is non-idempotent usage.

[Jon] Two ways forward here
1. Make previous statement a MUST and delete this statement Or 2.
OLD
If the server detects part way through a body transfer that the resource
data has changed and the server is not maintaining a cached copy of the old
data, then the body response SHOULD be restarted with a different ETag
Option value. Any subsequent missing block requests MUST be responded to
using the latest ETag Option value.
NEW
If the server detects part way through a body transfer that the resource
data has changed and the server is not maintaining a cached copy of the old
data, then the transmission is terminated.  Any subsequent missing block
requests MUST be responded to using the latest ETag and Size2 Option values
with the updated data.

[Jon] Preferences ?
> 
> * 3.6 Size1/2: These options MUST be used per 3rd paragraph, so the "If"
>   in the 4th is odd.
> 
> * (General wording: It's "A comprise X and Y" or "A is comprised of X
>   and Y"; https://en.wiktionary.org/wiki/comprise#Usage_notes "in the
>   passive voice")

[Jon]
OLD
The Size1 Option MUST be used with the Q-Block1 Option when used in a
request. The Size2 Option MUST be used with the Q-Block2 Option when used in
a response.

If Size1 or Size2 Options are used, they MUST be used in all payloads of the
body and MUST preserve the same value in each of those payloads.
NEW
The Size1 Option MUST be used with the Q-Block1 Option when used in a
request and MUST be present in all payloads of the request preserving the
same value. The Size2 Option MUST be used with the Q-Block2 Option when used
in a response and MUST be present in all payloads of the response preserving
the same value.

> 
> * 5. Use of Tokens: The MUST on the unique tokens misrepresents
>   echo-request-tag. There are rules there about when a token can or can
>   not be reused, and they depend on factors immaterial to the present
>   specification.
> 
>   In particular, when used with CoAP-over-TLS or with OSCORE, using
>   non-unique tokens is quite alright.
> 
>   I recmomend not making a normative statement where none is required;
>   eg.
> 
>   "Each new request generally uses a new Token (and sometimes must, see
>   Section 4 of ERT).  Additional responses to a request all use the
>   token of the request they respond to".

[Jon] Gone with your suggestion.
> 
> * "Implementation Note: To minimize": I'd prefer to go with "it is
>   suggested" rather than "recommended", but as long as it's not in
>   normative language, I don't care too much.

[Jon] Ok
> 
> * "Servers continue to treat": While not factually incorrect considering
>   the above recommendation, the reference to the 32 bits in the
>   paragraph about the server is confusing. Last prenthized expression
>   could read "(i.e., is sent on the token of the request that caused
>   its retransmission)".

[Jon]
OLD
To minimize on the number of tokens that have to be tracked by clients, it
is recommended that the bottom 32 bits is kept the same for the same body
and the upper 32 bits contains the current body's request number
(incrementing every request). This allows the client to be alleviated from
keeping all the per-request-state, e.g., in Section 3 of [RFC8974].

Servers continue to treat the token as a unique opaque entity. If an
individual payload has to be resent (e.g., requested upon packet loss), then
the retransmitted packet keeps the same bottom 32 bits and the upper 32 bits
is incremented.
NEW
To minimize on the number of tokens that have to be tracked by clients, it
is suggested that the bottom 32 bits is kept the same for the same body and
the upper 32 bits contains the current body's request number (incrementing
every request, including for every re-transmit). This allows the client to
be alleviated from keeping all the per-request-state, e.g., in Section 3 of
[RFC8974].

> 
> * (I skipped through the congestion contol section for the time being;
>   it's probably best read by someone with some experience in congestion
>   control which I lack).

[Jon] Noted.
> 
> * "When the next client completes building the body, any existing
>   partial body transmission to the CoAP server is terminated": Just a
>   note, you're already using Request-Tag, so you could leave it up to
>   the proxy to try to run them simultaneously (it obviously can, as it
>   already got to the point of having both request bodies loaded in
>   full). The server can then still cancel one or postpone the other.

[Jon] If the proxy uses multi-plexing client logic to talk to a singular
server with a common 'CoAP session', it has to determine which body entity
to terminate - and may chose the wrong one based as timing, whereas it is
simpler to get the proxy to make the correct decision.
> 
> * Figure 6: The first line says "for RT=11", that's probably a remnant
>   from when the Request-Tag was copied into the payload. (Same for later
>   '[for RT=...]' items

[Jon] Fixed
~Jon

---

From: <[email-masked]>
Date: Thu, 18 Feb 2021 16:37:32 -0000

Hi Christian,

We are following https://tools.ietf.org/html/rfc8742#section-4.1 here.  CDDL
does not support a notation for top-level CBOR sequences so have gone with
the recommendations of this section.

As CDDL defines it as an array using the documentation text "This defines an
array, the elements of which are to be used in a CBOR Sequence:", I am
thinking that we need to keep it as an array.

I guess that we need an expert understanding of what to do here.
- Maybe leave out the CDDL definition and give an example?

Regards

Jon

> From: Christian M. Amsüss [mailto: [email-masked]]
> Sent: 18 February 2021 13:32
> To: [email-masked]
> Cc: [email-masked]; [email-masked]; [email-masked]
> Subject: Re: [core] WG Last Call on draft-ietf-core-new-block
> 
like this
> (courtesy of cbor.me):
is this:
> So now the implementer's worst worry is that if they start writing an item
in the
> last byte and the item needs a u16 they gotta roll back, but that is
simple. Picking
> the array length in advance would be hard (and the implementation note's
> suggestion of not exceeding 23 items would apply), but by using a CBOR
> sequence you're already free of that.
> 
> BR
> c
> 
> --

---

From: Christian M. Amsüss <[email-masked]>
Date: Thu, 18 Feb 2021 17:43:46 +0100

Hello Jon,

> - Maybe leave out the CDDL definition and give an example?

the CDDL definition is fine and following the state-of-the-art
workaround.

But what it means is that the array wrapping is only there on paper to
make the CDDL happy. And as the array header does not hit the wire (and
is not generally constructed in memory either), the implementation note
is moot.

BR
c

---

From: <[email-masked]>
Date: Thu, 18 Feb 2021 17:00:55 -0000

Hi Christian,

> the CDDL definition is fine and following the state-of-the-art workaround.
>
make the
> CDDL happy. And as the array header does not hit the wire (and is not
generally
> constructed in memory either), the implementation note is moot.

Happy to remove the (actual) array wrappers and associated stuff despite
CDDL documentation text.

I think I will add in an example to keep me happy by removing any ambiguity
about the array.

Regards

Jon

---

From: <[email-masked]>
Date: Fri, 19 Feb 2021 09:47:37 -0000

Hi Christian,

I have gone with just updating the wording.

Changes can be found at https://tinyurl.com/new-block-latest for page 16.

Regards

Jon

> From: [email-masked] [mailto:ietf-supjps-supjps-
> [email-masked]]
> Sent: 18 February 2021 17:01
> To: [email-masked]
workaround.
> _______________________________________________
> core mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/core