Question: The initiator uses information from the peer's certificate to verify the delegated credential and that the peer is asserting an expected identity, determining an authentication result for the <del> peer.. </del> <ins> peer. </ins> Peers accepting the delegated credential use it as the certificate key for the (D)TLS handshake.

Nits/editorial comments: Abstract: The exact form of the abbreviation (D)TLS is not in the set of well-known abbreviations. I assume it is supposed to mean DTLS or TLS - This ought to be expanded on first use. Abstract: s/mechanism to to/mechanism to/ s1, para 2: CA is used before its expansion in para 3. s1, next to last para: "this document proposes" Hopefully when it becomes an RFC it will do more than propose. Suggest "this document introduces". s1, next to last para: "to speak for names" sounds a bit anthropomorphic to me, but I can't think of a simple alternative word. s1, last para: s/We will refer/This document refers/ [Not an academic paper!] s3.1, 2nd bullet: s/provide are not necessary/provide is not necessary/ s4, definition of expectedcertverify_algorithm: " Only signature algorithms allowed for use in CertificateVerify message are allowed." Does this need a reference to the place where the list of such algorithms is recorded? s4.1.1 and s4.1.2: In s4.1.1: "the client SHOULD ignore delegated credentials sent as extensions to any other certificate." I would have though this ought to be a MUST. There is an equivalent in s4.1.2. I am not sure what the client/server might do if it doesn't ignore the DC. s4.1.3, para 1: s/same way that is done/same way that it is done/ s4.2, para 1: s/We define/This docuent defines/ sS/s5.1: RFC conventions prefer not to have sections empty of text: Add something like: "The following operational consideration should be taken into consideration when using Delegated Certificates:"


Question: Application messages <del> The sender information used to look up the key for the content encryption is encrypted under AEAD using a random nonce and the "sender_data_key" which is derived from the "sender_data_secret" as follows: </del> <ins> The sender information used to look up the key for content encryption is encrypted with an AEAD where the key and nonce are derived from both "sender_data_secret" and a sample of the encrypted message content. </ins> For handshake and application messages, a sequence of keys is derived via a "sender ratchet".  Each sender has their own sender ratchet,

Just to recap the options as I understand them: a) Today: encryptedsenderdata = AEAD(senderdatakey, senderdatanonce, (groupID, epoch), senderdata) encryptedcontent = AEAD(appkey[i][j], appkey[i][j], (groupID, epoch, encryptedsenderdata), content) b) Sample sender data nonce from ciphertext (saves explicit nonce) encryptedcontent = AEAD(appkey[i][j], appnonce[i][j], (groupID, epoch), content) encryptedsenderdata = AEAD(senderdatakey, sample(encryptedcontent), (groupID, epoch, encryptedcontent), senderdata) c) Drop auth tag from content encryption (saves explicit nonce and content auth tag) encryptedcontent = Enc(appkey[i][j], appnonce[i][j], content) encryptedsenderdata = AEAD(senderdatakey, sample(encryptedcontent), (groupID, epoch, encryptedcontent), senderdata)
Earlier, we had considered a "masking" approach for sender data, much like QUIC does for . This approach would save 28 bytes of overhead (nonce + tag), but was abandoned because of uncertainty around the security of the masking approach. Since then, Bellare et al. published , which includes what is effectively a proof of the security properties of the QUIC scheme. The QUIC scheme is essentially scheme HN1 of the paper, the main difference being that QUIC encrypt not the nonce directly, but a packet number which is used to compute the nonce. Our application would be similar, since we would encrypt metadata used to encrypt the key and the nonce. Given this new analysis, is it time to bring back masking?
Fixed by


Question: consider congestion control aspects when proposing coding solutions. The proposed recommendations apply for coding at the transport or <del> application layer and coding for tunnels is out-of-the scope of the </del> <ins> application layer.  Coding for tunnels is out of scope for the </ins> document. 2. fig:sep-channel presents the notations that will be used in this document and introduce the Congestion Control (CC) and Forward <del> Erasure Correction (FEC) channels.  Congestion Control channel carries data packets (from the server to the client) and a potential </del> <ins> Erasure Correction (FEC) channels.  The Congestion Control channel carries data packets (from a server to a client) and a potential </ins> information signaling the packets that have been received (from the <del> client to the server).  Forward Erasure Correction channel carries coded packets (from the server to the client) and a potiential information signaling the packets that have been repaired (from the client to the server).  It is worth pointing out that there are cases where these channels are not separated. </del> <ins> client to the server).  The Forward Erasure Correction channel carries coded packets (from the server to the client) and a potiential information signaling the packets that have been repaired (from the client to the server).  It is worth pointing out that there are cases where these channels are not separated. Inside a host, the CC and FEC entities can be regarded as conceptually separate: As this diagram shows, the inputs to FEC (data to work upon, and signaling from the receiver about losses and/or repaired blocks) are distinct from the inputs to CC.  The latter calculates a sending rate or window from network measurements, and it takes the data to send as input, sometimes along with application requirements such as upper/ lower rate bounds, periods of quiescence, or a priority. It is not clear that the ACK signals feeding into a congestion control algorithm are useful to FEC in their raw form, and vice versa - information about repaired blocks may be quite irrelevant to a CC algorithm.  However, there can be meaningful other interactions (indicated by the horizontal double arrow) between the two entities, usually as a result of their operation rather than by relaying their own raw inputs.  For example, the network measurements carried out by CC can yield a longer-term statistical measure such as a loss ratio which is useful input for a FEC coding scheme.  Similarly, unequal error protection using fountain codes can be used to assign different priorities to blocks of data, and these priorities can be honored by a CC mechanism. </ins> 3.

This proposes a complete re-vamp of the document. I would also suggest to completely remove sections 6 and 7, but rather than doing this yet, I inserted comments that explain why.
Le 17/01/2020 à 09:28, mwelzl a écrit : Yes ! Definitely agree.
Le 17/01/2020 à 13:50, francoismichel a écrit : OK for me.


Question: length is a uint defined by the application <del> PRK_exporter is derived from PRK_out: where hash_length denotes the output size in bytes of the EDHOC hash algorithm of the selected cipher suite. </del> The (exporter_label, context) pair used in EDHOC_Exporter must be unique, i.e., an (exporter_label, context) MUST NOT be used for two different purposes.  However an application can re-derive the same

I strongly think that all 10 EDHOC-KDF should be in the same table The text about maclengthx need to use the defined term hash_length
I made one commit for review.


Question: timestamp of the event, Client visible information (including the IP address), and the Origin name. <del> The challenge controls the type of token that the Origin will accept for the given resource.  As described in AUTHSCHEME, there are a number of ways in which the token may vary, including: </del> <ins> The challenge provides the client with the information necessary to obtain tokens that the server might subsequently accept (in this context).  As described in AUTHSCHEME, there are a number of ways in which the token may vary, including: </ins> Issuance protocol.  The token identifies the type of issuance protocol required for producing the token.  Different issuance

Is really true? A challenge is just a declaration from the Origin about what the Client should offer. It exerts no control. I would have thought that the arrangement is thus: The Origin determines what sorts of token are acceptable, including whether a token is necessary. This might incorporate any contextual information and so could change between different Clients or over time. A valid token includes information that an Origin can use to validate it against its policies. This includes all the stuff in the list that follows the quoted text (issuance protocol, issuer, redemption context, origin). Importantly, it does not carry information that directly identifies the Client to any entity other than the Origin; this being the primary privacy benefit to Clients. If the Origin determines that a token is necessary it can issue a challenge to the Client. This challenge might imply that a token that meets these constraints would be acceptable, but see the first point (i.e., the Origin can change its mind). There should be enough information in the challenge for the Client to obtain a token under reasonable assumptions (the Client understands the request and meets the requirements for token issuance). Clients can pre-emptively request token issuance. This might be based on a previous indication that this might work. (I see some caching in the trust tokens API.)
I'm probably missing the confusion that led to this issue. The arrangement you describe is true, and in that arrangement the only tokens that will be accepted for an Origin are those which verify with a valid challenge. That means the challenge determines how the client produces a valid token. For example, the challenge indicates the token type and therefore the issuance protocol required to produce a token. It also indicates a redemption context and therefore whether or not clients can preemptively request and cache tokens to amortize the cost of issuance. I don't think a challenge is just a declaration of what the Client should offer. To me, challenges fundamentally determine the set of possible tokens that clients can produce, and that implies some level of control. If "control" is somehow problematic or confusing, perhaps we just phrase this differently. That might be "The challenge determines the set of tokens the Origin will accept for the given resource. This is because tokens cryptographically bind the challenge to a client-chosen nonce."


Question: timestamp of the event, Client visible information (including the IP address), and the Origin name. <del> The challenge controls the type of token that the Origin will accept for the given resource.  As described in AUTHSCHEME, there are a number of ways in which the token may vary, including: </del> <ins> The challenge provides the client with the information necessary to obtain tokens that the server might subsequently accept (in this context).  As described in AUTHSCHEME, there are a number of ways in which the token may vary, including: </ins> Issuance protocol.  The token identifies the type of issuance protocol required for producing the token.  Different issuance

As far as I can tell, yes, challenges do constrain what a client can produce in that in order to produce some tokens you need a challenge. However, the text here might be read to imply that it constrains the server in terms of what it might accept in the future. So yeah, using "control" is problematic as it too directly implies a link between the signal and the server actions that follow. I would have said that maybe "A challenge provides the client with the information necessary to obtain tokens that the server might subsequently accept (in this context)."
That works for me! I'll send a PR.


Question: In some circumstances, the information needed at a given stage is communicated out of band or is preconfigured between the components <del> or entities performing the roles.  For example, one entity can fulfil multiple roles, and so explicit communication between the roles is not necessary within the protocol flow.  Additionally some components may not be involved in all use cases.  For example, a client instance could be calling the AS just to get direct user information and have no need to get an access token to call an RS. </del> <ins> or entities performing the roles.  For example, one entity can fulfill multiple roles, and so explicit communication between the roles is not necessary within the protocol flow.  Additionally some components may not be involved in all use cases.  For example, a client instance could be calling the AS just to get direct user information and have no need to get an access token to call an RS. </ins> 1.5.1.

Deploy Preview for gnap-core-protocol-editors-draft ready! Explore the source changes: 180278a02620d6e193b78d72e2dae6d0aa5c5c4e Inspect the deploy log: Browse the preview:


Question: methods: If interaction finishing is supported for this client instance and <del> request, the AS response-interact-finish used by the client instance to validate the callback.  Requests to the callback URI MUST be processed as described in interaction-finish, and the AS MUST require presentation of an interaction callback reference as described in continue-after-interaction. </del> <ins> request, the AS will response-interact-finish used by the client instance to validate the callback.  All interaction finish methods MUST use this nonce to allow the client to verify the connection between the pending interaction request and the callback.  GNAP does this through the use of the interaction hash, defined in interaction- hash.  All requests to the callback URI MUST be processed as described in interaction-finish. All interaction finish methods MUST require presentation of an interaction reference for continuing this grant request.  This means that the the interaction reference MUST be returned by the AS and MUST be presented by the client as described in continue-after- interaction.  The means by which the interaction reference is returned to the client instance is specific to the interaction finish method. </ins> 2.5.2.1.

NAME Please take a look at this updated text to see if it addresses your concerns.
To edit notification comments on pull requests, go to your .
Thinking about possible extensions to GNAP's interaction modes, I had the impression that the specification could be a bit clearer regarding requirements on such extensions. From reading Section 3.3, my understanding is that all implementations of GNAP, including ones using extensions which define additional interaction finish methods, MUST include a nonce in the grant response (given that the AS wants to use the finish method offered by the client instance): URL However, Section 3.3.5 sounds a bit different, only referring to the two interaction finish methods defined by GNAP core: URL Section 4.2 could be a bit clearer as to what is expected of future extensions to GNAP, it currently says: URL with the two following sections describing the finish methods defined by GNAP core. This is, however, somewhat clearer in Section 4.2.3: I.e., Section 4.2.3 implies that AS must (somehow) provide the client instance with an interaction reference and interaction finish nonce. But it may be helpful to make this more explicit throughout the relevant Sections. There seem to be no requirements for future interaction start methods. It may be helpful to document some minimal requirements, e.g., enough information to identify the grant has to be conveyed to AS via RO in the interaction start (such as the redirect URI in GNAP core).
Thanks NAME for taking the time! The proposed text looks good to me (just one possible typo, I'm not a native speaker, so I'm not 100% sure about that).


Question: 5.2. <del> min_rtt is the minimum RTT observed for a given network path. min_rtt is set to the latest_rtt on the first RTT sample, and to the lesser of min_rtt and latest_rtt on subsequent samples.  In this document, min_rtt is used by loss detection to reject implausibly small rtt samples. </del> <ins> min_rtt is the sender's estimate of the minimum RTT observed for a given network path.  In this document, min_rtt is used by loss detection to reject implausibly small rtt samples. min_rtt MUST be set to the latest_rtt on the first RTT sample. min_rtt MUST be set to the lesser of min_rtt and latest_rtt (latest- rtt) on all other samples. </ins> An endpoint uses only locally observed times in computing the min_rtt and does not adjust for acknowledgment delays reported by the peer.

I believe this covers the discussion on the issue. It also introduces some MUSTs which should've always been there. I don't have a strong opinion on the use of RFC 2119 language here, and I'm happy to remove all of that language if folks think that's better. I would like not to bikeshed this, but I would also like to be on a beach right now, enjoying a lovely drink and watching the sunset.
NAME wrote the following in his WGLC review (): Splitting this off from as a potential design issue.
This seems like a reasonable thing to do.
I'd support a can or a MAY, as an example when you might reset min_rtt, but I don't think we need a SHOULD here.
minrtt is currently only used for filtering unexpectedly large ackdelay's reported by the peer. If the path RTT truly inflates then the peer will be able to report much larger ackdelay values and get a much lower RTT sample accepted. But I don't think this is a security problem in practice. The only other consideration is that in future QUIC implementations may reuse this computed value for other purposes like delay based congestion control. It's hard to make a judgement call on how important it is to reset minrtt. I guess I'd be happy with a SHOULD but I can live with a MAY.
Jana made a good argument that persistent congestion could be declared due to an overly small RTT, so resetting minrtt could avoid an endpoint repeatedly declaring persistent congestion. That being said, the RTT samples also need to be too low to spuriously declare persistent congestion, so this is increasingly sounding like an attack scenario, rather than having a poor estimate of minrtt. I think a SHOULD is Ok now, but I'd like to state the best rationale we have for why it's a SHOULD and neither a MUST or a MAY.
I think there's one tricky point in resetting the minrtt after handshake confirmation. That is that all the packets can be acked with delays. IIRC, one of the reasons we were happy with using minrtt for capping latestrtt is that Initial and Handshake packets do not have ackdelays.


Question: 5.2. <del> min_rtt is the minimum RTT observed for a given network path. min_rtt is set to the latest_rtt on the first RTT sample, and to the lesser of min_rtt and latest_rtt on subsequent samples.  In this document, min_rtt is used by loss detection to reject implausibly small rtt samples. </del> <ins> min_rtt is the sender's estimate of the minimum RTT observed for a given network path.  In this document, min_rtt is used by loss detection to reject implausibly small rtt samples. min_rtt MUST be set to the latest_rtt on the first RTT sample. min_rtt MUST be set to the lesser of min_rtt and latest_rtt (latest- rtt) on all other samples. </ins> An endpoint uses only locally observed times in computing the min_rtt and does not adjust for acknowledgment delays reported by the peer.

If we are to suggest that an endpoint MAY reset minrtt when persistent congestion is declared, I think we should consider the risk of not having good estimate of minrtt, as we would have during the handshake.
I don't see that as a risk here. min_rtt doesn't consider any discretionary delays.
NAME That's exactly the problem. will be inflated by , unless and until the peer sends an immediate acknowledgement. And until that happens, will as well.
I think that's OK. In practice, immediate ACKs do happen, and even at low rates, this should resolve to a "true" minimum. And if it doesn't, then you have worse performance than you might had otherwise. You have to have a pretty poor network (or a terrible ACK generation regime) for minrtt not to eventually resolve to a useful minimum. Explaining this risk is fine, but the endpoint that does this made the choice to throw out minrtt and that's just a consequence of that.
On one hand I agree that we can expect to see immediate ACKs, especially when HTTP/3 is used. At the same time, I am not sure if resetting minrtt when observing persistent congestion is better than other cases where we might reset minrtt, but that we do not currently mention. Change of IPTTL could be one of the examples in this regard (IIRC NAME pointed out that we do not use that value for detecting path changes). To summarize, I think talking about resetting minrtt might be fine, though I am not sure if that discussion should be tied to persistent congestion.
To give a specific example, one problem that I know with the current definition of minrtt is that it cannot detect and correct RTT estimate of a congested path. The sole purpose of minrtt is to discard excessive ack-delays being reported by the receiver. This works by capping the lower bound of adjustedrtt to minrtt. The problem here is that minrtt is a value that is typically collected when the path is almost idle. Once the path becomes congested, the true RTT becomes much greater than minrtt.


Question: 5.2. <del> min_rtt is the minimum RTT observed for a given network path. min_rtt is set to the latest_rtt on the first RTT sample, and to the lesser of min_rtt and latest_rtt on subsequent samples.  In this document, min_rtt is used by loss detection to reject implausibly small rtt samples. </del> <ins> min_rtt is the sender's estimate of the minimum RTT observed for a given network path.  In this document, min_rtt is used by loss detection to reject implausibly small rtt samples. min_rtt MUST be set to the latest_rtt on the first RTT sample. min_rtt MUST be set to the lesser of min_rtt and latest_rtt (latest- rtt) on all other samples. </ins> An endpoint uses only locally observed times in computing the min_rtt and does not adjust for acknowledgment delays reported by the peer.

For instance, if RTT-on-idle is 10ms and if RTT-on-congestion is 50ms, minrtt would be 10ms, and therefore cannot be used to correct RTT estimates when the peer reports an excessive ackdelay of, say 25ms. The RTT estimate would become 25ms in such case. I tend to think that this might be a bigger problem of the original issue, and therefore that we should state that an endpoint can periodically re-collect minrtt estimates, if we are to make a change to the current definition of minrtt.
Based on agreement on the resolution in , which introduces normative language, let's mark this design.
Seems fine. I'm not 100% on the strength of the recommendation to reset after persistent congestion, but it's sensible advice.The resetting of min RTT is also specified with LEDBAT or BBR, which differ from each other and from this proposed spec. This is a complex issue, because resetting min RTT in LEDBAT "because of congestion" is a variation of the latecomer advantage. But as long as the text applies only to RENO as specified here, then I am fine with it.I like the cautionary text. Just one suggestion but LGTM regardless. Thank you for working on this.


Question: The following information is exposed in QUIC packet headers: <del> demux bit: the second most significant bit of the first octet every QUIC packet of the current version is set to 1, for demultiplexing with other UDP-encapsulated protocols. </del> <ins> "fixed bit": the second most significant bit of the first octet most QUIC packets of the current version is currently set to 1, for demultiplexing with other UDP-encapsulated protocols. </ins> latency spin bit: the third most significant bit of first octet in the short packet header.  The spin bit is set by endpoints such

(which didn't require any non-editorial changes; the review is done now)
Also call out invariants (esp. in header structure and handshake) explicitly: v2 may/will break functionality outside the invariants.
Document is currently in in with final invariants; do one last pass to make sure everything documented in Section 17 as expose information appears here (which is basically the same check).


Question: (TLS) and Datagram Transport Layer Security (DTLS) recommends use of SHA-256 as a minimum requirement.  This update moves the minimum recommendation to use stronger language deprecating use of both SHA-1 <del> and MD5.  The prior text did not explicitly include MD5 and this text adds it to ensure it is understood as having been deprecated. </del> <ins> and MD5.  The prior text did not explicitly include MD5 or SHA-1; and this text adds guidance to ensure that these algorithms have been deprecated.. </ins> Section 4.3:

Addressing Roman's AD comments.
has 2 conflicts, not sure how to resolve, the updates look fine. Please merge.
There was a conflict with the 8174 reference being in the other branch. I added it in because it's now part of the terminology paragraph.
Please address the following IDNits: -- The document seems to lack an IANA Considerations section. (See Section 2.2 of URL for how to handle the case when there are no actions for IANA.) -- The draft header indicates that this document updates RFC5246, but the abstract doesn't seem to mention this, which it should. -- The draft header indicates that this document updates RFC7525, but the abstract doesn't seem to mention this, which it should. Section 1. Editorial. -- s/RFC 5246 [RFC5246]/[RFC5246]/ -- s/RFC 6151 [RFC6151]/[RFC6151]/ -- s/RFC7525 [RFC7525]/[RFC7525]/ Section 1. Editorial. For symmetry with the rest of the text: OLD RFC 6151 [RFC6151] details the security considerations, including collision attacks for MD5, published in 2011. NEW In 2011, [RFC6151] detailed the security considerations, including collision attacks for MD5. Section 1. Please provide a reference for "Wang, et al". Is there a reference to provide for the "the potential for brute-force attack" Section 6. Editorial Nit. s/RFC5246 [RFC5246]/[RFC5246]/ Section 6. Move the text "In Section 7.4.1.4.1: the text should be revised from" out of the "OLD" block of text to be its own intro paragraph so that the OLD vs. NEW is a clear cut-and-paste. Section 7. Editorial. s/ RFC7525 [RFC7525]/[RFC7525]/ Section 7. SHA-1 is also not mentioned in RFC7525. Recommend: OLD The prior text did not explicitly include MD5 and this text adds it to ensure it is understood as having been deprecated.


Question: (TLS) and Datagram Transport Layer Security (DTLS) recommends use of SHA-256 as a minimum requirement.  This update moves the minimum recommendation to use stronger language deprecating use of both SHA-1 <del> and MD5.  The prior text did not explicitly include MD5 and this text adds it to ensure it is understood as having been deprecated. </del> <ins> and MD5.  The prior text did not explicitly include MD5 or SHA-1; and this text adds guidance to ensure that these algorithms have been deprecated.. </ins> Section 4.3:

NEW The prior text did not explicitly include MD5 or SHA-1; and this text adds guidance to ensure that these algorithms have been deprecated. Section 7. Editorial. Grammar. OLD In addition, the use of the SHA-256 hash algorithm is RECOMMENDED, SHA-1 or MD5 MUST NOT be used NEW In addition, the use of the SHA-256 hash algorithm is RECOMMENDED; and SHA-1 or MD5 MUST NOT be used Section 10.2 Please make RFC5246 a normative reference.


Question: Full Coverage This property specifies the minimum number of bytes in a received <del> message that need to be covered by a checksum.  A special value of 0 means that a received packet does not need to have a non-zero checksum field.  A receiving endpoint will not forward messages that have less coverage to the application.  The application is responsible for handling any corruption within the non-protected part of the message RFC8085. </del> <ins> message that need to be covered by a checksum.  A receiving endpoint will not forward messages that have less coverage to the application. The application is responsible for handling any corruption within the non-protected part of the message RFC8085.  A special value of 0 means that a received packet may also have a zero checksum field. </ins> 8.1.2.

, , , , , .
In 8.1.1 the second sentence is convoluted. Is there a way to restate it without as many nots, nons, an different zeros?
Do you really mean "host" at "(endpoints) SHOULD represent the same host" in section 6, or do you mean something more like service, given that an endpoint may configured with a DNS name?
actually we mean service, good catch.
The "reformatted where necessary" part of the requirement in the last paragraph of 4.1 makes the MUST NOT almost impossible to conform to. I think I understand what the paragraph is trying to say, but the current formulation leaves the reader guessing. I think you are trying to say "Avoid using any of the terms listed as keywords in the protocol numbers registry as any part of a vendor or implementation-specific property name".
The first sentence-paragraph of section 4 is complex. Please break it apart.
has a comment that's too long for the text version
In the text version of the document, the last paragraph before 3.1.3 has some markup (~~~) that has leaked through.
As you can tell, I don't think the documents do what the first sentence of the API summary claims. This document would not lose anything if you deleted the sentence.
Agreed, we can lose this sentence.
Why? Removing this makes no sense to me.
For one, it's redundant - it only repeats what we already say earlier twice.
Ah, I see - so just this one instance..... then go ahead, we don't need to say something twice.


Question: authoritative IdPs, thus allowing the user to instantly grasp that the call is being authenticated by Facebook, Google, etc. <ins> 6.4.4.1. Because a broad range of characters are permitted in identity strings, it may be possible for attackers to craft identities which are confusable with other identities (see RFC6943 for more on this topic).  This is a problem with any identifier space of this type (e.g., e-mail addresses).  Those minting identifers should avoid mixed scripts and similar confusable characters.  Those presenting these identifiers to a user should consider highlighting cases of mixed script usage (see RFC5890, section 4.4).  Other best practices are still in development. </ins> 6.4.5. A number of optional Web security features have the potential to

NAME PTAL
The current text on user identity covers the domain portion well enough, but doesn't really say anything about how the part preceding the 'NAME is handled. There is text regarding the use of a local address book for the purposes of rendering, which might help avoid these issues entirely... where available. We may need to consider addressing the issue of confusable characters and whether we need to define the use of a particular normalization form. (See )


Question: 3.1.3. <del> QUIC ends a loss epoch when a packet sent after loss is declared is acknowledged.  TCP waits for the gap in the sequence number space to be filled, and so if a segment is lost multiple times in a row, the loss epoch may not end for several round trips.  Because both should reduce their congestion windows only once per epoch, QUIC will do it correctly once for every round trip that experiences loss, while TCP may only do it once across multiple round trips. </del> <ins> QUIC starts a loss epoch when a packet is lost and ends one when any packet sent after the epoch starts is acknowledged.  TCP waits for the gap in the sequence number space to be filled, and so if a segment is lost multiple times in a row, the loss epoch may not end for several round trips.  Because both should reduce their congestion windows only once per epoch, QUIC will do it correctly once for every round trip that experiences loss, while TCP may only do it once across multiple round trips. </ins> 3.1.4.

I was trying to come up with text for this but this PR looks great.
I believe there's an extra "is".
Can you write a PR? Removing either 'is' doesn't read well to me, but I suspect a sentence rewrite could be an improvement. ie: "A loss epoch ends when a packet sent after loss is first declared is acknowledged."?
I agree a rewrite would be better.


Question: to receiving packets that only contain DATAGRAM frames, since the timing of these acknowledgements is not used for loss recovery. <ins> As with any ack-eliciting frame, when a sender suspects that a packet containing only DATAGRAM frames has been lost, it MAY send probe packets to elicit a faster acknowledgement as described in Section 6.2.4 of RFC9002. </ins> If a sender detects that a packet containing a specific DATAGRAM frame might have been lost, the implementation MAY notify the application that it believes the datagram was lost.

The draft has some good text in the "Acknowledgement Handling" and "Congestion Control" sections that essentially is stating that DATAGRAM is just like any other ACK-eliciting packet, but is not automatically retransmitted by the transport. That's all reasonable, but I think there needs to be more text on how the (suspected) loss of a packet with a DATAGRAM frame or a PTO with only an outstanding DATAGRAM packet should be handled. I can see two possible models: It's just like any other packet. The goal is to elicit some ACK from the peer to get accurate loss information about the outstanding packet as soon as possible. If there is nothing outstanding we could use to send in a new packet, just send a PING frame. It's special. Because we don't necessarily intend to retransmit the data in the packet if it is actually lost, we don't actually care about immediate loss information/feedback. Don't force anything to be sent immediately to elicit the ACK. So far as I have it coded up in MsQuic, I've assumed (1). This essentially results in an immediate PING frame/packet being sent out if I have nothing else to retransmit to try to elicit an ACK for the DATAGRAM frame/packet. This could result in a slightly noisier connection if the app doesn't care about all loss information about their datagrams, but, IMO makes for a cleaner design. I don't know what the general consequences to congestion control might be if we don't do this. Assuming folks are in agreement, we should have some text on this topic in the draft.
NAME NAME as authors of the recovery draft do you have an opinion here?
I support NAME choice of 1 and it aligns with the recovery draft. It also matches our implementation. Adding clarifying text around this SG and I'd be happy to review it.
I agree -- choice (1) is cleanest and I would argue that choice(2) is really not principled.
Late to the issue, but I think (1) is the right choice here. It's not simply that datagrams aren't retransmitted, but that they might be retransmitted by the application if they're declared lost. If you don't have prompt feedback, that scenario suffers.


Question: to receiving packets that only contain DATAGRAM frames, since the timing of these acknowledgements is not used for loss recovery. <ins> As with any ack-eliciting frame, when a sender suspects that a packet containing only DATAGRAM frames has been lost, it MAY send probe packets to elicit a faster acknowledgement as described in Section 6.2.4 of RFC9002. </ins> If a sender detects that a packet containing a specific DATAGRAM frame might have been lost, the implementation MAY notify the application that it believes the datagram was lost.

Seems like we have good agreement on this, just need to write the text
NAME -- To NAME 's comment at the mic, you should cite .
This text sounds good, though I'd love a little bit more text mentioning the benefit of this probeThis text is fine with me. I am wondering if we should say something additional, like that packets with datagram frames shouldn't be treated special, with respect to loss recovery.


Question: server.  This attack is bound by the number of valid TCP connections an attacker can open. <del> 7.2.4. </del> <ins> 7.3.4. </ins> As more clients enable ESNI support, e.g., as normal part of Web browser functionality, with keys supplied by shared hosting

Since OCSP is the server name, ESNI should probably enforce OCSP stapling (similar to ) or any other way of encrypted OCSP checks. Ignoring OCSP status checks entirely makes it hard to revoke a certificate, even if it's only valid for a few months.
NAME what behavior do you expect here? Would clients fail hard if server don't send stapled responses? It's good to view ESNI as part of the leaky boat problem. It plugs one hole, but not all of them. Implementations probably should do something about cleartext OCSP if they want all holes plugged.
Thank you for the changes. LGTM.


Question: 2.1. QUIC packets may have either a long header, or a short header.  The <del> first bit of the QUIC header indicates which type of header is present. </del> <ins> first bit of the QUIC header us the Header Form bit, and indicates which type of header is present. </ins> The long header exposes more information.  It is used during connection establishment, including version negotiation, retry, and


Question: 9. Running DNS over HTTPS relies on the security of the underlying HTTP <del> connection.  By requiring at least RFC7540 levels of support for TLS, this protocol expects to use current best practices for secure transport. </del> <ins> transport.  Implementations utilizing HTTP/2 benefit from the TLS profile defined in RFC7540 Section 9.2. </ins> Session level encryption has well known weaknesses with respect to traffic analysis which might be particularly acute when dealing with

NAME I'm ok with you merging this and closing 11 if you're ok with it.
I think that it is fine - or more precisely, invaluable - to explain what the semantics of server push are. But you don't actually require HTTP/2 for this protocol to work. The only thing that requiring HTTP/2 gets you is tighter constraints on TLS usage. You can get those same constraints with some deployment recommendations. I would support strong recommendations that said HTTP/2 is useful for its multiplexing as well as similarly strong advice about following the advice in RFC 7525. Those are both good practice.
fairly clear feedback from singapore to change this to an endorsement (SHOULD) with better explanatory text focusing on performance and scale.
What are the drawbacks of HTTP/2? Less readily available libraries? more complex protocol? Potential difficulties in integrating with current fronting stacks that may not be HTTP/2 ready? On one hand, I feel like it may be easier to just enforce 1 stack for now rather than having to support multiple flavor of client/server protocols. A suboptimal HTTP/2 implementation may just be similar to HTTP/1 but at least we can try to move forward toward multiplexing. Making HTTP/2 a should may just leave us in limbo in HTTP/1 land.
NAME the singapore meeting is available here URL .. goto the 12 minute mark to review the discussion (wrt your question about drawbacks).
Text is in URL
Last PR accepted. I suspect there will be a bit more wordsmithing, but this should cover the main issue well.
thanks, I was in the room, but my notes were sparse and some of the cons I remembered of were more inconvenience to me than blockers. What I am not getting from the current spec, and which I believe NAME touched on in URL, is that it is unclear whether or not a minimum HTTP version must be supported. Based on URL , do we consider that by supporting HTTP/1.1 we get HTTP/1.0 for free and consider 0.9 not an option? Wouldn't not mandating a required version prevent client/server from having a known version to use? Can we make this clearer maybe?
The decision was to rely only on HTTP semantics and not versions. So any HTTP implementation that is acceptable to its peer can be used.


Question: external_aad = << TH_2, CRED_R, ? EAD_2 >> <del> CRED_R - bstr containing the credential of the Responder, see </del> <ins> CRED_R - CBOR item containing the credential of the Responder, see </ins> EAD_2 = unprotected external authorization data, see

CRED_R - bstr containing the credential This is not true for C509 which is an CBOR array


Question: is persistently offline may still be holding old keying material and thus be a threat to both FS and PCS if it is later compromised. <del> MLS partially defend against this problem by active member including freshness, however not much can be done on the inactive side especially in the case where the client has not processed messages. </del> <ins> MLS partially defends against this problem by active members including freshness, however not much can be done on the inactive side especially in the case where the client has not processed messages. </ins> <del> *RECOMMENDATION:* Mandate a key updates from clients that are not </del> <ins> *RECOMMENDATION:* Mandate key updates from clients that are not </ins> otherwise sending messages and evict clients which are idle for too long.

For the authors' consideration: Section 3 A member with a valid credential authenticates its MLS messages by signing them with the s/its/it's/ mechanisms for a user to monitor and control which keys are associated to their identity. s/to their/with their/ Operational Requirements A extension can help maintain interoperability s/A extension/An extension/ Whether there should be a extension in groups. s/a extension/an extension/ Forward and Post-Compromise Security MLS partially defend against this problem by active member including freshness, however not s/defend/defends/ s/member/members/ Mandate a key updates from clients that are not otherwise sending messages s/a key/key/ Compromise of AEAD key material authentication is not affected in neither of these s/neither/either/ Compromise of the Group Secrets of a single group for one or more group epochs of the compromised party with no ability to an honest group to recover message secrecy. s/to an/for an/ Compromise by an active adversary with the ability to sign messages the attacker can perform all operations which are available to an legitimate client s/an legitmate/a legitimate/ Compromise of the authentication with access to a signature key Beware that in both oracle and private key access, an active adaptive attacker, can follow th s/attacker, can/attacker can/ Security consideration in the context of a full state compromise They also are providing the strong authentication guarantees to other clients s/providing the strong/providing strong/ hence we consider that their protection by additional security mechanism should be a priority. s/mechanism/mechanisms/ Overall there is no way to detect or prevent these compromise, as discussed s/compromise/compromises/ Privacy of delivery and push notifications For secure messaging systems, push notification are often sent real-time s/notification/notifications/ Authentication Service Compromise MLS client (which is under the control of the user) have often the ability s/have often/often have/
Approved with nits.These changes look good to me.


Question: Architecture RFC7556 provides some discussion on authenticating an operator. <del> Given that a user chooses to visit a Captive Portal URI, the URI location SHOULD be securely provided to the user's device.  E.g., the DHCPv6 AUTH option can sign this information. </del> <ins> The user makes an informed choice to visit and trust the Captive Portal URI.  Since the network provides Captive Portal URI to the user equipment, the network SHOULD do so securely so that the user's trust in the network can extend to their trust of the Captive Portal URI.  E.g., the DHCPv6 AUTH option can sign this information. </ins> If a user decides to incorrectly trust an attacking network, they might be convinced to visit an attacking web page and unwittingly

The language of this section was hard for some of the reviewers to understand. Rephrase it to be more explicit and clear.
Yes. We should probably rephrase this. E.g. "The user makes an informed choice in deciding to visit and trust the Captive Portal URI. Since the network provides Captive Portal URI to the user equipment, thenetwork SHOULD do so securely so that the user's trust in the network can extend to their trust of the Captive Portal URI. E.g., the DHCPv6 AUTH option can sign this information."


Question: report share as invalid with the error "hpke-unknown-config-id". Otherwise, it decrypts the payload with the following procedure: <del> where "sk" is the HPKE secret key, "task_id" is the task ID, "nonce" and "extensions" are the nonce and extensions of the report share respectively, and "server_role" is 0x02 if the aggregator is the leader and 0x03 otherwise.  If decryption fails, the aggregator marks the report share as invalid with the error "hpke-decrypt-error". Otherwise, it outputs the resulting "input_share". </del> <ins> where "sk" is the HPKE secret key, and "server_role" is the role of the aggregator ("0x02" for the leader and "0x03" for the helper).  If decryption fails, the aggregator marks the report share as invalid with the error "hpke-decrypt-error".  Otherwise, it outputs the resulting "input_share". </ins> 4.3.1.4.

Specifically: Specify use of the "one-shot" HPKE APIs defined in RFC9180, replacing equivalent use of the "multi-shot" APIs. (This change is intended to be a clarification, not a functional change.) Move the task_id parameter from the "info" parameter to the "aad" parameter. This is intended to protect against key-commitment-related attacks[1]. (This is a functional change.) Clarify that the URL field is an encapsulated key, rather than an encryption context. (This is a clarification, not a functional change.) [1] See discussion in URL
Per URL section 8.1: PPM effectively uses the single-shot APIs; we should consider refactoring PPM's usage of HPKE to use only one of applicationinfo & AAD. Following the advice of the HPKE RFC, we would want to use applicationinfo. This would permit slightly simpler implementations. I am not sure how much it would simplify the HPKE computations.
Should we then formally use the single shot HPKE APIs from ?
That would be my recommendation (though, somewhat confusingly given the advice quoted above, those APIs still allow specifying both application info & AAD). Implementations can & do already use the single-shot APIs, so I strongly suspect specifying the single-shot APIs will be feasible. & .]
+1 to using single-shot APIs, though I'm not sure I agree that using either info or add (but not both) is simpler. What's the reasoning?
The reasoning is: a) it follows the advice of the HPKE spec (quoted above) b) AFAICT, in a single-shot setting, application info & AAD serve exactly the same purpose, so using both is arbitrary/confusing/a potential source of mistakes. (in a multi-shot setting, application info is bound to all encryptions/decryptions done by the same context; AAD is bound to a single encryption/decryption)
TBH I'm not sure I agree with the quoted guidance here. There is a concept in protocol design known as "domain separation", the goal of which is to provide some kind of binding of long-term secret key operations to the context in which they were used. Imagine, for example, that someone used an HPKE secret key for PPM and some other protocol. Suppose further that both are using the empty string for .


Question: report share as invalid with the error "hpke-unknown-config-id". Otherwise, it decrypts the payload with the following procedure: <del> where "sk" is the HPKE secret key, "task_id" is the task ID, "nonce" and "extensions" are the nonce and extensions of the report share respectively, and "server_role" is 0x02 if the aggregator is the leader and 0x03 otherwise.  If decryption fails, the aggregator marks the report share as invalid with the error "hpke-decrypt-error". Otherwise, it outputs the resulting "input_share". </del> <ins> where "sk" is the HPKE secret key, and "server_role" is the role of the aggregator ("0x02" for the leader and "0x03" for the helper).  If decryption fails, the aggregator marks the report share as invalid with the error "hpke-decrypt-error".  Otherwise, it outputs the resulting "input_share". </ins> 4.3.1.4.

Then the security of our PPM deployment depends on how the other protocol uses the derived AEAD key, since in both protocols may end up deriving the same AEAD key. One way to avoid creating this attack surface is to pick an string that no other application is likely to choose so that derived keys are guaranteed to not collide (except with some negligible probability). That said, I'd go for changing how we use and . Something like this might be simpler: Let be a fixed string that identifies the protocol. It would be good if this string were relatively long, say the SHA-256 hash of "ppm-00". Let encode the task ID, sender/receiver roles, etc.
I definitely agree that application info should include information allowing domain separation, for the reasons you mention. (Indeed, the current PPM spec includes the strings "ppm input share" or "ppm aggregate share" in its application infos, presumably for this purpose.) But I think that's orthogonal to the question of whether we should also use AAD, since the application info could also include information other than the "domain separation parameter". Picking one example to make things concrete, a client upload request sets its application info to and its AAD to . But it could just as easily set the application info to (i.e. the concatenation of the two previous strings) and not use AAD. (Or alternatively, it could place that string in the AAD and not use application info.) My argument is that it's simpler to use only one of the parameters, since in the single-shot setting that PPM is using HPKE, the two parameters serve exactly the same purpose (i.e. including additionally-authenticated data).
As I see it, our goal is to make sure that decryption only succeeds if the sender and receiver agree on the "context", i.e., the task ID, sender/receiver role, nonce, extensions, and so on. This way a MITM cannot force the aggregator to interpret an input share incorrectly. Does this sound reasonable to you? From the point of view of this threat model, I don't think it's immediately clear that sticking the context in or is equivalent.


Question: report share as invalid with the error "hpke-unknown-config-id". Otherwise, it decrypts the payload with the following procedure: <del> where "sk" is the HPKE secret key, "task_id" is the task ID, "nonce" and "extensions" are the nonce and extensions of the report share respectively, and "server_role" is 0x02 if the aggregator is the leader and 0x03 otherwise.  If decryption fails, the aggregator marks the report share as invalid with the error "hpke-decrypt-error". Otherwise, it outputs the resulting "input_share". </del> <ins> where "sk" is the HPKE secret key, and "server_role" is the role of the aggregator ("0x02" for the leader and "0x03" for the helper).  If decryption fails, the aggregator marks the report share as invalid with the error "hpke-decrypt-error".  Otherwise, it outputs the resulting "input_share". </ins> 4.3.1.4.

For example, if we stuff the context in , then it influences the derivation of the AEAD key; but depending on the AEAD, it might be feasible for an attacker to find a find two keys that decrypt the same ciphertext. (See URL) More analysis will be needed to say for sure whether this weakness in the AEAD amounts to an attack against our protocol. In the meantime, sticking the "context" in seems like a more conservative choice to me.
Given your concern, your approach SGTM. It sounds like this may be a concern worth raising with the folks working on the HPKE spec, given the advice to "use the Setup info parameter for specifying auxiliary authenticated information", but I'm not going to chase this down currently.
So I think there's two tasks for this issue: Move task ID from to Use single-shot APIs for HPKE Anything else?
Yep, I think that's it.
(reopening for now as the fix PR has been reverted temporarily)
Perfect, great work!


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

This adds an explicit Listener object to the API ( to clarify behaviour of multi-streaming protocols ( clarify behaviour and enable re-use of Preconnections (
We talk about listen objects in architecture and implementation, but not in the API. Changes needed: Let return a Listener Move the the Listener Allow Preconnection to be used multiple times.
This issue popped up while discussing and seem to be a wired QUIC multi-streaming issue, possible affecting SCTP too): When a multi-streaming protocol like QUIC allows both ends to open new streams (e.g. by cloning the QUIC connection representing the stream), the both side needs a way to get a ConnectionReceived event for a new stream. That might result in the following weird pattern: I think this needs to be documented somehow and we may need to add a Selection Property do turn off this behaviour.
Calling is an active open. Once the connection is open, the peer can open new streams, but those would surely be events on the not on the .
NAME I am not sure with this one: assuming you have a bunch of ? The first one? What happens if I close the first one?
That's a good point, and I'm not sure I know the answer, but I don't think the should fire the events. A is a potential connection, yet to be instantiated, but these connections come from an already active connection. I've never been entirely comfortable with cloning a connection as the multi-streaming abstraction. This is perhaps the first scenario where it struggles though.
I do not understand the pattern in the example. You do not get a ConnectionReceived after an active open, you need a Listen?
NAME Your assumption is true for TCP, but not for multi-streaming transports like QUIC. With QUIC, you can indeed get additional TAPS connections (QUIC streams) based on an existing, initiated connections. The question is how to handle this. NAME A possible way out would be making itself is returned by an event then.
NAME the TAPS interface is the same weather you have TCP or QUIC underneath. For TAPS an active open generates a READY event not a ConnectionReceived? I do not think your example is a valid TAPS sequence.
NAME the Ready event is not shown in the example (it would be within the first ). The problem I raised is how to model the addition of streams to a multi-streaming connection.


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

In case of QUIC, additional streams can be initiated by the server/listening side of the QUIC connection. If we model QUIC streams as TAPS connections, this results in events at the client (and server) side for each new QUIC stream.
NAME agree we could add , although it's a significant shift in the model. If we did that, we might also want to revisit as the way of creating a new stream on a connection, in favour of a method on . NAME did you implement this with QUIC? How does your implementation work?
I also see a problem with the communication pattern here. To me, modelling a stream as a TAPS connection means that for every new connection that a peer creates (be it a stream of an existing connection or not), I'll have to listen. So: if I expect 5 incoming connections, which may e.g. be 1 connection with 1 stream and 4 later-added streams below the API, I'll have to listen 5 times. What this also means is that the grouping notion should be a readable property - I believe that we currently only describe it as something that's actively created via clone(). Regarding code, no idea how NAME has done this, but I believe that the NEAT implementation is like I describe here. For more details on this specific aspect, see: URL
NAME We create a Listener from a Connection to handle inbound streams associated with the same parent transport connection. NAME Currently, our Listener object doesn't require calling Listen() for each new connection—you can get the event invoked many times, so it doesn't require knowing how many streams may be opened by the peer. In order to get back pressure, we're talking about having a window for how many new inbound connections will be allowed at a time.
Ok, that also sounds perfectly reasonable. Actually it seems that this (receiving multiple ConnectionReceived events on one Preconnection) is already supported by our current text, sorry for missing this! So... what is the problem we're discussing here - what do we need to change in the text? I think we need only the following: do we have a use case for one Listener getting multiple Connections without having these Connections grouped? (I guess not? Grouping is not a promise of multi-streaming.)


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

If so, we need the ability to query whether connections are grouped (currently grouping is only created actively via "clone"). Otherwise, we can just statically say that all Connections that are created from the same Preconnections are grouped. some kind of ConnectionReceived event for the Rendezvous case, with text saying that all Connections created off the same PreConnection are grouped. (right?) a way to provide back pressure. Here, we already have PreConnection.Stop(). In the interest of keeping things simple, do we think that intelligently switching between a listening and a non-listening mode would be enough? If so, maybe we should have a call similar to Stop which stops listening, but does not dispose of the PreConnection, such that Listen could be called again. Maybe have an "End" call which stops and disposes, and let Stop only stop listening (because "Stop", to me, indicates only stopping but nothing else).
NAME This solution sounds very reasonable – I guess we should do it the same way for TAPS and add that as Text to the API NAME Some comments: It depends – if writing a server, you might want all streams of a multi-streaming connection grouped, but not all multi-streaming connections received through the same listener. So the behaviour wether to group should be a property of the Listener. I would not group connections received through the same Rendezvous (analogous to server-style listener). We might want to add a property to the listener
NAME I agree, but: just because groups may encompass more than the Connections from one Listener doesn't mean that it would be bad to always group the Connections from one Listener (i.e., group them among themselves, but maybe group them with others too). Besides, I think that wouldn't be the listener deciding anyway. Just to understand this, are you saying "no, see my argument for case 1" ? Then we're just discussing case 1, my answer is above. Otherwise I'd say: why not? yes ... but what do you mean with ? We have , just the semantics are not what I suggested. Regarding , I think that's a good idea - my own proposal was me overdoing "keep it simple, let's not add features". Nobody needs to use this unless they want to.
NAME I guess the answer really depends on what a connection group is for you.


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

I always saw connection groups as an abstraction for multi-streaming connections (or their emulation) – therefore I see no use for grouping connections from multiple listeners. My opinion is auto-grouping for multi-streaming is fine, otherwise it is not. really falls out of 1 I want your semantics, but call it
NAME Me too. I can imagine other things ( this paper of ours comes to mind: URL ), but generally I agree and don't think we should complicate the API for this. But I'm getting confused: you wrote "you might want all streams of a multi-streaming connection grouped, but not all multi-streaming connections received through the same listener". That sounded to me like you want to support multiple streams, but from several listeners?! ACK Agreed!
NAME let me elaborate on this… You might want all streams of a multi-streaming connection grouped, e.g., all streams within a QUIC connection You might not want all multi-streaming connections (e.g., QUIC connections) received through the same Listener object grouped You definitely do not want all all streams of all QUIC connection received through one listener grouped (except if you have hierarchical groups that allows you to sort that out the cases above)
I agree with all this. Anyway I think it's a moot point: whether they're grouped or not is not up to the listener to decide? So grouping needs to be something that can be queried.
Ok – fair enough – but I still think the Listener is the right place to configure whether connections that come out of it should be grouped by default or not.
Not unless we have a concrete idea on what to do with this information inside the transport system. => I think no text update is needed as a result of this issue and lean towards closing it...
I don't think we really need a text update for the grouping, but for the original question. To address the handling of incoming streams in multi-streaming connections, I would like to have the solution NAME outlined reflected in the API.
One question on this, for NAME the description of your Listener object being able to accept multiple events, is that how it works in general or was that specif for a multi-streaming scenario? As specified I am not sure that our Listen action does not allow multiple ConnectionReceived events? The text says
NAME The listener object for all cases (both multi streaming and receiving brand-new transport connections) allows multiple events.


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

I think the existing text is a bit ambiguous, but it seems that "listening continues" implies that the event can certainly fire again.
Revisit after is done
Regarding this text: This seems to imply that the Preconnection object, which may be full of many carefully tuned settings that could be useful for another Connection, is no longer usable. While I understand that the specific Preconnection cannot change for a Connection, this is inconvenient to the application. I see two good options to solve this: Make a deep copy of the Preconnection upon Initiate(), and say that a Preconnection may be used or changed but changes can no longer influence the Connection (this is what Network.framework currently does) Allow a URL() method to let the applications do the deep copy themselves when and if they want to re-use.
+1 to reusing the preconnection. Do you even need a deep copy. The connection is a new object that should be independent of the preconnection anyway, no? Another thought: Are there actually ways to get different connections out of the preconenction. E.g. you do racing and end up with two open connections and (suddenly) want to use both...?
I'd like to see this as well. To me it makes most sense to allow calling Initiate() on the same Preconnection multiple times to get multiple Connections, but not allow to change this Preconnection anymore after the first Initiate. This way it would be similar to Listen() and Rendezvous(), where we have a Preconnection that yields multiple Connections, and that cannot be changed anymore after Listen() or Rendezvous(). So here we already have a binding between the Preconnection and the Connections that come out of it. If the application wants to change the Preconnection before re-using it, I'd be in favor of letting it explicitly clone the Preconnection - not sure if we actually want to call it clone() though, because we already have Connection.Clone(), which creates a Connection Group, a completely different thing.
Why do you think it should not be allowed that a preconnection can be changed after the first initiate? If you don't change it you should get the same kind of connection, if you change it you might get something different. Your choice!
I wanted the API contract to be similar for different forms of Connection establishment. But I may be overthinking this.


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

First, I like the idea of reusing Preconnections. I am not sure whether we should define now whether they should be changeable after the first initiation. There might be kinds of Preconnections where this is a good idea, there might be others where it is not. I anticipate one can realize connection pools as a sub-class of Preconnection. In this case, in such cases, it should not be possible to change a Preconnection.
So the difference is if you think you morph a preconnection into a connection, or if the preconnection create the connection. i think the first think does not make sense because their are two completely different things; they have not actions or events in common.
NAME The morphing one has its beauty for modeling TCP fastopen / 0-RTT data.
Whether it makes sense to re-use a perhaps depends on how fully specified it is? Reusing a completely specified , that will just re-open an identical 5-tuple as an existing might not make sense. Reusing a partially specified , e.g., with the source port left as a wildcard to new connections can open without conflicts, seems reasonable.
NAME right, using the exact same set of fully-specified properties isn't going to work. But having a partially specified one and copying it, or modifying one that was used (by switching out the Remote, etc) would be useful.
This might work better the other way -- on , the Preconnection corresponding to the initiated/initiating connection gets deep-copied into the new connection, leaving the existing Preconnection in the state that it was. That deep copy, inside the connection, cannot be reused, but the existing one could be. (This probably only works for connections on which you . turns the preconnection into a listener from which multiple , each of which will have their own deep copy of the listener, will spawn. might be even weirder, but there's a potentially bigger win to allowing reuse, but I don't quite have my head around how it would work)
So i think there is actually not that much too deep copy because a preconception is not a super class of a connection. At the moment when you call initiate or rendezvous the preconception should create a connection and store all information regarding this connection in the connection object which is later returned.


Question: Passive open is the Action of waiting for Connections from remote endpoints, commonly used by servers in client-server interactions. <del> Passive open is supported by this interface through the Listen Action: </del> <ins> Passive open is supported by this interface through the Listen Action and returns a Listener object: </ins> Before calling Listen, the caller must have initialized the Preconnection during the pre-establishment phase with a Local Endpoint specifier, as well as all properties necessary for Protocol Stack selection.  A Remote Endpoint may optionally be specified, to <del> constrain what Connections are accepted.  The Listen() Action consumes the Preconnection.  Once Listen() has been called, no further properties may be added to the Preconnection, and no subsequent establishment call may be made on the Preconnection. </del> <ins> constrain what Connections are accepted.  The Listen() Action returns a Listener object.  Once Listen() has been called, properties added to the Preconnection have no effect on the Listener and the Preconnection can be disposed of or reused. </ins> Listening continues until the global context shuts down, or until the <del> Stop action is performed on the same Preconnection: </del> <ins> Stop action is performed on the Listener object: </ins> <del> After Stop() is called, the preconnection can be disposed of. </del> <ins> After Stop() is called, the Listener can be disposed of. </ins> The ConnectionReceived Event occurs when a Remote Endpoint has <del> established a transport-layer connection to this Preconnection (for </del> <ins> established a transport-layer connection to this Listener (for </ins> Connection-oriented transport protocols), or when the first Message has been received from the Remote Endpoint (for Connectionless protocols), causing a new Connection to be created.  The resulting

The only thing that needs "copying" is the properties but you need to create a new object anyway because preconnection properties have preferences and connection properties not but have to be marked as mutable or unmutable. These two things are also not the same. So the only that that's left to copy maybe are the endpoints. Not sure if the preconnection and connection both have a copy of the endpoints or if an endpoint only exists once and both have a reference (which means if the endpoint gets somehow updated that's relevant for both) or maybe even the connection does not need a reference to the endpoint anymore...?
NAME right – but I don't know a way of specifying "a is consumed if fully specified, else may be reusedin any current programming language. Maybe tracking lifetimes so closely doesn't matter though, and we can just write this in the draft.
I have no problem with an Interface where some Preconnections can be reused and others can not. That makes a pretty nice case for -- preconnection reuses itself for multiple incoming connections. For ` I see this API-wise as some kind of listen called at both sides.
Side meeting says we can reuse the initiate call. Implementation should specify that a deep copy is made on Initiate() or Listen()
Will be trivial to fix after is done
Sorry to reopen an old issue, but when reading the current API draft, I noticed that it still says that reusing the Preconnection is possible for Listeners, but not possible for Initiate() and Rendezvous(). For example, see Section 6.1: "The Initiate() Action consumes the Preconnection […]" From what I read in this issue, I think Preconnections should be allowed to be reused for Initiate() and Rendezvous() as well (possibly with a note on deep-copy).
This looks just right to me, thanks a lot for doing this! In particular having read again, I believe that NAME should definitely have the last word on this one. So I'll go with whatever NAME says.


Question: address validation by sending a Retry packet (packet-retry) containing a token.  This token MUST be repeated by the client in all Initial packets it sends for that connection after it receives the <del> Retry packet.  In response to processing an Initial containing a token, a server can either abort the connection or permit it to proceed. </del> <ins> Retry packet. In response to processing an Initial containing a token that was provided in a Retry packet, a server cannot send another Retry packet; it can only refuse the connection or permit it to proceed. </ins> As long as it is not possible for an attacker to generate a valid token for its own address (see token-integrity) and the client is

The original text here might be read to imply that a server can't send Retry if it receives an Initial that contains a token that came from NEW_TOKEN. That's wrong.


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 6.4. <del> Groups of Connections can be created using the Clone Action: </del> <ins> Entangled Connections can be created using the Clone Action: </ins> Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned


Question: 4.1.4. Session description objects (RTCSessionDescription) may be of type <del> "offer", "pranswer", and "answer".  These types provide information as to how the description parameter should be parsed, and how the media state should be changed. </del> <ins> "offer", "pranswer", or "answer".  These types provide information as to how the description parameter should be parsed, and how the media state should be changed. </ins> "offer" indicates that a description should be parsed as an offer; said description may include many possible media configurations.  A

I was reading this draft and noticed a couple of minor wording issues that made the text not as clear as it could be. I don't believe the changes are controversial, or change the intention of the draft.
These changes look good - I agree the rewrite of the offer/answer paragraph is a nice improvement.
Looks fine to me


Question: "authority" as defined in Section 3.2 of RFC3986. The Alternative-Address Option is a repeatable option as defined in <del> Section 5.4.5 of RFC7252. </del> <ins> Section 5.4.5 of RFC7252.  When multiple occurrences of the option are included, the peer can choose any of the alternative transport addresses. </ins> The elective Hold-Off Option indicates that the server is requesting that the peer not reconnect to it for the number of seconds given in

URL - WGLC review by Esko Dijk Page 20: Alternative-Address Option - the semantics of including multiple of these options is not defined. Can the receiver pick any of the addresses? Or does it need to try the first address first? And then keep trying all alternatives until one succeeds, or not?
URL Unless Carsten or Hannes (authors of draft-bormann-core-coap-sig-02) have a preference, I would suggest that the addresses are unordered (pick any).


Question: contains the unmodified payload of a UDP packet (referred to as "data octets" in UDP). <del> Clients MAY optimistically start sending UDP packets in HTTP Datagrams before receiving the response to its UDP proxying request. However, implementors should note that such proxied packets may not be processed by the UDP proxy if it responds to the request with a failure, or if the proxied packets are received by the UDP proxy before the request. </del> By virtue of the definition of the UDP header UDP, it is not possible to encode UDP payloads longer than 65527 bytes.  Therefore, endpoints MUST NOT send HTTP Datagrams with a Payload field longer than 65527

PR in response to Al's OPSDIR review -- Reviewer: Al Morton Review result: Has Nits Hi David, this is the OPS-DIR review. I tried to stay in my lane. I found this paragraph confusing (which doesn't mean it is incorrect, just that someone with limited background read the section 2 requirements list, all MUSTs, and then the paragraph below, which seems to have a conflicting MUST with the SHOULD and MAY that follows). Help readers like me understand the options you are allowing here: If the client detects that any of the requirements above are not met by a URI Template, the client MUST reject its configuration and fail the request without sending it to the UDP proxy. While clients SHOULD validate the requirements above, some clients MAY use a general-purpose URI Template implementation that lacks this specific validation. I see that Christer's GEN_ART review picked-up on this too (I looked after I was done...). In Section 5, there seems to be a possible operations issue for proxy operators: Clients MAY optimistically start sending UDP packets in HTTP Datagrams before receiving the response to its UDP proxying request. However, implementors should note that such proxied packets may not be processed by the UDP proxy if it responds to the request with a failure, or if the proxied packets are received by the UDP proxy before the request. This seems like a good place to limit the amount of optimistic traffic, given that the request is not yet accepted. (also, would the optimistic traffic use Context ID zero?) In Performance Considerations UDP proxies SHOULD strive to avoid increasing burstiness of UDP traffic: they SHOULD NOT queue packets in order to increase batching. This requirement is written qualitatively, so users might "know a violation if they see it", but not hold the proxy system/operator to any specific performance without providing more details here. Inter-packet delay variation measurements on proxy ingress and egress would characterize increased burstiness well. Another solution is s/SHOULD/should/ (I doubt some increased burstiness will be avoidable, or enforceable.) Thanks in advance for considering these comments, Al


Question: A signature algorithm <del> The HPKE parameters are used to instantiate HPKE I-D.irtf-cfrg-hpke for the purpose of public-key encryption.  The "DeriveKeyPair" function associated to the KEM for the ciphersuite maps octet strings to HPKE key pairs. </del> <ins> MLS uses draft-07 of HPKE I-D.irtf-cfrg-hpke for public-key encryption.  The "DeriveKeyPair" function associated to the KEM for the ciphersuite maps octet strings to HPKE key pairs. </ins> Ciphersuites are represented with the CipherSuite type.  HPKE public keys are opaque values in a format defined by the underlying protocol

cc NAME
NAME is the build expected to fail?
No, but the problem seem unrelated to your change, so we are all good.
Looks like it was a transient failure. Re-running resulted in success.
NAME points out that the HPKE version is not pinned. This is probably needed for interop. Version -07 should come sometime this week, so that seems like a perfectly fine version to use. I can send a PR when that version is cut.
Fixed by


Question: RDAO: Clarify that it is an option for RAs and not other ND messages. <ins> Examples: Use example URIs rather than unclear reg names (unless it's RFC6690 examples, which were kept for continuity) </ins> changes from -24 to -25 Large rework of section 7 (Security policies)

... and a few other cases of example errors and use of unregistered names.


Question: client ever sees the values for individual clients. In order to address this problem, the aggregators engage in a secure, <del> multi-party computation specified by the chosen VDAF I-D.draft-cfrg- patton-vdaf in order to prepare a report for aggregation.  At the beginning of this computation, each aggregator is in possession of an input share uploaded by the client.  At the end of the computation, each aggregator is in posession of either an "output share" that is ready to be aggregated or an indication that a valid output share could not be computed. </del> <ins> multi-party computation specified by the chosen VDAF VDAF in order to prepare a report for aggregation.  At the beginning of this computation, each aggregator is in possession of an input share uploaded by the client.  At the end of the computation, each aggregator is in posession of either an "output share" that is ready to be aggregated or an indication that a valid output share could not be computed. </ins> To facilitiate this computation, the input shares generated by the client include information used by the aggregators during aggregation

Would be helpful to readers if this reference was fixed in the Editor's Copy: [I-D.draft-cfrg-patton-vdaf] " BROKEN REFERENCE ".
Maybe change each reference to ? That way it'll render like in the text, which reads a bit nicer.


Question: PMTU probes are ack-eliciting packets. Endpoints could limit the content of PMTU probes to PING and PADDING <del> frames as packets that are larger than the current maximum packet size are more likely to be dropped by the network.  Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion control reaction; see Section 3, Bullet 7 of DPLPMTUD.  However, PMTU probes consume congestion window, which could delay subsequent transmission by an application. </del> <ins> frames, since packets that are larger than the current maximum datagram size are more likely to be dropped by the network.  Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion control reaction; see Section 3, Bullet 7 of DPLPMTUD.  However, PMTU probes consume congestion window, which could delay subsequent transmission by an application. </ins> 14.4.1.

Addresses . NAME points out in that we use in the transport draft and in the recovery draft. In reading carefully, I realized that in the transport draft was actually historical, and is the more appropriate term. This is an entirely editorial PR, and it's largely simple changes, despite the fact that it looks a bit big. It is a bit subtle though. Sorry about that.
This issue will list a number of minor editorial things that should be checked and likely addressed with some editorial fixes: Section 5.3: "These delays are computed using the ACK Delay field of the ACK frame as described in Section 19.3 of [QUIC-TRANSPORT]." This text implies that the computation of the delay is described in Section 19.3 of QUIC-TRANSPORT. However, I don't think it is described the calculation, only the definition of the field. Please reformulate to imply only field definition not calculation. Section 5.3: "On the first RTT sample for the network path, that sample is used as rttsample. This ensures that the first measurement erases the history of any persisted or default values." I think this intended to cover cases where path changes are detected. But it is not well expressed. Does this need a reformulation and a reference into QUIC-TRANSPORT where it states when such a reset should occur? Section 6.1: "Either its packet number is kPacketThreshold smaller than an acknowledged packet" Nitpicking, assuming no PN gaps in transmission. Does that need a note? Section 6.2.4: "An endpoint MAY send up to two full-sized datagrams containing ack-eliciting packets, to avoid an expensive consecutive PTO expiration due to a single lost datagram or transmit data from multiple packet number spaces." This last part, I assume intended to generate additional datagrams to prevent single loss to impact. However, due to coalescing this is unclear in this context. Section 7: "Endpoints can unilaterally choose a different algorithm to use, such as Cubic ([RFC8312])." I think this sentence should be explicit that in needs to be sender-based algorithms. I think we need to have the requirement on performing congestion control on the sender unless there has been explicit agreement with the receiver that they will do it.


Question: PMTU probes are ack-eliciting packets. Endpoints could limit the content of PMTU probes to PING and PADDING <del> frames as packets that are larger than the current maximum packet size are more likely to be dropped by the network.  Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion control reaction; see Section 3, Bullet 7 of DPLPMTUD.  However, PMTU probes consume congestion window, which could delay subsequent transmission by an application. </del> <ins> frames, since packets that are larger than the current maximum datagram size are more likely to be dropped by the network.  Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion control reaction; see Section 3, Bullet 7 of DPLPMTUD.  However, PMTU probes consume congestion window, which could delay subsequent transmission by an application. </ins> 14.4.1.

Section 7.2: "Endpoints SHOULD use an initial congestion window of 10 times the maximum datagram size (maxdatagramsize), limited to the larger of 14720 bytes or twice the maximum datagram size." "maximum datagram size" is not used in Transport there need to be alignment here of what name to use. Transport has Maximum Packet Size, which appears to match the definition in the appendix of maxdatagram_size.
Thanks for your careful review, NAME -- these are good finds! I've addressed your comments below and in . I'll address point 6 in a separate PR. Section 19.3 has the following text, which does tell how to compute acknowledgement delay from the ACK Delay field: I've replaced "computed" with "decoded" in the recovery document to make it clearer. Coalescing applies to packets, not to datagrams. We've explicitly stated that a sender could send 2 datagrams to avoid any effects of coalescing. I think the text is pretty clear on this: "An endpoint MAY send up to two full-sized datagrams containing ack-eliciting packets". I've added "sender-side" to make the controller more explicit. To your point about making this a sender requirement, that is covered in the transport doc (end of ):
Based on and , labeling this as "editorial"
I think these issues are resolved once the two PRs are completely ready.
Except for the one erronous exchange of packet this looks good.


Question: The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and <del> "OPTIONAL" in this document are to be interpreted as described in RFC2119.  The term "byte" is used in its now customary sense as a synonym for "octet". </del> <ins> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. The term "byte" is used in its now customary sense as a synonym for "octet". </ins> This specification requires readers to be familiar with all the terms and concepts that are discussed in RFC3986, RFC8288 and RFC6690.

All expected to be uncontroversial; to be merged soon.
Commit 3809be46013e9708a6584c4fb730e7cfecab5f22 should have been part of this as well, and is already applied to master.