Private key (optional) <del> Privaate key seed data (optional) </del>  Leaf creation: Just import data Puncture tree heads are nodes that are OK whose parents are not OK <del> [[ Following sections to be filled from earlier PDF/code + diffs from the London meeting ]] </del> 5.  6.  6.1.  6.2. <del> 6.3. </del>  <del> 6.4. </del>  <del> 6.5. </del>  <del> 6.6. </del>  7.  Each state-changing message is premised on a given starting state Thus, there is a need to deconflict if two messages are generated In any case, risk of starvation <del> 7.1. </del>  With this approach, the server ensures that incoming messages are added to an ordered queue and outgoing messages are dispatched in the This apllies to all messages, not only state changing messages. <del> 8. </del>  The primary purpose of this protocol is AKE choose to ignore it (if the value is not known, or if transcript security is not required). <del> 9. Key Secrecy Authentication Re-use of InitKeys </del> 10. <del> 11. The Asynchronous Ratcheting Tree is the building block around which this protocol is built.  It was originally specified by Cohn-Gordon et al with a formal proof of its security properties (https://eprint.iacr.org/2017/666). ART uses a Diffie-Hellman Key Tree to derive a shared secret for a group, allowing it to be efficiently updated (ratcheted) by any group member (leaf node) to provide the properties of Forward Secrecy and Post-Compromise Security.  Alongside ratcheting, receiving messages, and changing the group membership can also be efficiently achieved. 11.1. ART uses a recursive structure, in which every node is a Diffie- Hellman public key or key pair.  The value of a given parent node's private key is computed as follows: (TODO: define our KDF). The ART root secret is the private Diffie-Hellman key of the root of the tree.  This should not be used directly within the protocol, but rather computed into a Stage Key (TODO: below). For this document, we will use the shorthand notation [A,B] to indicate KDF(DH(Alice, Bob)). 11.2. Changing a leaf DH key will inherently update its entire path to and including the root. In the above tree, if C updates to C', the path of all nodes referencing C is updated, resulting in the below tree. C must transmit the public keys of her entire path to the other participants in the tree.  Each participant will update their copath with their respective element from this path, and thus recompute the same updated tree that C has computed. 11.3. 11.4. 12. [[ Session comprised of (1) ART (2) pre-stage key (3) message key chains ]] [[ Each node caches... ]] 13. In MLS, the endpoints involved in a session collaborate to establish and maintain an Asynchronous Ratchet Tree for the session.  There are three major phases in the life-cycle of a group: Initializing the tree Adding a new endpoint Updating a leaf in the tree Leaves are never removed from tree.  One endpoint can remove another endpoint by updating that endpoint's leaf to a key that the endpoint being removed does not possess. At any point, an endpoint can publish a PreKey message, which contains information that another endpoint can use to add that endpoint to a group.  Typically applications provide a PreKey cache to which endpoints periodically push fresh PreKey messages. Suppose an endpoint A wants to initiate a group conversation with otehr endpoints B, C, and D.  A accomplishes this by downloading PreKeys fro B, C, and D, computing a tree over (A, B, C, D), and sending different individual Setup messages to B, C, and D. If A subsequently wants to add another endpoint E to the conversation, then the process is similar.  First A downloads a PreKey for E and uses it to add E to the tree.  From these computations, A generates a Setup message for E and an Add message that can be broadcast to B, C, and D. Upon being added, E should update its leaf key so that its leaf key will not be known to A.  To update a leaf key in the tree, an endpoint simply generates a new key pair, creates an Update message, and broadcasts it to the group. 13.1. Each MLS endpoint caches a view of the overall tree including certain global elements and certain elements specific to the endpoint: For the group: The current epoch The list of identity keys for the group The current frontier The current preStageKey For the endpoint: Index in the tree Leaf key pair Copath MLS messages synchronize this state information across the participants in the group. Note that no state is modified when an endpoint sends a Setup, Add, or Update message.  Because all endpoints need to process updates to the tree in the same order, there is a risk that any given message of these types will be rejected.  To avoid the need to roll back on such rejections, endpoints only apply Setup / Add / Update messages once they are published and accepted by the group.  For more discussion of how modifications to the tree should be sequenced, see #sequencing- of-modifications. 13.2. 13.2.1. 13.2.2. 13.2.3. 13.2.4. 13.3. [[ Endpoints need to make modifications to the tree in the same order.  How does that happen? ]] 14. </del>  <del> [[ What trust is placed in the server? ]] </del>  <del> 15. </del>

This PR adds a pretty complete description of the protocol. The only major thing that's missing is , which should be straightforward-ish to construct. NAME want to take a stab at that?

Private key (optional)  <ins> Private key seed data (optional) </ins> Leaf creation: Just import data Puncture tree heads are nodes that are OK whose parents are not OK  5. <ins> Logically, the state of an MLS group at a given time comprises: A group ID A ciphersuite used for cryptographic computations A Merkle tree over the participants' identity keys A ratchet tree over the participants' leaf key pairs A message root key (known only to participants) An add key pair (private key known only to participants) An init secret (known only to participants) Since a group can evolve over time, a session logically comprises a sequence of states.  The time in which each individual state is used is called an "epoch", and each state is assigned an epoch number that increments when the state changes. MLS handshake message provide each node with enough information about the trees to authenticate messages within the group and compute the group secrets. Thus, each participant will need store the following information about each state of the group: The participant's index in the identity/ratchet trees The private key for the participant's leaf key pair The private key for the participant's identity key pair The current epoch number The group ID A subset of the identity tree comprising at least the copath for the participant's leaf A subset of the ratchet tree comprising at least the copath for the participant's leaf The current message root key The current update key pair The current init secret 5.1. Each MLS session uses a single cipher suite that specifies the following values to be used in group key computations: A hash function A Diffie-Hellman group Public keys used in the protocol are opaque values in a format defined by the ciphersuite. 5.2. Group keys are derived using the HKDF-Extract and HKDF-Expand functions as defined in RFC5869, as well as the functions defined below: The Hash function used by HKDF is the cipher suite hash algorithm. Hash.length is its output length in bytes.  In the below diagram: HKDF-Extract takes its Salt argument form the top and its IKM argument from the left Derive-Secret takes its Secret argument from the incoming arrow When processing a handshake message, a participant combines the following information to derive new epoch secrets: The init secret from the previous epoch The update secret for the current epoch The handshake message that caused the epoch change The current group ID and epoch The derivation of the epoch key pair depends on the change being made.  For the first epoch, when there is no previous epoch key pair, the creator of the group generates a fresh key pair and publishes it to the initial set of participants. Given these inputs, the derivation of secrets for an epoch proceeds as shown in the following diagram: </ins> 6. <ins> In order to facilitate asynchronous addition of participants to a group, it is possible to pre-publish initialization keys that provide some public information about a user or group.  UserInitKey messages provide information a user that a group member can use to add the user to a group without the user being online.  GroupInitKey messages provide information about a group that a new user can use to join the group without any of the existing members of the group being online. </ins> 6.1. <ins> A UserInitKey object specifies what cipher suites a client supports, as well as providing public keys that the client can use for key derivation and signing.  The client's identity key is intended to be stable through the lifetime of the group; there is no mechanism to change it.  Init keys are intend to be used one time only (or perhaps a small number of times, see #init-key-reuse). The init_keys array MUST have the same length as the cipher_suites array, and each entry in the init_keys array MUST be a public key for the DH group defined by the corresponding entry in the cipher_suites array. The whole structure is signed using the client's identity key.  A UserInitKey object with an invalid signature field MUST be considered mal-formed.  The input to the signature computation comprises all of the fields except for the signture field. </ins> 6.2.  <ins> A GroupInitKey object specifies the aspects of a group's state that a new member needs to initialize its state (together with an identity key and a fresh leaf key pair). The current epoch number The number of participants currently in the group The group ID The cipher suite used by the group The public key of the current update key pair for the group </ins>  <ins> The frontier of the identity tree, as a sequence of hash values </ins>  <ins> The frontier of the ratchet tree, as a sequence of public keys </ins>  <ins> GroupInitKey messages are not themselves signed.  A GroupInitKey should not be published "bare"; instead, it should be published by constructing a handshake message with type "none", which will include a signature by a member of the group and a proof of membership in the group. </ins> 7. <ins> Over the lifetime of a group, changes need to be made to the group's state: Initializing a group A current member adding a new participant A new participant adding themselves A current participant updating its leaf key A current member deleting another current member In MLS, these changes are accomplished by broadcasting "handshake" messages to the group.  Note that unlike TLS and DTLS, there is not a consolidated handshake phase to the protocol.  Rather, handshake messages are exchanged throughout the lifetime of a group, whenever a change is made to the group state. An MLS handshake message encapsulates a specific message that accomplishes a change in group state, and also includes two other important features: First, it provides a GroupInitKey so that a new participant can observe the latest state of the handshake and initialize itself.  Second, it provides a signature by a member of the group, together with a Merle inclusion proof that demonstrates that the signer is a legitimate member of the group. Before considering a handshake message valid, the recipient MUST verify both that the signature is valid and that the Merkle inclusion proof is valid.  The input to the signature computations comprises the entire handshake message except for the signature field. The Merkle tree head to be used for validating the inclusion proof MUST be one that the recipient trusts to represent the current list of participant identity keys. 7.1. [[ Direct initialization is currently undefined.  A participant can create a group by initializing its own state to reflect a group including only itself, then adding the initial participants.  This has computation and communication complexity O(N log N) instead of the O(N) complexity of direct initialization. ]] 7.2. An GroupAdd message is sent by a group member to add a new participant to the group.  The contents of the message are simply the UserInitKey for the user being added. A group member generates such a message by downloading a UserInitKey for the user to be added.  The added participant processes the message together with the private key corresponding to the UserInitKey to initialize his state as follows: Compute the participant's leaf key pair by combining the init key in the UserInitKey with the prior epoch's update key pair Use the frontiers in the GroupPreKey of the Handshake message to add its keys to the trees An existing participant receiving a GroupAdd message first verifies the signature on the message, then verifies its identity proof against the identity tree held by the participant.  The participant then updates its state as follows: Compute the new participant's leaf key pair by combining the leaf key in the UserPreKey with the prior epoch add key pair Update the group's identity tree and ratchet tree with the new participant's information The update secret resulting from this change is the output of a DH computation between the private key for the root of the ratchet tree and the add public key from the previous epoch. [[ ALTERNATIVE: The sender could also generate the new participant's leaf using a fresh key pair, as opposed to a key pair derived from the prior epoch's secret.  This would reduce the "double-join" problem, at the cost of the GroupAdd having to include a new ratchet frontier. ]] 7.3. A UserAdd message is sent by a new group participant to add themselves to the group, based on having already had access to a GroupInitKey for the group. A new participant generates this message using the following steps: Fetch a GroupInitKey for the group Use the frontiers in the GroupPreKey to add its keys to the trees Compute the direct path from the new participant's leaf in the new ratchet tree (the add_path). An existing participant receiving a UserAdd first verifies the signature on the message, then verifies its identity inclusion proof against the updated identity tree expressed in the GroupPreKey of the Handshake message (since the signer is not included in the prior group state held by the existing participant).  The participant then updates its state as follows: Update trees with the descriptions in the new GroupInitKey Update the local ratchet tree with the add path in the UserAdd message, replacing any common nodes with the values in the add path The update secret resulting from this change is the secret for the root node of the ratchet tree. 7.4. An Update message is sent by a group participant to update its leaf key pair.  This operation provides post-compromise security with regard to the participant's prior leaf private key. The sender of an Update message creates it in the following way: Generate a fresh leaf key pair Compute its direct path in the current ratchet tree An existing participant receiving a Update message first verifies the signature on the message, then verifies its identity proof against the identity tree held by the participant.  The participant then updates its state as follows: Update the cached ratchet tree by replacing nodes in the direct path from the updated leaf with the corresponding nodes in the Update message The update secret resulting from this change is the secret for the root node of the ratchet tree. 7.5. A delete message is sent by a group member to remove one or more participants from the group. The sender of a Delete message creates it in the following way: Compute the ordered list of subtree heads by puncturing the deleted participants' leaves from the current ratchet tree Generate a fresh DH key pair and initialize a "delete path" to the one-element list containing that key pair For each subtree head in the list: Perform a DH computation between the subtree head's public key and the private key from the last key pair in the delete path Derive a DH key pair from the output of that DH computation Append the resulting key pair to the delete path The head field in the Delete message holds the public keys corresponding to the subtree heads.  The path field holds the public keys corresponding to the delete path, with the last element omitted (it is unnecessary).  As a result, the heads and path arrays MUST have the same length. Note that the sender of a Delete message must enough information about the ratchet tree so that it has all of the subtree heads resulting from the puncture operation.  This criterion is met if the sender has a copath for each of the deleted participants. An existing participant receiving a Delete message first verifies the signature on the message, then verifies its identity proof against the identity tree held by the participant.  The participant then updates its state as follows: Compute the ordered list of subtree heads by puncturing the deleted participants' leaves from the current ratchet tree Find a public key in the list of subtree heads for which the private key is known to the recipient Perform a DH computation between the known subtree head private key and the public key in the delete path at the same index For each remaining element in the list of subtree heads: Derive a DH key pair from the last DH output Perform a DH computation between the private key of the derived key pair with the subtree head's public key The update secret for this change is the last DH output from the delete path. 8. </ins> Each state-changing message is premised on a given starting state Thus, there is a need to deconflict if two messages are generated In any case, risk of starvation  <ins> 8.1. </ins> With this approach, the server ensures that incoming messages are added to an ordered queue and outgoing messages are dispatched in the This apllies to all messages, not only state changing messages.  <ins> 9. </ins> The primary purpose of this protocol is AKE choose to ignore it (if the value is not known, or if transcript security is not required).  10.  <ins> 10.1. </ins>  <ins> 10.2. </ins>  <ins> 10.3. </ins>


Name: mqtt-topic-filter <del> Description/Specification: Topic Filter as defined in mqtt-defs. </del>  Reference: [[This document]] (scope) Name: mqtt-permissions <del> Description/Specification: Permissions for MQTT client.  Tperm is a string with a value either "pub" or "sub". </del>  <del> Reference: [[This document]] (scope ) </del>  8.

Thanks Carsten! I'll go clear my DISCUSS :)
I see. These didn't cause a problem on my side.

Name: mqtt-topic-filter  <ins> Description/Specification: Topic Filter as defined in scope. </ins> Reference: [[This document]] (scope) Name: mqtt-permissions  <ins> Description/Specification: Permissions for MQTT client as defined in scope.  Tperm is an array of one or more text strings that each have a value of either "pub" or "sub". </ins>  <ins> Reference: [[This document]] (scope) </ins> 8.


of-Possession (PoP) token by default. This document follows RFC7800 for PoP semantics for JWTs (CWTs MAY <del> also be used).  The AS includes a "cnf" (confirmation) parameter to </del>  the PoP token, to declare that the Client possesses a particular key and RS can cryptographically confirm that the Client has possession <del> of that key.  The "cnf" parameter is REQUIRED if a symmetric key is used, and MAY be present for asymmetric PoP keys, as described in I- D.ietf-ace-oauth-params. </del>  Note that the contents of the web tokens (including the "cnf" parameter) are to be consumed by the RS and not the Client (the

Let's assume we're talking about what the AS puts in the token (not the token response). That means that "cnf" always has to be present. The flow where "cnf" is only required in the symmetric case and is optional for the asymmetric case is the use of the "cnf" parameter in the token response, from AS to client.

of-Possession (PoP) token by default. This document follows RFC7800 for PoP semantics for JWTs (CWTs MAY  <ins> also be used).  The AS includes a "cnf" (confirmation) parameter in </ins> the PoP token, to declare that the Client possesses a particular key and RS can cryptographically confirm that the Client has possession  <ins> of that key, as described in I-D.ietf-ace-oauth-params. </ins> Note that the contents of the web tokens (including the "cnf" parameter) are to be consumed by the RS and not the Client (the


Broker (RS) via the CONNECT control message after the TLS handshake. This is similar to an earlier proposal by Fremantle et al. fremantle14.  Alternatively, the token may be used for the TLS <del> session establishment as described in the I-D.gerdes-ace-dtls- </del>  authorize.  In this case, both the TLS PSK and RPK handshakes MAY be supported.  This may additionally require that the Client transports the token to the Broker before the connection establishment.  To this

fixed ID reference to ietf-ace-dtls-authorize doing this first so it'll build from makefile (
The correct reference is I-D.ietf-ace-dtls-authorize and not I-D.gerdes-ace-dtls-authorize.

Broker (RS) via the CONNECT control message after the TLS handshake. This is similar to an earlier proposal by Fremantle et al. fremantle14.  Alternatively, the token may be used for the TLS  <ins> session establishment as described in the I-D.ietf-ace-dtls- </ins> authorize.  In this case, both the TLS PSK and RPK handshakes MAY be supported.  This may additionally require that the Client transports the token to the Broker before the connection establishment.  To this


2.5. <del> In the case of a Client DISCONNECT, due to the Clean Session flag, the Broker deletes all session state but MUST keep the retained messages.  By setting a RETAIN flag in a PUBLISH message, the </del>  publisher indicates to the Broker that it should store the most <del> recent message for the associated topic.  Hence, the new subscribers can receive the last sent message from the publisher of that particular topic without waiting for the next PUBLISH message.  The Broker MUST continue publishing the retained messages as long as the associated tokens are valid. </del>  In case of disconnections due to network errors or server disconnection due to a protocol error (which includes authorization

I believe this " if you're happy with it now we're (assumed) targetting MQTT v5.0 we should refer to Clean Start acknowledge that RETAINed messages could be made irrelevant by further publishes
yes, that's much better, thanks! (see e46a8d)
Section 2.5 - The last sentence in the first paragraph could be state more clearly. Specifically there would appear to be some ambiguity on who the associated tokens are attached to. "messages as long as the publisher token for that message remains valid." Might be better.
Better working might to "the retailed message until the token for that message has expired," That avoids the question if all of the tokens have expired or just the one with the message.

2.5.  <ins> In the case of a Client DISCONNECT, due to the Clean Start flag (or Clean Session flag with MQTT v3.1.1), the Broker deletes all session state but MUST keep the retained messages and token expiry information.  By setting a RETAIN flag in a PUBLISH message, the </ins> publisher indicates to the Broker that it should store the most  <ins> recent message for the associated topic.  Hence, new subscribers can receive the most recent message from the publisher of that particular topic without waiting for the next PUBLISH message.  The Broker MUST continue publishing each retained message until the token for that message has expired, or another RETAIN message is published on the associated topic. </ins> In case of disconnections due to network errors or server disconnection due to a protocol error (which includes authorization


there is none. The MUD file permits access to a particular Internet service, but <del> the name of that service resolved to something that was not permitted. </del>  The administrator overrode the recommendations in the MUD file.

I added a container to report ACL violation dropped packets. I am not sure how the l3l4info is going to be used. The YANG model was fixed (I think some parens missing). Please check and let me know you agree with these changes. Thanks, Ranga

there is none. The MUD file permits access to a particular Internet service, but  <ins> the name of that service has not been resolved (or name resolution failed). </ins> The administrator overrode the recommendations in the MUD file.


array of the MUD file. Second, the "mud" container is augmented with a container that points <del> to where to report and how often. </del>  This is done as follows:

Added a default packet classification. Removed the generated txt file ( can always be generated from Makefile). Please reject pull request if you disagree. Thanks.
Reworked yang model. Mostly implemented (except for json serialization).
Reduced the amount of information in the YANG model to something manageable. Mostly implemented (except for some JSON serialization issues). At least it is feasible to implement this. Removed frequency (should be left to administrator - not manufacturer).

array of the MUD file. Second, the "mud" container is augmented with a container that points  <ins> to where to report. The frequency of reporting is impelementation dependent. Impelemntations are encouraged to report when ever packet drops are noticed at the enforcement point; however, this is not a strict requirement. </ins> This is done as follows:


This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of <del> several different media types into a single message, such as a CoAP request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </del>  1. This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of <del> several different media types into a single message, such as a CoAP RFC7252 request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </del>  This simple and efficient binary framing mechanism can be employed to create application specific request and response bodies which build RFCthis <del> Applications that need to combine representations of potentially several media types into one, e.g., EST-CoAP </del>  N/A

WFM
Oops, I'd missed that. I will change that instance as well.
It should not preclude 0, 1 or 2, therefore: s/several/zero or more/
Maybe just "representations of different media types"?

This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of  <ins> zero or more different media types into a single message, such as a CoAP request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </ins> 1. This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of  <ins> zero or more different media types into a single message, such as a CoAP RFC7252 request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </ins> This simple and efficient binary framing mechanism can be employed to create application specific request and response bodies which build RFCthis  <ins> Applications that need to combine representations of zero or more different media types into one, e.g., EST-CoAP </ins> N/A


This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of <del> several different media types into a single CoAP message-body with minimal framing overhead, each along with a CoAP Content-Format identifier. </del>  1. This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of <del> several different media types into a single CoAP RFC7252 message-body with minimal framing overhead, each along with a CoAP Content-Format identifier. </del>  This simple and efficient binary framing mechanism can be employed to create application specific request and response bodies which build

Sure. Apologies, I had completely misunderstood the gist of your comment (and Carsten's reply).
-> s/message-body/request or response body/
I still don't understand why the only permissible use of this representation format is inside a CoAP payload. Can't I transfer the CBOR structure over HTTP or store it in a file?

This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of  <ins> several different media types into a single message, such as a CoAP request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </ins> 1. This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of  <ins> several different media types into a single message, such as a CoAP RFC7252 request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </ins> This simple and efficient binary framing mechanism can be employed to create application specific request and response bodies which build


Applications that need to combine representations of zero or more different media types into one, e.g., EST-CoAP <del> N/A </del>

Carsten adds:
Yes. (Where is the rest of that change?)
As we speak there's no PR, only this issue.
NAME would you mind writing the missing text? I'm not comfortable messing around with media type registration procedures :-)

Applications that need to combine representations of zero or more different media types into one, e.g., EST-CoAP  <ins> The syntax and semantics of fragment identifiers specified for "application/multipart-core" is as specified for "application/ cbor".  (At publication of this document, there is no fragment identification syntax defined for "application/cbor".) </ins>


create application specific request and response bodies which build on multiple already existing media types. <del> Applications using the application/multipart-core Content-Format define the semantics as well as the internal structure of the application/multipart-core representation according to the syntax described by the CDDL in mct-cddl. For example, one way to structure the sub-types specific to an application/multipart-core container is to always include them at the same fixed position.  This specification allows to indicate that an optional part is not present by substituting a null value for the representation of the part. Optionally, an application might use the general format defined here, but also register a new media type and an associated Content-Format identifier instead of using application/multipart-core. </del>  2. representation can be described by the CDDL I-D.ietf-cbor-cddl specification in mct-cddl:  3. 3.1.

So, a multipart representation can be processed up till the first error? Works for me.
I think we have to avoid saying "must check the whole thing before acting on any of it". The intention was not to say "If there is an error, you have to process up to the error". Is that what you read there?
mmm, that's not how I interpret "stop processing". Maybe "invalidate processing"?
But that is too close the meaning I'm trying to avoid. Maybe we can leave it slightly open as it is proposed now?
Sorry I'm not following: Which meaning are you trying to avoid? I think not removing the ambiguity in the text is a bad thing.
Nice, thanks (and also, my previous ship-it is still valid).
Klaus still sees a problem with assigning too much leeway to the application in giving the positioning special semantics. We'll need to discuss this a bit further...
I don't see how we could limit applications in this sense? It's intrinsically a piece of malleable data. And what's more important, your change here only talks about what happens on syntactic violations, which is as far as we can go to limit application leeway.
Well, this is introductory material that tells readers how this is supposed to be used. I made a proposal that I think reflects Klaus' sentiment. In the process, I lost the part that needed the fix requested by , but I think that is OK -- an introduction should not really have a MUST anyway. NAME — better?
Apart from the array, set and struct-like use cases, it'd be worth mentioning the "union" pattern that was discussed at the interim?
LGTM
NAME do you want to re-integrate af472b3 here or prefer to merge as-is?
Since about 9 hours I'm trying to write the union sentence; crazy day.
And, yes, af472b3 should stay in, but I don't care in which PR :-)
If you like the wording of the union pattern, this can go in and we can submit the next version.
Go for it! FWIW I like it very much.
Klaus: Carsten seems to prefer failing hard and early (draft-iab-protocol-maintenance). Thomas loves simplicity and +1 Carsten's proposal.
Klaus has a point, but we already have a way to evolve: Define a new media type. I don't think there really is a need here to haphazardly send a new version of this to someone that might not understand it.
+1, as I said in other emails, we don't need to make it perfect now. Let's make it simple, use it and measure its ergonomics. We can always grab another code point in the future if this needs fixing.
NAME wdyt?
sorry, hit the wrong button
LGTM

create application specific request and response bodies which build on multiple already existing media types.  <ins> The individual representations in an application/multipart-core body occur in a sequence, which may be employed by an application where such a sequence is natural, e.g. for a number of audio snippets in different formats to be played out in that sequence. In other cases, an application may be more interested in a bag of representations, which are distinguished by their Content-Format identifier, such as an audio snippet and a text representation accompanying it.  In such a case, the sequence in which these occur may not be relevant to the application.  This specification allows to indicate that an optional part is not present by substituting a null value for the representation of the part. A third situation that is common only ever has a single representation in the sequence, which is one of a set of formats possible.  This kind of union of formats may also make the presence of the actual representation optional, the omission of which leads to a zero-length array. Where these rules are not sufficient for an application, it might still use the general format defined here, but register a new media type and an associated Content-Format identifier to associate the representation with these more specific semantics instead of using application/multipart-core. </ins> 2. representation can be described by the CDDL I-D.ietf-cbor-cddl specification in mct-cddl: <ins> This format is intended as a strict specification: An implementation MUST stop processing the representation if there is a CBOR well- formedness error, a deviation from the structure defined above, or any residual data left after processing the CBOR data item.  (This generally means the representation is not processed at all except if some streaming processing has already happened.) </ins> 3. 3.1.


This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of <del> zero or more different media types into a single message, such as a CoAP RFC7252 request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </del>  This simple and efficient binary framing mechanism can be employed to create application specific request and response bodies which build on multiple already existing media types.  The individual representations in an application/multipart-core body occur in a sequence, which may be employed by an application where such a sequence is natural, e.g. for a number of audio snippets in <del> different formats to be played out in that sequence. </del>  In other cases, an application may be more interested in a bag of representations, which are distinguished by their Content-Format identifier, such as an audio snippet and a text representation accompanying it.  In such a case, the sequence in which these occur <del> may not be relevant to the application.  This specification allows to indicate that an optional part is not present by substituting a null value for the representation of the part. </del>  A third situation that is common only ever has a single <del> representation in the sequence, which is one of a set of formats possible.  This kind of union of formats may also make the presence of the actual representation optional, the omission of which leads to a zero-length array. </del>  Where these rules are not sufficient for an application, it might still use the general format defined here, but register a new media type and an associated Content-Format identifier to associate the representation with these more specific semantics instead of using <del> application/multipart-core. </del>  1.1. respective content format. The collection is encoded as a CBOR RFC7049 array with an even number <del> of elements.  The second, fourth, sixth, etc. element is a byte string containing a representation, or the value "null" if an optional part is indicated as not given.  The first, third, fifth, etc. element is an unsigned integer specifying the content format ID of the representation following it. </del>  For example, a collection containing two representations, one with content format ID 42 and one with content format ID 0, looks like [42, h'0123456789abcdef', 0, h'3031323334'] For illustration, the structure of an application/multipart-core <del> representation can be described by the CDDL I-D.ietf-cbor-cddl specification in mct-cddl: </del>  This format is intended as a strict specification: An implementation MUST stop processing the representation if there is a CBOR well- 3. <del> 3.1. </del>  <del> When a client registers to observe a resource RFC7641 for which no </del>  representation is available yet, the server may send one or more 2.05 (Content) notifications before sending the first actual 2.05 <del> (Content) or 2.03 (Valid) notification.  The possible resulting sequence of notifications is shown in Figure 1. </del>  The specification of the Observe option requires that all notifications carry the same Content-Format.  The application/ For example, a single text/plain object (content-format 0) of value "Hello World" (11 characters) would be serialized as <del> 0x82 0x00 0x4b H e l l o 0x20 w o r l d </del>  In effect, the serialization for a single object is done by prefixing the object with information that there is one object (here: 0x82), (0x84 for two representations, 0x86 for three, ...) and the sequences of content-format and embedded representations follow.  5. 5.1.

Address Benjamin Kaduk's outstanding DISCUSS.
No: with that, the sender sends along all formats and the recipient chooses based on its capabilities or preferences. Appropriate for single-shot mail, not at all appropriate for a request/response situation (at least not for the response part). URL Grüße, Carsten
Ah sorry, hadn't read properly (it's sender, not receiver).
LGTM

This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of  <ins> zero or more different media types, each along with a CoAP Content- Format identifier, into a single representation, with minimal framing overhead.  This combined representation may then be carried in a single message, such as a CoAP RFC7252 request or response body. </ins> This simple and efficient binary framing mechanism can be employed to create application specific request and response bodies which build on multiple already existing media types. <ins> As the name of the media-type suggests, it is inspired by the multipart media types that started to be defined with the original set of MIME specifications RFC2046.  However, while those needed to focus on the syntactic aspects of integrating multiple representations into one e-mail, transfer protocols providing full data transparency such as CoAP as well as readily available encoding formats such as the Concise Binary Object Representation (CBOR) RFC7049 shift the focus towards the intended use of the combined representations.  In this respect, the basic intent of the application/multipart-core media type is like that of multipart/mixed (Section 5.1.3 of RFC2046).  The detailed semantics of the representations are refined by the context established by the application in the accompanying request parameters, e.g., the resource URI and any further options (header fields), but three usage scenarios are envisioned: </ins> The individual representations in an application/multipart-core body occur in a sequence, which may be employed by an application where such a sequence is natural, e.g. for a number of audio snippets in  <ins> various formats to be played out in that sequence, or search results returned in order of relevance. </ins> In other cases, an application may be more interested in a bag of representations, which are distinguished by their Content-Format identifier, such as an audio snippet and a text representation accompanying it.  In such a case, the sequence in which these occur  <ins> may not be relevant to the application.  This specification adds the option of substituting a null value for the representation of an optional part, which indicates that the part is not present. </ins> A third situation that is common only ever has a single  <ins> representation in the sequence, where the sender already selects just one of a set of formats possible for this situation.  This kind of union "type" of formats may also make the presence of the actual representation optional, the omission of which leads to a zero-length array. </ins> Where these rules are not sufficient for an application, it might still use the general format defined here, but register a new media type and an associated Content-Format identifier to associate the representation with these more specific semantics instead of using  <ins> the application/multipart-core media type. Also, future specifications might want to define rough equivalents for other multipart media types with specific semantics not covered by the present specification, such as multipart/alternative (Section 5.1.4 of RFC2046), where several alternative representations are provided in the message, but only one of those is to be selected by the recipient for its use (this is less likely to be useful in a constrained environment that has facilities for pre-flight discovery). </ins> 1.1. respective content format. The collection is encoded as a CBOR RFC7049 array with an even number  <ins> of elements.  Counting from zero, the odd-numbered elements are a byte string containing a representation, or the value "null" if an optional part is indicated as not given.  The (even-numbered) element preceding each of these is an unsigned integer specifying the content format ID of the representation following it. </ins> For example, a collection containing two representations, one with content format ID 42 and one with content format ID 0, looks like [42, h'0123456789abcdef', 0, h'3031323334'] For illustration, the structure of an application/multipart-core  <ins> representation can be described by the CDDL RFC8610 specification in mct-cddl: </ins> This format is intended as a strict specification: An implementation MUST stop processing the representation if there is a CBOR well- 3.  <ins> This section illustrates one less obvious example for using application/multipart-core: combining it with observing a resource RFC7641 to handle pending results. </ins>  <ins> When a client registers to observe a resource for which no </ins> representation is available yet, the server may send one or more 2.05 (Content) notifications before sending the first actual 2.05  <ins> (Content) or 2.03 (Valid) notification.  A diagram depicting possible resulting sequences of notifications, identified by their respective response code, is shown in fig-sequence. </ins> The specification of the Observe option requires that all notifications carry the same Content-Format.  The application/ For example, a single text/plain object (content-format 0) of value "Hello World" (11 characters) would be serialized as  <ins> 0x82 0x00 0x4b H e l l o 0x20 W o r l d </ins> In effect, the serialization for a single object is done by prefixing the object with information that there is one object (here: 0x82), (0x84 for two representations, 0x86 for three, ...) and the sequences of content-format and embedded representations follow. <ins> For instance, the example from encoding would be serialized as: 0x84 (*) 0x182A 0x48 0x0123456789ABCDEF (+) 0x00 0x45 0x3031323334 where (*) marks the start of the information about the first representation (content-format 42, byte string length 8) and, (+), of the second representation (content-format 0, byte string length 5). </ins> 5. 5.1.


This memo defines application/multipart-core, an application- independent media type that can be used to combine representations of <del> zero or more different media types into a single message, such as a CoAP request or response body, with minimal framing overhead, each along with a CoAP Content-Format identifier. </del>  1. zero or more different media types, each along with a CoAP Content- Format identifier, into a single representation, with minimal framing overhead.  This combined representation may then be carried in a <del> single message, such as a CoAP RFC7252 request or response body. </del>  This simple and efficient binary framing mechanism can be employed to <del> create application specific request and response bodies which build on multiple already existing media types. </del>  As the name of the media type suggests, it is inspired by the multipart media types that started to be defined with the original resource URI and any further options (header fields), but three usage scenarios are envisioned: <del> The individual representations in an application/multipart-core body occur in a sequence, which may be employed by an application where such a sequence is natural, e.g. for a number of audio snippets in various formats to be played out in that sequence, or search results returned in order of relevance. </del>  In other cases, an application may be more interested in a bag of representations, which are distinguished by their Content-Format for other multipart media types with specific semantics not covered by the present specification, such as multipart/alternative (Section 5.1.4 of RFC2046), where several alternative representations <del> are provided in the message, but only one of those is to be selected by the recipient for its use (this is less likely to be useful in a constrained environment that has facilities for pre-flight discovery). </del>  1.1.

(URL) Q1 The Introduction says talks about “request or response body’. However, when looking in RFC 7252, I don’t find ‘body’ anywhere. I assume that ‘body’ refers to what RFC 7252 calls ‘payload’. If so, I suggest aligning the terminology. (For some reason section 10.2.3 of RFC 7252 does use ‘message-body’, without any explanation or reference, but I guess that is just an error) Q2 Related to Q1, the text says: “can be used to combine representations of zero or more different media types into a single message” I assume it means ‘single message payload’? Because, you are not combing other parts (Codes, Tokens etc) of the message, are you? I think it would be more clear if you said ‘combine multiple representations, each using the same or different media types, into a single message payload’. Q3 The draft uses both ‘media type’ and ‘media-type’. RFC 7252 uses ‘media type’ (there is one instance of ‘media-type’, though), so maybe align with that?

Q1 is addressed in
Finally closed in 5a1a23c
LGTM Hi Christer, thank you for alerting us to this oversight. (And thank you for the critical reading in the first place!) Right. Body is an RFC 7959 term (which was adapted from HTTP’s “Message Body”, obviously). I didn’t really want to muddy the picture by explaining again that CoAP block-wise transfers can cut up a single body into multiple payloads (as per RFC 7959). The current text already might be misunderstood to say that this media type is CoAP specific, which it is not at all. We didn’t go to the trouble of having a formal terminology import section (apart from the usual BCP14 boilerplate in 1.1). We could add that text, reference 7959 and 7230 as well, and make this abundantly clear. Or we could leave it as it is. That is about the message-body on the HTTP side, so it is exactly as it should be. (Actually, 1.2 of 7252 says »This specification requires readers to be familiar with all the terms and concepts that are discussed in [RFC2616], including "resource", "representation", "cache", and "fresh". (Having been completed before the updated set of HTTP RFCs, RFC 7230 to RFC 7235, became available, this specification specifically references the predecessor version -- RFC 2616.) In addition, this specification defines the following terminology: « […] So this term is already defined in RFC 7252, albeit implicitly only.) Actually, it now says This memo defines application/multipart-core, an application- independent media-type that can be used to combine representations of zero or more different media types, each along with a CoAP Content- Format identifier, into a single representation, with minimal framing overhead. This combined representation may then be carried in a single message, such as a CoAP [RFC7252] request or response body. (Where “message” might be a whole block-wise transfer.) Is that better? To carry that in a single message, you would carry it in the message’s payload (or, theoretically, in an option, but we only do that in OSCORE so far). The new text above more clearly separates the representation combining from the ability to send it in a single message then. Yeah, that’s a bit funny. I actually believe we should have used media-type throughout the history of the term, as this is an artificial construct that only loosely relates to media types (types of media). But maybe this draft is not the place to correct this mistake which has been in place since 1996. That one instance is in the construction “media-type ranges”, which is the normal way to compose composites in English. I’m sure the RFC editor will force us to do that anyway, but I have made the change to “media type” (with a space) in the editors’ copy in case we get to submit another version. Waiting for CI to show this at https://core-URL (And the RFC editor will make us expand abbreviations and all that, too.) Grüße, Carsten
The Constrained RESTful Environments (core) virtual interim meeting for 2024-02-14 from 16:00 to 17:30 Europe/Stockholm has been cancelled.

This memo defines application/multipart-core, an application- independent media type that can be used to combine representations of  <ins> zero or more different media types into a single message body, carried e.g., as a CoAP request or response payload, with minimal framing overhead, each along with a CoAP Content-Format identifier. </ins> 1. zero or more different media types, each along with a CoAP Content- Format identifier, into a single representation, with minimal framing overhead.  This combined representation may then be carried in a  <ins> single message body, such as a CoAP RFC7252 request or response payload. </ins> This simple and efficient binary framing mechanism can be employed to  <ins> create application specific message bodies which build on multiple already existing media types. </ins> As the name of the media type suggests, it is inspired by the multipart media types that started to be defined with the original resource URI and any further options (header fields), but three usage scenarios are envisioned:  <ins> The individual representations in an application/multipart-core message body occur in a sequence, which may be employed by an application where such a sequence is natural, e.g. for a number of audio snippets in various formats to be played out in that sequence, or search results returned in order of relevance. </ins> In other cases, an application may be more interested in a bag of representations, which are distinguished by their Content-Format for other multipart media types with specific semantics not covered by the present specification, such as multipart/alternative (Section 5.1.4 of RFC2046), where several alternative representations  <ins> are provided in the message body, but only one of those is to be selected by the recipient for its use (this is less likely to be useful in a constrained environment that has facilities for pre- flight discovery). </ins> 1.1.


After completing the handshake, endpoints have agreed to enable multipath feature and can start using multiple paths.  This document <del> does not discuss when a client decides to initiate a new path.  We delegate such discussion in separate documents. </del>  This proposal adds one multipath control frame for path management:

Attempt at moving Further, it is out of scope for this document if the old address can also be used for multipath after a client has migrated to the address provided in the preferred_address transport parameter. However, it SHOULD NOT be assumed that it is possible to use both addresses simultaneously without further confirmation from the other host. In the beginning of section where I think it would be more appropriate.
Looks good, except for the typo.

After completing the handshake, endpoints have agreed to enable multipath feature and can start using multiple paths.  This document  <ins> does not specify how an endpoint that is reachable via several addresses announces these addresses to the other endpoint.  In particular, if the server uses the preferred_address transport parameter, clients SHOULD NOT assume that the initial server address and the addresses contained in this parameter can be simultaneously used for multipath.  Furthermore, this document does not discuss when a client decides to initiate a new path.  We delegate such discussion in separate documents. </ins> This proposal adds one multipath control frame for path management:


Add some implementation considerations to handle different PMTU sizes following the discussion on . Feel free to add different implementation options here.
Looks ok to me, just a small suggestion to avoid talking about packet retransmission.

11.  <ins> 11.1. An implementation should take care to handle different PMTU sizes across multiple paths.  One simple option if the PMTUs are relatively similar is to apply the minimum PMTU of all paths to each path.  The benefit of such an approach is to simplify retransmission processing as the content of lost packets initially sent on one path can be sent on another path without further frame scheduling adaptations. </ins> 12.


"enable_multipath", it MUST treat this as a connection error of type MP_CONNECTION_ERROR and close the connection. <del> Note that the transport parameter "active_connection_id_limit" QUIC- TRANSPORT limits the number of usable Connection IDs, and also limits the number of concurrent paths.  For the QUIC multipath extension this limit even applies when no connection ID is exposed in the QUIC header. </del> This extension does not change the definition of any transport <del> parameter defined in Section 18.2. of QUIC-TRANSPORT.  Inline with the definition in QUIC-TRANSPORT disable_active_migration also disables multipath support, except "after a client has acted on a preferred_address transport parameter" Section 18.2. of QUIC- TRANSPORT.  Further, it is out of scope for this document to specify if the old address can also be used for multipath after a client has migrated to the address provided in the preferred_address transport parameter.  However, it SHOULD NOT be assumed that it is possible to use both addresses simultaneously without further confirmation from the other host. </del>  3.

This text will be moved to the next section in PR . Therefore this PR needs to be merged together with PR .

"enable_multipath", it MUST treat this as a connection error of type MP_CONNECTION_ERROR and close the connection.  This extension does not change the definition of any transport  <ins> parameter defined in Section 18.2. of QUIC-TRANSPORT. Inline with the definition in QUIC-TRANSPORT disable_active_migration also disables multipath support, except "after a client has acted on a preferred_address transport parameter" Section 18.2. of QUIC- TRANSPORT. The transport parameter "active_connection_id_limit" QUIC-TRANSPORT limits the number of usable Connection IDs, and also limits the number of concurrent paths.  For the QUIC multipath extension this limit even applies when no connection ID is exposed in the QUIC header. </ins> 3.


9.2. <del> The MP_ACK frame (types TBD-00 and TBD-01; experiments use </del>  0xbaba00..0xbaba01 or 0x42..x43) is an extension of the ACK frame defined by QUIC-TRANSPORT.  It is used to acknowledge packets that <del> were sent on different paths.  If the frame type is TBD-01, MP_ACK </del>  frames also contain the sum of QUIC packets with associated ECN marks received on the connection up to this point. number space, which is the sequence number of Destination Connection ID of the 1-RTT packets which are acknowledged by the ACK_MP frame. If the endpoint receives 1-RTT packets with 0-length Connection ID, <del> it SHOULD use Packet Number Space Identifier 0 in ACK_MP frames. </del>  10.

Should we trigger an connection closure with a MPCONNECTIONERROR in the case an endpoint receives an ACK_MP frame acknowledging packets on a non-existing packet number space ID?
Yes. I just submitted PR for this issue.
PR merged.
LGTM.

9.2.  <ins> The ACK_MP frame (types TBD-00 and TBD-01; experiments use </ins> 0xbaba00..0xbaba01 or 0x42..x43) is an extension of the ACK frame defined by QUIC-TRANSPORT.  It is used to acknowledge packets that  <ins> were sent on different paths.  If the frame type is TBD-01, ACK_MP </ins> frames also contain the sum of QUIC packets with associated ECN marks received on the connection up to this point. number space, which is the sequence number of Destination Connection ID of the 1-RTT packets which are acknowledged by the ACK_MP frame. If the endpoint receives 1-RTT packets with 0-length Connection ID,  <ins> it SHOULD use Packet Number Space Identifier 0 in ACK_MP frames.  If an endpoint receives a ACK_MP frame with a non-existing packet number space ID, it MUST treat this as a connection error of type MP_CONNECTION_ERROR and close the connection. </ins> 10.


The endhost can use all the paths in the "Active" state, provided that the congestion control and flow control currently allow sending <del> of new data on a path. </del>  In the "Closing" state, the endhost SHOULD NOT send packets on this path anymore, as there is no guarantee that the peer can still map the "Closed" state to ensure a graceful termination of the path. When a path reaches the "Closed" state, the endhost releases all the <del> path's associated resources.  Consequently, the endhost is not able to send nor receive packets on this path anymore. </del>  5.

Fix issue and
For the transition from a "closing" state to a "closed" state In the path state figure in section 4.2, I find the phrase "path idle timeout" a bit confusing, because right now this value is supposed to be equal to maxidletimeout, but shouldn't a transition from a "closing" state to a "closed" state be much quicker than that from an "active" state to a "closed" state since the first transition is just what we expect to happen?
I think this is now fixed by .
In Section 4.3 we wrote: There are 2 problems in this figure: "Associated CID have been retired" should not cause the path turn into closed state, because in Section : So retiring associated CID only cause the resources belonging to the corresponding packet number space to be released, but not the whole path to be closed. In CID migration cases, endpoints just want to retire the old CID and use a new one, as path is defined as "refers to the 4-tuple" in the current draft, this operation will not cause the whole path context (including congestion control states, RTT measurements, etc.) to be removed. Path closing is triggered by PATHABANDONED frame, and does not have dependency on CID retiring (Although path closing would trigger the retirement of CID resource). So when pathstate transmit from "Closing" to "Closed", the proper condition might be "Acknowledgement of PATHABANDONED frame received" or "Path's draining timeout for at least 3 times the current PTO interval".
First, regarding the transitioning from a "closing" state to a "closed" state, there will be a problem if we use the receipt of the ACK of a PATHABANDON as a condition for the transitioning due to possible out-of-order delivery. Suppose a client uses DCID S2 to on its first path to send three pkts with the packet number 100, 101, and 102, where PATHABANDON frame is sent in packet 102. However, due to the out-of-order delivery, it is possible that 102 is acked first, while packet 100 and 101 are still in flight. Therefore, at this point, we cannot mark the first path as "closed" since it is also possible that the acks of those two packets will later return from the first path. Due to the above reasons, in the initial design, we say that the path should be closed after CIDs are retired. As shown in the path-closing figure (Fig.3) in the draft, after the client makes sure that the packets (100, 101) sent before PATHABANDON on path 1 are also acknowledged, it then decides that the CID S2 is no longer needed, and thus sending out the RETIRECONNECTION_ID frame. Second, regarding the transitioning from an "active" state to a "closed" state, yes, it is possible that we want to retire the old CID and use a new one, and I think the current figure is a bit confusing. The purpose of this transitioning is to handle exceptions and it basically says that when there are no available CIDs to use for communication on a particular path, we should close it. I think we can simply keep the "path's timeout" as the condition because when there are no available CIDs, the path timeout will be triggered anyway.
I agree that the transitioning from "Active" to "Closed" should not be directly done if we retire the associated CID. We could instead have an intermediate "Idle" state in which as long as you have no associated CID, keep relevant recovery/RTT/... contexts. In general, I think it could be worthwhile to make a clearer distinction between the acknowledgment/packet number context and the recovery one. For instance, if for any reason a host changes the DCID used over a given path, it should still keeps track of packets sent with the previous DCID (and thus possibly sent with a different packet number space). For the "Closing" to "Closed" transition, I tend to agree with Yunfei and I would not directly rely on the acknowledgment of the PATHABANDON frame to close my path. But as a sender, I can react to the acknowledgment of my PATHABANDON frame and send the RETIRECONNECTIONID frame. On the other hand, relying on 3*PTO to transition from "Closing" to "Closed" is probably more relevant than using the path's idle timeout.
I've just submitted PR for this issue, containing the suggestions from Yunfei and Quentin. The core points for this modification: Retiring CIDs would not trigger path closure. If a path is idle timeout, endpoints should send PATHABANDON frame before closing the path, so the path state transition would be "Active" -> "Closing" -> "Closed" in this situation If a path is detected blackhole or can't be used for some reason such as the whole network environment failed, endpoints can close the path immediately, because sending PATHABANDON frame on this path seem to be useless.
NAME your PR () says While you wrote in your comment above that it might be useless to send PATH_ABANDONED. Am I missing something?

The endhost can use all the paths in the "Active" state, provided that the congestion control and flow control currently allow sending  <ins> of new data on a path.  Note that if a path became idle due to a timeout, endpoints SHOULD send PATH_ABANDONED frame before closing the path. </ins> In the "Closing" state, the endhost SHOULD NOT send packets on this path anymore, as there is no guarantee that the peer can still map the "Closed" state to ensure a graceful termination of the path. When a path reaches the "Closed" state, the endhost releases all the  <ins> path's associated resources, including the associated Connection IDs. Endpoints SHOULD send RETIRE_CONNECTION_ID frames for releasing the associated Connection IDs following QUIC-TRANSPORT.  Considering endpoints are not expected to send packets on the current path in the "Closed" state, endpoints can send RETIRE_CONNECTION_ID frames on other available paths.  Consequently, the endhost is not able to send nor receive packets on this path anymore. </ins> 5.


4.2.  Each endpoint manages the set of paths that are available for transmission.  At any time in the connection, each endpoint can decide to abandon one of these paths, following for example changes Stateless Reset (Section 10.3 of QUIC-TRANSPORT) closes the connection. <del> 4.2.1. </del>  Both endpoints, namely the client and the server, can close a path, by sending PATH_ABANDON frame (see path-abandon-frame) which abandons such as one RTO if a path probing packet is received on a new path before sending the CONNECTION_CLOSE frame. <del> 4.2.2. </del>  Receiving a RETIRE_CONNECTION_ID frame causes the endpoint to discard the resources associated with that connection ID.  If the connection either acknowledged or marked as lost, and finally retire the Connection ID. <del> 4.2.3. </del>  QUIC-TRANSPORT allows for closing of connections if they stay idle for too long.  The connection idle timeout in multipath QUIC is for an excessive time or having to promptly reestablish a path after a spurious estimate of path abandonment by the client. <del> 4.3. </del>  fig-path-states shows the states that an endpoint's path can have. 12.2.  The ACK_MP frame (types TBD-00 and TBD-01; experiments use 0xbaba00..0xbaba01) is an extension of the ACK frame defined by QUIC- TRANSPORT.  It is used to acknowledge packets that were sent on

For issue
I agree with this point. For the receiver side, endpoint MAY ignore this frame if it would cause all the paths unavailable. I updated the description.
I believe stand-by (or backup) has been useful in MPTCP. This is not really about scheduling because all it says is: I won't use this path actively(yet) but please leave it open.
IMHO, this is a (simple) form of path prioritization. I'm not sure it should be part of the current. We could delegate this point to an "advanced" path management draft.
I agree that this should not be in the core. Let's start by assuming that all established paths can be used. We will then be able to add mechanisms to indicate that some existing paths should not currently be used. In MPTCP we only had limit messages to do this. In QUIC, we will have more flexibility in the definition of frames to encode such information if needed.
Okay, actually there might be two different signals here: One is "please do not use this path as long as you have others" but the other is "please keep this path open even if I don't use it". I agree we don't need the first one but I thought the second one might be useful because otherwise if no packets are received on a path the other end might assume the path to be closed after an idle time, no?
One problem is NAT timeout when we want to keep a path open but do not send any traffic. To solve this, we may want to send "ping" at a very low frequency to keep that path alive. Suppose if we don't have a stand-by state (which I think we should have eventually), but we do employ this ping mechanism to keep that path alive, does it solve Mirja's problem as now the other end won't close that path because it receives some "ping"s at a very low frequency?
I indeed think that we should have some mechanism (like sending a PING frame) to avoid some "path idle timeout".
Do we need any more text in the draft or can we just close this issue?
The current text in Section 3.2.3 ("To avoid idle timeout of a path, endpoints can send ack-eliciting packets such as packets containing PING frames Section 19.2 of [QUIC-TRANSPORT] on that path to keep it alive. Sending periodic PING frames also helps prevent middlebox timeout, as discussed in Section 10.1.2 of [QUIC-TRANSPORT].") is fine for me.
This is still much more expensive than MPTCP's backup subflows since we send a PING frame every N rtts, with N being close to 3.
I don't see many QUIC applications relying on keep-alive. For example, when studying DNS over QUIC, we concluded that it was much easier to use resumption and 0-RTT than to try to keep the paths open through NAT. I also think the issue is asymmetric: Servers have no good way to know that a path that has been idle for some time is still valid. The client might have moved, or the NAT binding might have changed. If servers send traffic on an idle path, there is a high risk that the traffic will be lost. The default should be, "silent close on idle". Clients typically do not have such limitations, because their traffic will force a new NAT binding if one is missing. There are mitigating strategies, such as only sending redundant traffic on suspect paths, but we probably don't need to discuss that here.
QUIC applications rely less on keep-alive (as you have 0-RTT resumption), however, I think the situation is different for multipath. If you have multiple paths available, you might still decide to only send data on one path at a time, e.g. you want to have a hot stand-by, meaning you already open a new path but didn't decide to use it yet, or want to be able to switch back to an "old" path anytime.
Do we need further text here or can we close this issue?
Actually thinking about this further I still think we should have at least one signal to tell the other end that a path should not be used. This is the typical handover case: a client opens both a wifi and a cellular path, also sends keep-alive on the cellular path to make sure one can switch over quickly. However, when it requests data from the server, the server doesn't know which path to use or that it should actually not use one of path as it is more costly. Therefore I think we need a signal to tell the other end that a path should not actively be used for sending data (as long as another path is still available).
NAME I agree that having a signal for stand-by is beneficial. Actually, we did have the standy-by signal with the PATHSTATUS frame in draft-liu. The PATHSTATUS frame signals three status: (1) abandon, (2) stand-by, and (3) available. PATHSTATUS Frame { Type (i) = TBD-03 (experiments use 0xbaba03), Path Identifier (..), Path Status sequence number (i), Path Status (i), Path Priority (i), } When the three drafts were merged, the PATHSTATUS frame was replaced by the current PATH_ABANDON frame, as at that time we wanted the first version to focus on the very basic features. I think we can put the stand-by status back if it proves to be a general requirement.
The stand-by status in draft-liu is used to explicitly inform the sender not to schedule packets on this path, but endpoints can keep the path context not to be removed. Once the endpoints need to use this path again, they can send PATH_STATUS(active) to update the status, and send packets on the path immediately without path validation and other preparation for this path. We can discuss about whether if we need to add the mechanism into the working group version.
At IETF-113 there was general support for this idea. Next step: write PR
The PATHSTATUS frame as described in PR is a rather generic way to update path information. Actually not sure if we need this at this point. I was assuming that indicating a path to be a stand-by or back-up path is a rather static information. E.g. if your mobile link is more expensive, this is static and will not change over the life time of the path. As such another option would be to signal this information during path initiation, e.g. creating an MPPATH_CHALLANGE frame that contains a flag.
It is generally preferred to defined composable frames, rather than create a special purpose version of an existing frame. I would combine Status & Challenge in a single message rather than modifying challenge. But we have to understand what happens if a challenge is lost, repeated, etc. I am also not sure that the 'status' is "once and forever". I could see the status evolving over time, and alternating between standby and available. But we need to add a bit to the specification. In particular: is there a default status when no status frame have been received on a path? does the status change if the peer starts sending non-probing frames on the path? can both client and server change the status of a path? do frames affect both directions of a path?
Yes, available. However, I wouldn't really call this a default status, because this info is a signal to the other end in order to give a recommendation if that should be sent on this path or not, but the fine sending decision is a local decision. If this info is not available, the sender has to base its decision on other (local known) criteria. No. Yes and no. The status tells the other end if or if not it should send data on the path. So effectively it impacts only one direction of the path as the other direction is a local decision. No. As I just said. This is a recommendation for the sender, however, if the sender follows that recommendation is effectively also a local decision. Again, I think we should at this point really just focus on the standby function and not make this too generic because that makes is more complicated.
NAME the current default status is "standby until the client has sent non probing frames, available after that" -- per RFC 9000. I would think that the client sending a status frame overrides that, since "status" is not "probing", but it is probably worth specifying. Similarly, I do agree with the "unilateral" view of status that you are presenting, "just tell the other end whether to send on that path of not." But it is worth specifying.
Okay, if we agree that we want a separate PATH_STATUS frame then I think PR is ready to merge. NAME and NAME can you review and approve PR ? Thanks!
Sounds good to me.Looks good.

4.2. <ins> An endpoint uses PATH_STATUS frames to inform that the peer should send packets in the preference expressed by these frames.  Notice that the endpoint might not follow the peer's advertisements, but the PATH_STATUS frame is still a clear signal of suggestion for the preference of path usage by the peer. PATH_STATUS frame describes 2 kinds of path states: Mark a path as "available", i.e., allow the peer to use its own logic to split traffic among available paths. Mark a path as "standby", i.e., suggest that no traffic should be sent on that path if another path is available. Endpoints use Path Identifier field in PATH_STATUS frame to identify which path's state is going to be changed.  Notice that PATH_STATUS frame can be sent via a different path.  An Endpoint MAY ignore the PATH_STATUS frame if it would make all the paths unavailable in a single connection. 4.3. </ins> Each endpoint manages the set of paths that are available for transmission.  At any time in the connection, each endpoint can decide to abandon one of these paths, following for example changes Stateless Reset (Section 10.3 of QUIC-TRANSPORT) closes the connection.  <ins> 4.3.1. </ins> Both endpoints, namely the client and the server, can close a path, by sending PATH_ABANDON frame (see path-abandon-frame) which abandons such as one RTO if a path probing packet is received on a new path before sending the CONNECTION_CLOSE frame.  <ins> 4.3.2. </ins> Receiving a RETIRE_CONNECTION_ID frame causes the endpoint to discard the resources associated with that connection ID.  If the connection either acknowledged or marked as lost, and finally retire the Connection ID.  <ins> 4.3.3. </ins> QUIC-TRANSPORT allows for closing of connections if they stay idle for too long.  The connection idle timeout in multipath QUIC is for an excessive time or having to promptly reestablish a path after a spurious estimate of path abandonment by the client.  <ins> 4.4. </ins> fig-path-states shows the states that an endpoint's path can have. 12.2. <ins> PATH_STATUS Frame are used by endpoints to inform the peer of the current status of one path, and the peer should send packets according to the preference expressed in these frames.  PATH_STATUS frames are formatted as shown in fig-path-status-format. PATH_STATUS Frames contain the following fields: Path Identifier: An identifier of the path, which is formatted as shown in fig-path-identifier-format.  Exactly the same as the definition of Path Identifier in {#path-abandon-frame}. Path Status sequence number: A variable-length integer specifying the sequence number assigned for this PATH_STATUS frame.  The sequence number MUST be monotonically increasing generated by the sender of the Path Status frame in the same connection.  The receiver of the Path Status frame needs to use and compare the sequence numbers separately for each Path Identifier. Available values of Path Status field are: 1: Standby 2: Available Endpoints use PATH_STATUS frame to inform the peer whether it prefer to use this path or not.  If an endpoint receives a PATH_STATUS frame containing 1-Standby status, it SHOULD stop sending non-probing packets on the corresponding path, until it receive a new PATH_STATUS frame containing 2-Available status with a higher sequence number referring to the same path. Frames may be received out of order.  A peer MUST ignore an incoming PATH_STATUS frame if it previously received another PATH_STATUS frame for the same Path Identifier with a sequence number equal to or higher than the sequence number of the incoming frame. PATH_STATUS frames SHOULD be acknowledged.  If a packet containing a PATH_STATUS frame is considered lost, the peer should only repeat it if it was the last status sent for that path - as indicated by the sequence number. 12.3. </ins> The ACK_MP frame (types TBD-00 and TBD-01; experiments use 0xbaba00..0xbaba01) is an extension of the ACK frame defined by QUIC- TRANSPORT.  It is used to acknowledge packets that were sent on


calculated by combining the packet protection IV with the packet number and with the path identifier. <del> The path ID for 1-RTT packets is the sequence number of of QUIC- </del>  TRANSPORT, or zero if the Connection ID is zero-length.  Section 19 of QUIC-TRANSPORT encodes the Connection ID Sequence Number as a variable-length integer, allowing values up to 2^62-1; in this

It's a grammar error fix in the aead section.
from URL The path ID for 1-RTT packets is the sequence number of of {{QUIC-TRANSPORT}} maybe it should be The path ID for 1-RTT packets is the sequence number of Connection ID of {{QUIC-TRANSPORT}}
Thanks Wu! I fixed this grammar error in PR .

calculated by combining the packet protection IV with the packet number and with the path identifier.  <ins> The path ID for 1-RTT packets is the sequence number of QUIC- </ins> TRANSPORT, or zero if the Connection ID is zero-length.  Section 19 of QUIC-TRANSPORT encodes the Connection ID Sequence Number as a variable-length integer, allowing values up to 2^62-1; in this


When more than one path is available, hosts shall monitor the arrival of non-probing packets and the acknowledgements for the packets sent over each path.  Hosts SHOULD stop sending traffic on a path if for <del> at least max_idle_timeout milliseconds (a) no non-probing packet was received or (b) no non-probing packet sent over this path was acknowledged, but MAY ignore that rule if it would disqualify all available paths.  To avoid idle timeout of a path, endpoints can send ack-eliciting packets such as packets containing PING frames (Section 19.2 of QUIC-TRANSPORT) on that path to keep it alive. Sending periodic PING frames also helps prevent middlebox timeout, as discussed in Section 10.1.2 of QUIC-TRANSPORT. </del>  Server MAY release the resource associated with paths for which no non-probing packet was received for a sufficiently long path-idle

Replace "maxidletimeout" with "a path's idleperiod" in the IdleTimeout Section and make sure that the idle_period is larger than 3 times the path's PTO.
This was discussed in issue and PR .
Regarding the maxidletimeout, RFC9000 says "To avoid excessively small idle timeout periods, endpoints MUST increase the idle timeout period to be at least three times the current Probe Timeout (PTO)." As in multi-path QUIC, the PTO is per-path, when maxidletimeout is used to close a connection, it makes sense to set maxidletimeout = 3max(PTO1, PTO2). But when it comes to close a path, I am not sure if the timeout for path1 should also depend on the PTO of path 2?
I think there are two idle timeouts: the "connection idle timeout" and the "path idle timeout". For the "connection idle timeout", I agree that it should be at least 3PTO_max. Triggering this timeout closes the connection. For the "path idle timeout", this might be a way to have a stronger guarantee to stop using paths (closing them) after some inactivity than the text proposed in . Still, if we define such a mechanism, we need to know whether all paths should have the same path timeout value or not (in the latter case, a transport parameter might not be the best way).
I would avoid having a different timer for a path than for a connection. That would make the protocol more complex without a lot of benefits. If a host wants to use a shorter timeout per path than the connection timeout, it can simply define it and use a PATH_ABANDON frame to indicate that the path is abandoned. However, we need to be clearer in 3.2.3 to indicate that a path can be considered valid if either packets are received on that path or packets sent on that path are acknowledged (possibly on another path)
Presented at IETF-113 but no time for discussion.
I have submitted PR to resolve this issue according to the above discussions.
PR was merged but forgot to close issue...
Just modified "URL least maxidletimeout milliseconds (a)..." into "... at least the period of the idle timeout as specified in {{Section 10.1 of QUIC-TRANSPORT}} (a)..." It's better to just modify the corresponding 2 lines, but it's ok for me.

When more than one path is available, hosts shall monitor the arrival of non-probing packets and the acknowledgements for the packets sent over each path.  Hosts SHOULD stop sending traffic on a path if for  <ins> at least the period of the idle timeout as specified in Section 10.1. of QUIC-TRANSPORT (a) no non-probing packet was received or (b) no non-probing packet sent over this path was acknowledged, but MAY ignore that rule if it would disqualify all available paths.  To avoid idle timeout of a path, endpoints can send ack-eliciting packets such as packets containing PING frames (Section 19.2 of QUIC- TRANSPORT) on that path to keep it alive.  Sending periodic PING frames also helps prevent middlebox timeout, as discussed in Section 10.1.2 of QUIC-TRANSPORT. </ins> Server MAY release the resource associated with paths for which no non-probing packet was received for a sufficiently long path-idle


endpoint abandons a path, the peer will not receive any more non- probing packets on that path. <del> An endpoint that wants to close a path SHOULD NOT rely on implicit signals like idle time or packet losses, but instead SHOULD use explicit request to terminate path by sending the PATH_ABANDON frame (see path-abandon-frame). </del>  4.2.1.

.
Should the spec say something about stateless reset? Suppose a node is sending on two paths with two different DCID and two corresponding stateless reset secrets, and receives a stateless reset packet that matches the reset secret on the first path. Should it: 1) Abandon that path and continue the connection with the other path? 2) Abandon the connection?
That's a good point. RFC9000 states that stateless resets should be used in last resort when the endpoint does not have access to the connection state. If hosts have still access to the connection state and want to abandon a specific path, I would expect them to rely on PATH_ABANDON frame (or on path idle timeout). So when receiving a stateless reset, I would abandon the connection. Depending on the number of impacts on existing RFC9000 mechanisms, it may be useful to write a section (or at least, a paragraph) clarifying these points.
We should review the current text and make sure we cover everything clearly. Maybe add some more text to the intro part of 3.2
Careful with implicit actions!LGTM

endpoint abandons a path, the peer will not receive any more non- probing packets on that path.  <ins> An endpoint that wants to close a path SHOULD use explicit request to terminate the path by sending the PATH_ABANDON frame (see path- abandon-close).  Note that while abandoning a path implies Connection ID retirement, only retiring the associated Connection ID does not necessarily advertise path abandon (see retire-cid-close).  However, implicit signals such as idle time or packet losses might be the only way for an endhost to detect path closure (see idle-time-close). Note that other explicit closing mechanisms of QUIC-TRANSPORT still apply on the whole connection.  In particular, the reception of either a CONNECTION_CLOSE (Section 10.2 of QUIC-TRANSPORT) or a Stateless Reset (Section 10.3 of QUIC-TRANSPORT) closes the connection. </ins> 4.2.1.


the connection ID, but MUST use a different connection ID when doing so.  4.2.3. QUIC-TRANSPORT allows for closing of connections if they stay idle

It might be possible to be in a state where a sender retires a DCID that was used by still in-flight packets. Hence, it is possible for the sender to receive a ACKMP frame referencing the retired DCID. Depending on the situation: The sender can keep a way to track the sent packet with the retired DCID sequence number, allowing proper acknowledgement of the packets. The sender drops all the state related to the DCID, hence marking the in-flight packets as being lost and ignoring ACKMP frames having a retired DCID sequence number. While this should not affect interoperability, it might be worthwhile to add a sentence or two to mention the possible performance issue in such situation.
We could add some text to . Can you propose a PR NAME ?

the connection ID, but MUST use a different connection ID when doing so. <ins> Note that if the sender retires a Connection ID that is still used by in-flight packets, it may receive ACK_MP frames referencing the retired Connection ID.  If the sender stops tracking sent packets with retired Connection ID, these would be spuriously marked as lost. To avoid such performance issue without keeping retired Connection ID state, an endpoint should first stop sending packets with the to-be- retired Connection ID, then wait for all in-flight packets to be either acknowledged or marked as lost, and finally retire the Connection ID. </ins> 4.2.3. QUIC-TRANSPORT allows for closing of connections if they stay idle


9.1.3. <del> The ACK Delay field of the ACK frame is relative to the largest acknowledged packet number (see Section 13.2.5 of QUIC-TRANSPORT). When using paths with different transmission delays, the reported host delay will most of the time relate to the path with the shortest latency.  To collect ACK delays on all the paths, hosts should rely on time stamps as described in QUIC-Timestamp. </del>  9.1.4.

For issue , add some considerations for RTT computation in our single pns implementation. Not sure if it is easy enough to understand. Please feel free to change.
Yes, this needs more discussion. Also maybe we want to move this text rather in the "Implementation Considerations" section?
NAME NAME updated this PR. Can we merge it? Note that this PR is only for SPNS and part of that respective section. Based on his report, the strategy seems reasonable. For ACK_MP we have the following text in the packet scheduling section (7.):
Comment by NAME (on PR ): I think we expand this section a bit as we found getting the delay right was non-trivial. QUIC time-stamp would work for sure. But if one decides not to use QUIC timestamp, we probably want to explain what is needed to be done here.
I have submitted PR for this one.
Closing as got merged.
I'm ok with the current version, just a few editorial hints.Seems like a reasonable tradeoff, easy to implement.

9.1.3.  <ins> When SPNS is in use, accurate RTT estimation requires more careful considerations.  According to QUIC-RECOVERY, an endpoint generates an RTT sample on receiving an ACK frame that meets the following two conditions: (1) the largest acknowledged packet number is newly acknowledged, and (2) at least one of the newly acknowledged packets was ack-eliciting.  The RTT sample, latest_rtt is calculated as the time elapsed since the largest acknowledged packet was sent. However, when applying the above algorithm with SPNS, one may encounter the following issues: (1) RTT of some paths are not updated timely if ACKs are mostly returned from other paths, and (2) ACK frames depend on the largest received packet of the connection, not the path, and the resulted RTT sample may be the sum of the one-way delays of two different paths.  One solution for accurate RTT measurements is to employ time-stamps as described in QUIC-Timestamp. If one chooses not to use time-stamps but wants to get reasonable estimation of RTTs on multiple paths with single packet number space, the following practices can be used: For packet receiver (ACK sender): Maintain an ACK threshold and an ACK timer for each path.  A path should send an ACK when it receives ack-eliciting-threshold number of ack-eliciting packets (e.g., two) on this path, and an ack- eliciting packet must be acknowledged within MAX_ACK_DELAY. Write ACK frame based on the largest received packet of the path. Start the ACK ranges with the largest received packet number of that path, which means that the "Largest Acknowledged" field is the path's largest packet number and the "ACK Delay" field is the delay time of the path's largest received packet. For packet sender (ACK receiver): Maintain an unacked list for each path to retrieve the packets that has been sent when an ACK is received.  It can coexist with the unacked list of the connection layer or packet number space layer. Generate RTT sample for a path when the following conditions are met: (1) the largest acknowledged packet number is newly acknowledged by the ACK received from this path, and (2) at least one of the newly acknowledged packets was ack-eliciting. </ins> 9.1.4.


4.3.2.  Receiving a RETIRE_CONNECTION_ID frame causes the endpoint to discard the resources associated with that connection ID.  If the connection ID was used by the peer to identify a path from the peer to this either acknowledged or marked as lost, and finally retire the Connection ID. <del> 4.3.3. </del>  QUIC-TRANSPORT allows for closing of connections if they stay idle for too long.  The connection idle timeout in multipath QUIC is

Should
I rewrote the text based on the suggestion from NAME to discuss the case of zero-length CIDs.
Is there any reason why a new parameter isn't defined to negotiate maxpaths rather than reusing this existing parameter? That design is much more cleaner. For example, the max paths wouldn't be ignored even when zero-length CIDs are in use. Unless I'm mistaken, the current design have to comply with the following from RFC9000: >If an endpoint issues a zero-length connection ID... and therefore ignores the activeconnectionidlimit value received from its peer. BTW, how the following MUST will be honored for the zero-length CID case:
From RFC9000 (Section 9.5), an endhost cannot (voluntary) reuse a given CID on different addresses. Since CIDs are the path identifiers, this already restricts the number of concurrent paths. Given that paths must be symmetrical, this should restrict the number of concurrent paths to the minimum advertised value of . Note that the actual limit can be lower than this, as you depend on your peer to have your CIDs. For the parameter, this is something we considered in early multipath drafts (such as draft-deconinck-quic-multipath-02). Such value would only be meaningful when it is lower than the advertised . And even in such case, it is difficult to enforce that limit. If you provide 8 CIDs to your peer and request to be 2, how would you do that? Especially when handling transient situations (i.e., stop using a path on a network A to use another on network B), the receiver might notice 3 paths being in concurrent use (especially if network B is faster than network A), even if the sender behaves nicely. On the other hand, if one host definitely wants to limit the number of concurrent paths, it can simply as most active CIDs. For the zero-length CIDs, I think there are two parts. If we consider one-sided zero-length CIDs while the other direction uses non-zero-length CIDs, the maximum number of paths is constrained by the value of the non-zero-length CID side. If we now consider both sides using zero-length CIDs, then I would keep the minimum of both values? RFC9000 states that the host can ignore because it will not send NEWCONNECTION_ID frames, but we can extend this meaning in the draft. In any case, it might be better to clarify this, and we will likely perform a strong editorial pass on the whole text once we get an agreement on .
I agree with NAME Having two limits instead of just one just introduces complexity with little benefit. Yes, the case of two endpoints both using zero-length CIDs may be under specified. But the deployments of that scenarios are going to be very limited. If the server is part of a frame and uses zero-length CID, the client is identified by its IP address and port. The load balancer will struggle to match the new IP and port of a new path with the original values used in connection establishment. I don't see how that could work. So we are pretty much left to peer to peer scenarios, in which the server is a single computer. Even there, the matching of the new IP and port with the original client requires a combination of guesswork and maybe trial decryption. If developers are ready to do that, they can probably invent a way to manage the path number...
I'm not sure to get why you say that CIDs are "path identifiers". Also, please note that an "address" in 9000 is defined as follows:
Sure, this reasoning is still valid independent of whether activeconnectionid_limit or a new transport metric is defined.
This same case can be considered when more than activeconnectionidlimit are used (including in transient situations you mentioned). What concerns me with activeconnectionidlimit is that the connection must be closed as per: while, with a dedicated path_max, new paths can be just discarded while maintaining the connection alive.
Agree. This is only possible when dedicated parameters are defined.
Noted.
I'm not sure to see complexities out there. Using connection IDs to infer per path specifics is not a clean design, btw.
Relying to previous comments: 1) the limits the number of CID that a peer MAY advertise at the same time. A peer MAY advertise "at most" this limit. 2) there is no guarantee that a peer will advertise "at least" the . For example, a node could decide to never advertise more than 3 CID, even if its peer's limit is 9. 3) if a node reuses a non-zero-length CID on a different path mimics, the peer is most likely to treat that as a "NAT rebinding" event. There will be an exchange of probes, after which the peer will retain either the old or the new path. Thus, there can never be more active paths than the . 4) Since a new path requires a new connection ID in each direction, the maximum number of paths cannot be higher than the lowest of the two advertised by both peers. I think the issue boils down to "how does a node refuse to establish a new path". Imagine a node with a hard limit to maximum two simultaneous paths per connection, but advertising 3 CIDs. With RFC 9000 the only option would be to ignore incoming challenges for new paths. The peer will see timeouts, and repeat the challenges a number of time before giving up. If the peer knew that the local node supports at most two paths, it might not bother sending new challenges in the first place, saving some time. But there are synchronization issues. The peer may or may not know how many paths are currently active. For example, one of the current paths may have been abandoned, and the peer does not know that yet. So if we create a "max path" mechanism, we also need some kind of synchronization mechanism. Or, we could add a soft-error mechanism of some kind, something like a "CHALLENGE_REFUSED" frame, maybe carrying an error reason. But we would have to work out the complexity, etc. Looks like something we could do later, maybe an extension on top of the basic multipath.
Fully Agree, Christian.
That's it! I'd like the mechanism to not lead to closing the connection when such new paths are being added but a limit is fired.
Let's not add additionally frame(s) now, but do we want to add some text about "how to refuse a new path"?
Actually, there is a pretty straightforward way to "refuse a new path" -- just send back an "abandon path" frame.
True. I think we should add some explicit text that you should send an abandon frame (on an existing path) to refuse a new path and not reply to oath challenge.
Looks good to me.

4.3.2. <ins> An endpoint may deny the establishment of a new path initiated by its peer during the address validation procedure.  According to QUIC- TRANSPORT, the standard way to deny the establishment of a path is to not send a PATH_RESPONSE in response to the peer's PATH_CHALLENGE. An endpoint that has negotiated the usage of the multipath extension MAY use an explicit method by sending on another active path a PATH_ABANDON frame containing the Path Identifier of the refused path, but only if the PATH_CHALLENGE arrives in a packet using a non- zero length Connection ID. 4.3.3. </ins> Receiving a RETIRE_CONNECTION_ID frame causes the endpoint to discard the resources associated with that connection ID.  If the connection ID was used by the peer to identify a path from the peer to this either acknowledged or marked as lost, and finally retire the Connection ID.  <ins> 4.3.4. </ins> QUIC-TRANSPORT allows for closing of connections if they stay idle for too long.  The connection idle timeout in multipath QUIC is