The layout of a Version Negotiation packet is: <del> The value in the Unused field is selected randomly by the server. Clients MUST ignore the value of this field.  Servers SHOULD set the most significant bit of this field (0x40) to 1 so that Version Negotiation packets appear to have the Fixed Bit field. </del>  The Version field of a Version Negotiation packet MUST be set to 0x00000000.

Éric Vyncke said:
No, but yes. The Unused field is defined in Invariants to be whatever the sender wants, so it's perhaps inconsistent to re-slice the fields in Transport. However, proposes removing this SHOULD entirely, which would also address this issue.
Since is design, marking this as such, too.
To make it clear what happened here as it several redirects. This issue was closely related to . Which was resolved by a better explanation . So I consider it resolved.
Closing this now that the IESG have approved the document(s).
Robert Wilton said:
I think that Rob's suggestion to remove the "SHOULD" is ideal.
Does someone remember why this SHOULD was added? The fixed bit is useful in the client-to-server direction because it allows servers to demultiplex QUIC with other protocols, but I don't remember what benefit it provided in the server-to-client direction.
I believe there 'could' be applications(ie: WebRTC) which share a port with QUIC and might want to use this bit to demux even on the client side, but that's seems like a pretty theoretical problem, so I'd be inclined to drop the SHOULD.
In a p2p setup, you might run QUIC clients and servers on the same port (in fact, that's what we're doing in libp2p), so demultiplexing might be important for both sides in that case.
Yes, this was to avoid collision with p2p protocols. As I recall, we had decided that this would be something we would recommend for v1, but not require this for future versions... and that if both endpoints agreed, then they could set the bit to something other than 1. I don't see why we should change this.
In a P2P setup where we're demultiplexing with another bootstrapping protocol over UDP, is there a need for version negotiation packets at all? I'd expect the bootstrapping protocol to convey the supported QUIC versions, and at that point you don't need version negotiation. I'm in favor of removing the SHOULD on VN packets.
My thinking is along the lines of NAME but I also don't care much about whether we remove this or not.
The VN packet is version-independent. v1 shouldn't be constraining its contents. However, implementations are free to select the value they put there any way they wish, so if they find it useful to always set that bit, they may.
This isn't constraining the contents of a VN packet broadly, it is constraining what a v1 sender sends in a VN packet. And, I don't think it's reasonable to require that P2P protocols shouldn't need to use VN. My high-level point is this: IIRC, we had this SHOULD for co-existence with P2P protocols, and we went through a lot of discussion, especially with ART folks on this. Do we really want to re-litigate this point at this stage in the process? Maybe I'm mis-remembering. If I am, and this SHOULD was there for a different reason that is no longer valid (or never was important), I'm happy to remove this.
That's right. Maybe we should have been more studious in capturing reasons. I think that for those P2P applications that care about multiplexing, this is a non-issue. Those applications can use their signaling channel to ensure that version negotiation does not happen. If things get badly out of hand, endpoints can ensure that Version Negotiation packets are sent with the bit set to conform to other constraints.
That applies to peers discovered during the execution of the p2p protocol. Every p2p network has some hard-coded bootstrap nodes though, for which the QUIC version might not be known in advance.
NAME are those hard-coded bootstrap nodes QUIC clients or servers? We're only talking about receipt of VN packets here.
I think that we can keep the inconsistency, but we need someone (NAME to follow up with Rob.
NAME At this point, I'd rather not change what was a design decision made by the wg, so I propose close with no action to this issue (not merge ). Can you see if the is satisfactory to you?
To check that my understanding is correct: VN packets (as per the Invariants doc) MAY set the fixed bit. VN packets for QUIC version 1 (as per the transport doc) SHOULD set the fixed bit. This behaviour is consistent, but the documents need to explain this more clearly. Particularly, because the the first sentence of section 17.2.1 states: " A Version Negotiation packet is inherently not version-specific," and yet the value set in this field might be version specific. Hence, I would suggest that you expand the description in the transport draft to explain that it SHOULD be set for QUIC version 1, but that other versions of QUIC may relax this requirement. Noting that the transport draft already talks about future versions having different requirements on the length of connection ids.
Just to close the loop here. I've added an explanation of two things to the draft that is about to go out: that this recommendation is to allow for multiplexing, and that this recommendation is not guaranteed to apply when other QUIC versions are in use. I think that is in line with what NAME suggests. If you disagree, we might be able to tweak this more later, but I need to publish -34 so that the wheels of the process can continue to turn.
Just to confirm that I am happy with the committed text change. Thanks for accommodating.
A bit late, but LGTM

The layout of a Version Negotiation packet is:  <ins> The value in the Unused field is set to an arbitrary value by the server.  Clients MUST ignore the value of this field.  Where QUIC might be multiplexed with other protocols (see RFC7983), servers SHOULD set the most significant bit of this field (0x40) to 1 so that Version Negotiation packets appear to have the Fixed Bit field.  Note that other versions of QUIC might not make a similar recommendation. </ins> The Version field of a Version Negotiation packet MUST be set to 0x00000000.


the message exchange, they must be received and processed before the message can be consumed.  See header-formatting for more details. <del> The "chunked" transfer encoding defined in Section 7.1 of HTTP11 MUST NOT be used. </del>  A response MAY consist of multiple messages when and only when one or more interim responses (1xx; see Section 15.2 of SEMANTICS) precede a present in an HTTP/3 request header; when it is, it MUST NOT contain any value other than "trailers". <del> This means that an intermediary transforming an HTTP/1.x message to HTTP/3 will need to remove any fields nominated by the Connection field, along with the Connection field itself.  Such intermediaries SHOULD also remove other connection-specific fields, such as Keep- Alive, Proxy-Connection, Transfer-Encoding, and Upgrade, even if they are not nominated by the Connection field. </del>  4.1.1.1. To ensure that the HTTP/1.1 request line can be reproduced accurately, this pseudo-header field MUST be omitted when translating from an HTTP/1.1 request that has a request target in <del> origin or asterisk form; see Section 3.2 of HTTP11.  Clients that generate HTTP/3 requests directly SHOULD use the ":authority" </del>  pseudo-header field instead of the Host field.  An intermediary that converts an HTTP/3 request to HTTP/1.1 MUST create a Host field if one is not present in a request by copying the value of MUST include a value of '/'.  The exception to this rule is an OPTIONS request for an "http" or "https" URI that does not include a path component; these MUST include a ":path" pseudo-header field <del> with a value of '*'; see Section 3.2.4 of HTTP11. </del>  All HTTP/3 requests MUST include exactly one value for the ":method", ":scheme", and ":path" pseudo-header fields, unless it is a CONNECT The ":authority" pseudo-header field contains the host and port to connect to (equivalent to the authority-form of the request-target <del> of CONNECT requests; see Section 3.2.3 of HTTP11) </del>  The request stream remains open at the end of the request to carry the data to be transferred.  A CONNECT request that does not conform

Three of these are simple -- origin and asterisk form lives in Semantics now, and we didn't get an update to the new pointer. Those are in the first commit. The second commit might be more controversial. See .
NAME just a heads-up that this is aligning with http2-bis in referencing SEMANTICS, which says... I'm not totally thrilled with dropping that back to a SHOULD, but it has the caveat that requests will look malformed if you don't, so I think it covers it.
NAME said
NAME said
NAME This is text imported mostly-unchanged from RFC7540, but I'm always happy to improve upon the past. This point actually in the discussion of , which is rewording that paragraph slightly, but your point would still remain with the new text. The key is that HTTP fields are an extension point, and some fields are defined to have hop-by-hop semantics. The endpoint necessarily knows the meaning of all fields it generates, and so we can tell it that it MUST NOT generate a field with hop-by-hop semantics. However, the intermediary does not necessarily know the meaning of all fields some other endpoint sends through it. Another way to read this is "MUST remove all fields which are known to have hop-by-hop semantics, but we acknowledge you might miss some"; that's a difficult requirement to test. We've tended to use SHOULD for unenforceable MUSTs throughout these documents. If you'd like to suggest a better way to phrase it, I'm open to incorporating it into or a follow-up.
As NAME in URL, the core HTTP spec now has , written more clearly. We should just reference them.
That WFM. Barry
now includes the same text as URL
Great; sounds like I'll be moving to a Yes ballot when I see the revised draft posted. Thanks, Mike, and all. Barry
NAME points out that, in addition to a couple easily-resolved normative references to the HTTP/1.1 draft (this content has moved to Semantics), there's a normative reference to "chunked" transfer encoding being prohibited. But technically, this is still a MUST NOT for an informative reference. One resolution would be to make it a statement of fact rather than a conformance requirement -- to say that the transfer codings defined by the HTTP/1.1 are HTTP/1.1-specific and not applicable to HTTP/3. But that's a broader assertion than just "chunked." Is there a reason we need to keep e.g. "Transfer-Encoding: gzip"?
My +1 goes to talking about transfer-encodings in general rather than just chunked, but as stated in the review comment, IIUC we already use different language for endpoints and intermediaries and therefore am afraid we have to keep doing so.
I think that the tweak to translation behaviour is probably necessary. I'll be opening a bug on h2 as well.NAME Thank you for your comments and the changes. I agree about the intent, and I am fine with retaining the SHOULD that we already have. I also like the updated text in the other section that explicitly states that intermediaries "MUST decode and remove transfer encodings."

the message exchange, they must be received and processed before the message can be consumed.  See header-formatting for more details.  <ins> Transfer codings (see Section 6.1 of HTTP11) are not defined for HTTP/3; the Transfer-Encoding header field MUST NOT be used. </ins> A response MAY consist of multiple messages when and only when one or more interim responses (1xx; see Section 15.2 of SEMANTICS) precede a present in an HTTP/3 request header; when it is, it MUST NOT contain any value other than "trailers".  <ins> An intermediary transforming an HTTP/1.x message to HTTP/3 MUST remove connection-specific header fields as discussed in Section 7.6.1 of SEMANTICS, or their messages will be treated by other HTTP/3 endpoints as malformed (malformed). </ins> 4.1.1.1. To ensure that the HTTP/1.1 request line can be reproduced accurately, this pseudo-header field MUST be omitted when translating from an HTTP/1.1 request that has a request target in  <ins> origin or asterisk form; see Section 7.1 of SEMANTICS.  Clients that generate HTTP/3 requests directly SHOULD use the ":authority" </ins> pseudo-header field instead of the Host field.  An intermediary that converts an HTTP/3 request to HTTP/1.1 MUST create a Host field if one is not present in a request by copying the value of MUST include a value of '/'.  The exception to this rule is an OPTIONS request for an "http" or "https" URI that does not include a path component; these MUST include a ":path" pseudo-header field  <ins> with a value of '*'; see Section 7.1 of SEMANTICS. </ins> All HTTP/3 requests MUST include exactly one value for the ":method", ":scheme", and ":path" pseudo-header fields, unless it is a CONNECT The ":authority" pseudo-header field contains the host and port to connect to (equivalent to the authority-form of the request-target  <ins> of CONNECT requests; see Section 7.1 of SEMANTICS) </ins> The request stream remains open at the end of the request to carry the data to be transferred.  A CONNECT request that does not conform


3.2. The dynamic table consists of a list of field lines maintained in <del> first-in, first-out order.  Each HTTP/3 endpoint holds a dynamic table that is initially empty.  Entries are added by encoder instructions received on the encoder stream; see encoder- instructions. </del>  The dynamic table can contain duplicate entries (i.e., entries with the same name and same value).  Therefore, duplicate entries MUST NOT The size of the dynamic table is the sum of the size of its entries. The size of an entry is the sum of its name's length in bytes, its <del> value's length in bytes, and 32.  The size of an entry is calculated using the length of its name and value without Huffman encoding applied. </del>  3.2.2.

I opted to reframe the language from HTTP/3 endpoint to decoder, since encoder and decoder instances are what this spec primarily talks about. We already say that HTTP/3 endpoints contain both an encoder and a decoder. I also added a comment that encoders track the contents of the table at the decoder. I specifically did not say that they keep a full copy of the table, however; they might not.
NAME said:
NAME said:

3.2. The dynamic table consists of a list of field lines maintained in  <ins> first-in, first-out order.  A QPACK encoder and decoder share a dynamic table that is initially empty.  The encoder adds entries to the dynamic table and sends them to the decoder via instructions on the encoder stream; see encoder-instructions. </ins> The dynamic table can contain duplicate entries (i.e., entries with the same name and same value).  Therefore, duplicate entries MUST NOT The size of the dynamic table is the sum of the size of its entries. The size of an entry is the sum of its name's length in bytes, its  <ins> value's length in bytes, and 32 additional bytes.  The size of an entry is calculated using the length of its name and value without Huffman encoding applied. </ins> 3.2.2.


HTTP semantics (SEMANTICS) are used for a broad range of services on the Internet.  These semantics have most commonly been used with <del> HTTP/1.1, over a variety of transport and session layers, and with HTTP/2 over TLS.  HTTP/3 supports the same semantics over a new </del>  transport protocol, QUIC. 1.1. HTTP/1.1 (HTTP11) uses whitespace-delimited text fields to convey HTTP messages.  While these exchanges are human-readable, using whitespace for message formatting leads to parsing complexity and <del> excessive tolerance of variant behavior.  Because HTTP/1.x does not include a multiplexing layer, multiple TCP connections are often used to service requests in parallel.  However, that has a negative impact on congestion control and network efficiency, since TCP does not share congestion control across multiple connections. </del>  HTTP/2 (HTTP2) introduced a binary framing and multiplexing layer to improve latency without modifying the transport layer.  However, same packet as the QUIC CONNECTION_CLOSE frame improves the chances of the frame being received by clients.  5.4. For various reasons, the QUIC transport could indicate to the

Address multiple editorial comments.
NAME said
NAME said
The text currently says: Transport makes the following addition, in : That might be worth reiterating in HTTP/3.
NAME said
Two separate questions. I'm fine generalizing it to HTTP/1.x. The link between the first two sentences is the fact that HTTP/1.x uses human-readable whitespace-delimited fields, but those attributes make parsing inconsistent; subsequent versions of HTTP/2 went a different direction. If you're talking about the second and third, that could easily be a paragraph split; it's a change of idea under the umbrella of major changes of direction from H1 to H2+.

HTTP semantics (SEMANTICS) are used for a broad range of services on the Internet.  These semantics have most commonly been used with  <ins> HTTP/1.1 and HTTP/2.  HTTP/1.1 has been used over a variety of transport and session layers, while HTTP/2 has been used primarily with TLS over TCP.  HTTP/3 supports the same semantics over a new </ins> transport protocol, QUIC. 1.1. HTTP/1.1 (HTTP11) uses whitespace-delimited text fields to convey HTTP messages.  While these exchanges are human-readable, using whitespace for message formatting leads to parsing complexity and  <ins> excessive tolerance of variant behavior. Because HTTP/1.1 does not include a multiplexing layer, multiple TCP connections are often used to service requests in parallel.  However, that has a negative impact on congestion control and network efficiency, since TCP does not share congestion control across multiple connections. </ins> HTTP/2 (HTTP2) introduced a binary framing and multiplexing layer to improve latency without modifying the transport layer.  However, same packet as the QUIC CONNECTION_CLOSE frame improves the chances of the frame being received by clients. <ins> If there are open streams that have not been explicitly closed, they are implicitly closed when the connection is closed; see Section 10.2 of QUIC-TRANSPORT. </ins> 5.4. For various reasons, the QUIC transport could indicate to the


Indicates that x can be any length from A to B; A can be omitted to indicate a minimum of zero bits and B can be omitted to <del> indicate no set upper limit; values in this format always end on an byte boundary </del>  Indicates that x, with a length described by L, has a fixed value of C Indicates that x can be any length from A to B; A can be omitted to indicate a minimum of zero bits and B can be omitted to <del> indicate no set upper limit; values in this format always end on an byte boundary </del>  Indicates that x has a fixed value of C with the length described by L, which can use any of the three length forms above

Draft 34 changed notation from "octet" to "byte" in a few places, but forgot to change the article in two places.
Thanks, NAME

Indicates that x can be any length from A to B; A can be omitted to indicate a minimum of zero bits and B can be omitted to  <ins> indicate no set upper limit; values in this format always end on a byte boundary </ins> Indicates that x, with a length described by L, has a fixed value of C Indicates that x can be any length from A to B; A can be omitted to indicate a minimum of zero bits and B can be omitted to  <ins> indicate no set upper limit; values in this format always end on a byte boundary </ins> Indicates that x has a fixed value of C with the length described by L, which can use any of the three length forms above


An HTTP message (request or response) consists of: <del> the header field section, sent as a single HEADERS frame (see frame-headers), </del>  optionally, the content, if present, sent as a series of DATA frames (see frame-data), and <del> optionally, the trailer field section, if present, sent as a single HEADERS frame. </del>  <del> Header and trailer field sections are described in Sections 6.3 and 6.5 of SEMANTICS; the content is described in Section 6.4 of SEMANTICS. </del>  Receipt of an invalid sequence of frames MUST be treated as a connection error of type H3_FRAME_UNEXPECTED; see errors.  In sections.  Endpoints MUST treat a request or response that contains undefined or invalid pseudo-header fields as malformed (malformed). <del> All pseudo-header fields MUST appear in the header field section before regular header fields.  Any request or response that contains a pseudo-header field that appears in a header field section after a regular header field MUST be treated as malformed (malformed). </del>  The following pseudo-header fields are defined for requests: 7.2.5. The PUSH_PROMISE frame (type=0x5) is used to carry a promised request <del> header field section from server to client on a request stream, as in </del>  HTTP/2. The payload consists of: A large field section (request-response) can cause an implementation to commit a large amount of state.  Header fields that are critical <del> for routing can appear toward the end of a header field section, which prevents streaming of the header field section to its ultimate destination.  This ordering and other reasons, such as ensuring cache correctness, mean that an endpoint likely needs to buffer the entire header field section.  Since there is no hard limit to the size of a field section, some endpoints could be forced to commit a large amount of available memory for header fields. </del>  An endpoint can use the SETTINGS_MAX_FIELD_SECTION_SIZE (header-size- constraints) setting to advise peers of limits that might apply on data.  Compression MUST NOT be used if the source of data cannot be reliably determined. <del> Further considerations regarding the compression of fields sections </del>  are described in QPACK. 10.7. An ordered collection of HTTP field lines associated with an HTTP message.  A field section can contain multiple field lines with the same name.  It can also contain duplicate field lines.  An <del> HTTP message can include both header field and trailer field sections. </del>  An instruction that represents a field line, possibly by reference to the dynamic and static tables. 2.1. <del> An encoder converts a header or trailer field section into a series of representations by emitting either an indexed or a literal </del>  representation for each field line in the list; see field-line- representations.  Indexed representations achieve high compression by replacing the literal name and possibly the value with an index to

HTTP Semantics refers to the field sections used at particular locations using terms "header section" and "trailer section." However, the HTTP/3 draft sometimes calls them "header field section" and "trailer field section." This PR addresses the inconsistency. It also fixes one instance "fields section."
NAME Of course I did (not). Done in 18c0242.
Have you checked to make sure QPACK matches as well?

An HTTP message (request or response) consists of:  <ins> the header section, sent as a single HEADERS frame (see frame- headers), </ins> optionally, the content, if present, sent as a series of DATA frames (see frame-data), and  <ins> optionally, the trailer section, if present, sent as a single HEADERS frame. </ins>  <ins> Header and trailer sections are described in Sections 6.3 and 6.5 of SEMANTICS; the content is described in Section 6.4 of SEMANTICS. </ins> Receipt of an invalid sequence of frames MUST be treated as a connection error of type H3_FRAME_UNEXPECTED; see errors.  In sections.  Endpoints MUST treat a request or response that contains undefined or invalid pseudo-header fields as malformed (malformed).  <ins> All pseudo-header fields MUST appear in the header section before regular header fields.  Any request or response that contains a pseudo-header field that appears in a header section after a regular header field MUST be treated as malformed (malformed). </ins> The following pseudo-header fields are defined for requests: 7.2.5. The PUSH_PROMISE frame (type=0x5) is used to carry a promised request  <ins> header section from server to client on a request stream, as in </ins> HTTP/2. The payload consists of: A large field section (request-response) can cause an implementation to commit a large amount of state.  Header fields that are critical  <ins> for routing can appear toward the end of a header section, which prevents streaming of the header section to its ultimate destination. This ordering and other reasons, such as ensuring cache correctness, mean that an endpoint likely needs to buffer the entire header section.  Since there is no hard limit to the size of a field section, some endpoints could be forced to commit a large amount of available memory for header fields. </ins> An endpoint can use the SETTINGS_MAX_FIELD_SECTION_SIZE (header-size- constraints) setting to advise peers of limits that might apply on data.  Compression MUST NOT be used if the source of data cannot be reliably determined.  <ins> Further considerations regarding the compression of field sections </ins> are described in QPACK. 10.7. An ordered collection of HTTP field lines associated with an HTTP message.  A field section can contain multiple field lines with the same name.  It can also contain duplicate field lines.  An  <ins> HTTP message can include both header and trailer sections. </ins> An instruction that represents a field line, possibly by reference to the dynamic and static tables. 2.1.  <ins> An encoder converts a header or trailer section into a series of representations by emitting either an indexed or a literal </ins> representation for each field line in the list; see field-line- representations.  Indexed representations achieve high compression by replacing the literal name and possibly the value with an index to


RTT samples for the network path are recorded in latest_rtt; see latest-rtt.  On the first RTT sample after initialization, the estimator is reset using that sample.  This ensures that the <del> estimator retains no history of past samples. </del>  On the first RTT sample after initialization, smoothed_rtt and rttvar are set as follows: only packets being sent, but this document does not describe a mechanism for doing so.  The algorithm in this document specifies and uses the controller's congestion window in bytes.

From the transport draft's connection migration section.
Section 9.4 in Transport(URL) does a nice job of explaining the RTT and congestion control implications of migration, but given one might reasonably expect some or all of that text to exist in recovery, I think it makes sense to reference it more. In particular, "Packets sent on the old path MUST NOT contribute to congestion control or RTT estimation for the new path." is a useful sentence.

RTT samples for the network path are recorded in latest_rtt; see latest-rtt.  On the first RTT sample after initialization, the estimator is reset using that sample.  This ensures that the  <ins> estimator retains no history of past samples.  Packets sent on other paths do not contribute RTT samples to the current path, as described in Section 9.4 of QUIC-TRANSPORT. </ins> On the first RTT sample after initialization, smoothed_rtt and rttvar are set as follows: only packets being sent, but this document does not describe a mechanism for doing so. <ins> The congestion controller is per path, so packets sent on other paths do not alter the current path's congestion controller, as described in Section 9.4 of QUIC-TRANSPORT. </ins> The algorithm in this document specifies and uses the controller's congestion window in bytes.


Because the setting has no defined meaning, the value of the setting can be any value the implementation selects. <del> Setting identifiers which were used in HTTP/2 where there is no </del>  corresponding HTTP/3 setting have also been reserved (iana-settings). <del> These settings MUST NOT be sent, and their receipt MUST be treated as a connection error of type H3_SETTINGS_ERROR. </del>  Additional settings can be defined by extensions to HTTP/3; see extensions for more details.

Specifically those defined in RFC 7540.
URL says: The table of defined HTTP/3 settings is in URL The diverges a little bit from everything that is stated in RFC 7540. is stated as reserved in IANA but no mention of it in RFC 7540. Therefore it is ambiguous if an HTTP/3 implementation should reject this Type value. The range is reserved for HTTP/2 experimental use. Its not clear if I should reject those too. IANA also includes some extension settings: (RFC 8441), 0x10 (MS-HTTP2E). I might expect to be reused by some extension that defines Websocket over H3. seems like something that is not reusable? And finally, we have Extensible Priorities that defines SETTINGSDEPRECATEHTTP2_PRIORITIES and wants to claim . I don't expect any need to also define that in HTTP/3 settings, unless the purpose is to prohibit it. In summary, I don't think there is a huge problem. Maybe we can editorialize our way out of the ambiguity. However, I'd really like to avoid H/3 connections instantly failing due to implementations disagreeing about this rejection requirement.
I overlooked that NAME already made the point about in .
The intent is to reserve things that are defined in 7540; things reserved by other extensions might later be defined for HTTP/3, so there shouldn't be any assumptions. Let's make that requirement crisper to apply specifically to those values explicitly reserved.
WfM
I wonder if we should ask IANA if they can tell how it came to be that 0x0 was marked as reserved with 7540 as the reference even though we are failing to see what part of 7540 should be effectuating that.

Because the setting has no defined meaning, the value of the setting can be any value the implementation selects.  <ins> Setting identifiers which were defined in HTTP2 where there is no </ins> corresponding HTTP/3 setting have also been reserved (iana-settings).  <ins> These reserved settings MUST NOT be sent, and their receipt MUST be treated as a connection error of type H3_SETTINGS_ERROR. </ins> Additional settings can be defined by extensions to HTTP/3; see extensions for more details.


*Note:* This registry will not exist until SEMANTICS is approved. *RFC Editor*, please remove this note prior to publication. <del> As in previous versions of HTTP, field names are strings containing a subset of ASCII characters that are compared in a case-insensitive fashion.  Properties of HTTP field names and values are discussed in more detail in Section 5.1 of SEMANTICS.  As in HTTP/2, characters in </del>  field names MUST be converted to lowercase prior to their encoding. A request or response containing uppercase characters in field names MUST be treated as malformed (malformed). 4.1.1.2. <del> HTTP/3 uses QPACK field compression as described in QPACK, a variation of HPACK that allows the flexibility to avoid compression- induced head-of-line blocking.  See that document for additional details. </del>  To allow for better compression efficiency, the "Cookie" field (RFC6265) MAY be split into separate field lines, each with one or permit these streams to open, an HTTP/3 server SHOULD configure non- zero minimum values for the number of permitted streams and the initial stream flow control window.  So as to not unnecessarily limit <del> parallelism, at least 100 requests SHOULD be permitted at a time. </del>  HTTP/3 does not use server-initiated bidirectional streams, though an extension could define a use for these streams.  Clients MUST treat

NAME said
NAME said
Honestly, this whole sentence is a bit awkward. I'll improve that.
NAME said
I have to say, this is a little odd. HTTP requires case insensitive comparison, but by calling it out here, the juxtaposition is weird. As we force lowercase, we could just strike: "that are compared in a case-insensitive fashion"
The first is a statement of fact about what SEMANTICS requires. However, I agree that we reduce confusion and lose nothing by making the statement less explicit. Interested parties can read SEMANTICS.
Yes, the proposed text addresses my comments. Thanks for the updates.

*Note:* This registry will not exist until SEMANTICS is approved. *RFC Editor*, please remove this note prior to publication.  <ins> Field names are strings containing a subset of ASCII characters. Properties of HTTP field names and values are discussed in more detail in Section 5.1 of SEMANTICS.  As in HTTP/2, characters in </ins> field names MUST be converted to lowercase prior to their encoding. A request or response containing uppercase characters in field names MUST be treated as malformed (malformed). 4.1.1.2.  <ins> QPACK describes a variation of HPACK that gives an encoder some control over how much head-of-line blocking can be caused by compression.  This allows an encoder to balance compression efficiency with latency.  HTTP/3 uses QPACK to compress header and trailer sections, including the pseudo-header fields present in the header section. </ins> To allow for better compression efficiency, the "Cookie" field (RFC6265) MAY be split into separate field lines, each with one or permit these streams to open, an HTTP/3 server SHOULD configure non- zero minimum values for the number of permitted streams and the initial stream flow control window.  So as to not unnecessarily limit  <ins> parallelism, at least 100 request streams SHOULD be permitted at a time. </ins> HTTP/3 does not use server-initiated bidirectional streams, though an extension could define a use for these streams.  Clients MUST treat


deadlocked if the decoder withholds flow control credit until the instruction is completely received. <del> To avoid these deadlocks, an encoder SHOULD avoid writing an instruction unless sufficient stream and connection flow control credit is available for the entire instruction. </del>  2.1.4. field name might occur for shorter values more quickly or with higher probability than for longer values.  7.1.3. Implementations can also choose to protect sensitive fields by not table are registered in the "HTTP/3 Settings" registry established in HTTP3.  8.2. This document specifies two stream types.  The entries in the

NAME said
I think we can change to SHOULD NOT. I'd rather not be so prescriptive here, since a QPACK implementation might well cut this corner and ignore flow control constraints and rely on higher levels of the stack to ensure the necessary flow control is available? I guess I could be convinced otherwise.
NAME
NAME said
Even though newlines are not really allowed (unescaped) in field values, we can add a note to this effect.
NAME said
Yes, that's why they're not there.
Propose to close with no action then? Or is there a way to reformat the table to include the longer names?
I see a couple options in addition to "close with no change", namely to add a note below the table that the names are abbreviated, or to write out the IANA directives in prose without a table at all. I don't have a particular preference among those three options, though.
We need to come to a decision on this. Since this is from an IESG COMMENT (and not a DISCUSS), the editors can IMO go ahead with their preferred resolution.
NAME said
I agree it's not worth mitigating technically. I question whether it's worth documenting, personally, but it does no harm.
Maybe just a sentence that this mitigation has limits when traversing multiple intermediaries?
That seems like it would strike a reasonable balance.
NAME said
This table appears before the general discussion of indexing. One thought is to add something along the top of the table, like this: ?
Your proposal does improve the clarity of the figure, but I am hoping for more. While it is true that the dedicated sections that discuss indexing appear later in the document, the introductory text alongside the figure uses language such as "smallest absolute index", increases the draining index", and "with an absolute index lower than the draining index" that imply a numerical ordering and directionality of the indices. Interpreting the figure would be easier with the direction of that ordering stated explicitly, as might be done via "Newer Entries (larger index)"/etc..
We need to come to a decision on this. Since this is from an IESG COMMENT (and not a DISCUSS), the editors can IMO go ahead with their preferred resolution.

deadlocked if the decoder withholds flow control credit until the instruction is completely received.  <ins> To avoid these deadlocks, an encoder SHOULD NOT write an instruction unless sufficient stream and connection flow control credit is available for the entire instruction. </ins> 2.1.4. field name might occur for shorter values more quickly or with higher probability than for longer values. <ins> This mitigation is most effective between two endpoints.  If messages are re-encoded by an intermediary without knowledge of which entity constructed a given message, the intermediary could inadvertently merge compression contexts that the original encoder had specifically kept separate. </ins> 7.1.3. Implementations can also choose to protect sensitive fields by not table are registered in the "HTTP/3 Settings" registry established in HTTP3. <ins> For fomatting reasons, the setting names here are abbreviated by removing the 'SETTING_' prefix. </ins> 8.2. This document specifies two stream types.  The entries in the


processed immediately.  Otherwise, the stream on which the field section was received becomes blocked. <del> To bound the memory requirements of the decoder for blocked streams, encoded field section data SHOULD remain in the stream's flow control window while the stream is blocked.  A stream becomes unblocked when the Insert Count becomes greater than or equal to the Required Insert Count for all encoded field sections the decoder has started reading from the stream. </del>  When processing encoded field sections, the decoder expects the Required Insert Count to equal the lowest possible value for the

NAME said
One could imagine an implementation using a small buffer to read the beginning of the stream. If the whole field section happens to fit into it, so be it. A MUST would probably mean that a conforming implementation had to unread the field section.
We can probably just use "can" here. From an interoperability standpoint, there is no value to recommending any particular value.
Does SHOULD -> can mean this is a design change?
Yes, so if you're advocating doing that then I'll mark this as design.
The SHOULD is there to guard against memory exhaustion attacks. Streams "parking" is a QPACK design feature. The SHOULD should stay.
The plan is to leave the SHOULD, but add more editorial text in 2.2.1 explaining why it's a good idea.

processed immediately.  Otherwise, the stream on which the field section was received becomes blocked.  <ins> While blocked, encoded field section data SHOULD remain in the blocked stream's flow control window.  This data is unusable until the stream becomes unblocked, and releasing the flow control prematurely makes the decoder vulnerable to memory exhaustion attacks.  A stream becomes unblocked when the Insert Count becomes unblocked when the Insert Count becomes greater than or equal to the Required Insert Count for all encoded field sections the decoder has started reading from the stream. </ins> When processing encoded field sections, the decoder expects the Required Insert Count to equal the lowest possible value for the


A QUIC stream provides reliable in-order delivery of bytes, but makes no guarantees about order of delivery with regard to bytes on other <del> streams.  On the wire, the stream data containing HTTP frames is carried by QUIC STREAM frames, but this framing is invisible to the HTTP framing layer.  The transport layer buffers and orders received QUIC STREAM frames, exposing the data contained within as a reliable byte stream to the application.  Although QUIC permits out-of-order delivery within a stream, HTTP/3 does not make use of this feature. </del>  QUIC streams can be either unidirectional, carrying data only from initiator to receiver, or bidirectional.  Streams can be initiated by

I'm okay with the current text, but this talks more squarely about "version 1" and the abstraction, with the framing just being an aside. And technically, QUIC doesn't order the STREAM frames, it assembles the stream data in order, so this is more precise.
NAME said
(as an individual) clarifying that all frames defined in draft-ietf-quic-http3 are sent in QUIC STREAM frames is probably useful. This is couched in the requirement that these H3 frames explicitly depend on reliable and in-order delivery. It might be worth checking we make that clear in the spec. However, the current requirements are not invariant, we don't want to prohibit H3 extensions from utilizing transport extensions like DATAGRAM, partial reliability, or some future STREAM-frame replacement that might emerge.
The draft currently says: guarantees about order of delivery with regard to bytes on other streams. On the wire, data is framed into QUIC STREAM frames, but this framing is invisible to the HTTP framing layer. The transport layer buffers and orders received QUIC STREAM frames, exposing the data contained within as a reliable byte stream to the application. Although QUIC permits out-of-order delivery within a stream, HTTP/3 does not make use of this feature. This seems sufficient to me, though I think there's another open issue about the exact wording of some of this.
The application data abstraction that QUIC offers right now is streams, which is what HTTP/3 uses; the text that NAME pointed to makes that clear. We could change how data is sent in QUIC from STREAM frames to something entirely different, and that should not matter to HTTP/3 as long as the abstraction is the same: reliable, in-order, byte-stream. I'm not worried about this mapping becoming an effective invariant for HTTP/3, since (i) changing this contract (say, for datagram webtransport) requires negotiating that change at both HTTP and QUIC levels; and (ii) if we don't deploy extensions that use other mappings between HTTP data and QUIC frames, I don't think saying that we allow other mappings in the future does much.
It's also worth noting that HTTP/3 as currently defined requires exactly QUIC version 1. Permitting additional QUIC versions will require an update or a follow-on spec which can adapt to any changed abstractions at the same time.
I guess my point is that the text describes what QUIC v1 without extensions provides, not what HTTP/3 on v1 requires. When there is only one option, there is only one natural solution. The reason I suggested to point this out is to allow future HTTP/3 an ability to iterate on this requirement, which could be done in a document that describes a change to the requirement of the frame(s) defined in this spec. That might help to make people aware of when they need to negotiate the extension. To put it another way. If QUIC v1 offered unreliable and reliable streams. We would likely say that all H3 frames must be delivered on the reliable stream and explain why.
Jana convinced me that the risk of ossification is low (thanks for talking through it!). Lucas may be on to something, though, in terms of how we describe what we use and what we need, but that could likely be done in the other issue that Mike noted might exist. I would be okay if we closed this one with no change, but it's not clear that we have fully resolved yet on the latter topic.
Could folks please come to a decision on whether this is "close with no action"?
I can live with no action.
reopening to run it through a call
Closing this now that the IESG have approved the document and it's with the RFC editor.
Yup, this is better.

A QUIC stream provides reliable in-order delivery of bytes, but makes no guarantees about order of delivery with regard to bytes on other  <ins> streams.  In version 1 of QUIC, the stream data containing HTTP frames is carried by QUIC STREAM frames, but this framing is invisible to the HTTP framing layer.  The transport layer buffers and orders received stream data, exposing a reliable byte stream to the application.  Although QUIC permits out-of-order delivery within a stream, HTTP/3 does not make use of this feature. </ins> QUIC streams can be either unidirectional, carrying data only from initiator to receiver, or bidirectional.  Streams can be initiated by


When a sender receives credit after being blocked, it might be able to send a large amount of data in response, resulting in short-term <del> congestion; see Section 7.7 in QUIC-RECOVERY for a discussion of how </del>  a sender can avoid this congestion. 4.3. datagram size are more likely to be dropped by the network.  Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion <del> control reaction; see Section 3, Bullet 7 of DPLPMTUD.  However, PMTU probes consume congestion window, which could delay subsequent </del>  transmission by an application. 14.4.1. 21.1.1. The QUIC handshake incorporates the TLS 1.3 handshake and inherits <del> the cryptographic properties described in Appendix E.1 of TLS13. Many of the security properties of QUIC depend on the TLS handshake </del>  providing these properties.  Any attack on the TLS handshake could affect QUIC. registrations in this registry are assigned using the Specification Required policy (RFC8126), except for values between 0x00 and 0x3f (in hexadecimal; inclusive), which are assigned using Standards <del> Action or IESG Approval as defined in Section 4.9 and 4.10 of </del>  RFC8126. In addition to the fields in iana-provisional, permanent policies.  Permanent registrations in this registry are assigned using the Specification Required policy (RFC8126), except for values between 0x00 and 0x3f (in hexadecimal; inclusive), which are assigned <del> using Standards Action or IESG Approval as defined in Section 4.9 and 4.10 of RFC8126. </del>  In addition to the fields in iana-provisional, permanent registrations in this registry MUST include the following fields:

to make RFC Editor diffs smaller
These are manual; if only there were a tool... Diffs in the are all very small, and in each case reflects correction of an existing error or slight adjustment to accommodate limitations in XML (in one case); happy to suppy (CI is broken because of URL).
I just uploaded this to a branch on this repository so that a diff is generated in CI (assuming that I have a little more luck in getting a build to stick). The changes should be visible at URL if CI ever passes. Which of course it has not at this point...
Seems to be working occasionally; I fixed a lint problem, and diffs are now at URL
NAME I'd strongly prefer to keep this PR focused on behind-the-scenes tidying, rather than making an editorial wording choice. Beyond keeping the PR focused, doing this piecemeal is going to miss a large number of instances of "see..." because the changes represented here are only where a specific section is called out; you'd do much better to adjust that language consistently after this PR is applied (when you can do a search for and it should consistently show all instances, whether or not there's a section being referenced). If that's sensible to everyone, I think this is ready; tell me if I missed one of the comments.
NAME Fair enough. This LGTM.
Here are the diffs, since tools is failing so badly (I plan to work around that, but that will take some time). URL I've spotted one problem there already, but it does look good so far.
NAME and NAME I have learned something new about kramdown-rfc2629. Cheers.
NAME
NAME and NAME should approveThanks for doing this, recovery LGTM

When a sender receives credit after being blocked, it might be able to send a large amount of data in response, resulting in short-term  <ins> congestion; see Section 7.7 of QUIC-RECOVERY for a discussion of how </ins> a sender can avoid this congestion. 4.3. datagram size are more likely to be dropped by the network.  Loss of a QUIC packet that is carried in a PMTU probe is therefore not a reliable indication of congestion and SHOULD NOT trigger a congestion  <ins> control reaction; see Bullet 7 in Section 3 of DPLPMTUD.  However, PMTU probes consume congestion window, which could delay subsequent </ins> transmission by an application. 14.4.1. 21.1.1. The QUIC handshake incorporates the TLS 1.3 handshake and inherits  <ins> the cryptographic properties described in Section E.1 of TLS13.  Many of the security properties of QUIC depend on the TLS handshake </ins> providing these properties.  Any attack on the TLS handshake could affect QUIC. registrations in this registry are assigned using the Specification Required policy (RFC8126), except for values between 0x00 and 0x3f (in hexadecimal; inclusive), which are assigned using Standards  <ins> Action or IESG Approval as defined in Sections 4.9 and 4.10 of </ins> RFC8126. In addition to the fields in iana-provisional, permanent policies.  Permanent registrations in this registry are assigned using the Specification Required policy (RFC8126), except for values between 0x00 and 0x3f (in hexadecimal; inclusive), which are assigned  <ins> using Standards Action or IESG Approval as defined in Sections 4.9 and 4.10 of RFC8126. </ins> In addition to the fields in iana-provisional, permanent registrations in this registry MUST include the following fields:


ClientHello message in their first Initial packet. The TLS implementation does not need to ensure that the ClientHello <del> is large enough to meet the requirements for QUIC packets.  QUIC PADDING frames are added to increase the size of the packet as necessary; see Section 14.1 of QUIC-TRANSPORT. </del>  4.4.

Cleanup the language here a little.
This text could be better: Maybe instead:
Does anyone want to prepare a PR? Otherwise, this will get dropped I guess.
I didn't want to clutter our list of stuff with post-IESG PRs. I'll copy the above text once HTTP is done (real soon now). We're going to have to be careful that these little tweaks don't pile up.
I think this should be good to go now?

ClientHello message in their first Initial packet. The TLS implementation does not need to ensure that the ClientHello  <ins> is large enough to meet QUIC's requirements for datagrams that carry Initial packets; see Section 14.1 of QUIC-TRANSPORT.  QUIC implementations use PADDING frames or packet coalescing to ensure that datagrams are large enough. </ins> 4.4.


An implementation has to set a limit for the values it accepts for integers, as well as for the encoded length; see prefixed-integers. In the same way, it has to set a limit to the length it accepts for <del> string literals; see string-literals. </del>  8.

Not sure whether this is design or not; it adds normative requirements, but they were already implicit.
Let's label it design.
NAME said
Section 3.2.2 mentions that it is an error to attempt to insert an entry larger than the table size: I can't actually find a place where the document says that if you fail to decode an instruction or reference (for any reason, which would include exceeding implementation limits) that it's an error. I think we might need one.
Actually, section 6 says: The decoder failed to interpret an encoded field section and is not able to continue decoding that field section. QPACKENCODERSTREAMERROR (0x201): The decoder failed to interpret an encoder instruction received on the encoder stream. QPACKDECODERSTREAMERROR (0x202): The encoder failed to interpret a decoder instruction received on the decoder stream. So "failing to interpret" anything results in an error. I think this includes being unable to decode an integer or string because of implementation limits. Is this sufficient or should we add something a bit more explicit?
If section 3.2.2 already imposes a limit on the length of an entry, then it would be good to referenced that text from section 7.4. E.g. section 7.4 states: In the same way, it has to set a limit to the length it accepts for string literals; see Section 4.1.2. But I suspect that really the only limit that is needed here is the one in 3.2.2? I.e. it seems reasonable that a receiver should accept any string up to the maximum table size? But my other point is that it suggests that a receiver can arbitrarily choose to set a limit on the size of integers that it receives, but section 4.1.1 states: QPACK implementations MUST be able to decode integers up to and including 62 bits long. So, I guess that I'm really suggesting that this paragraph (in section 7.4): An implementation has to set a limit for the values it accepts for integers, as well as for the encoded length; see Section 4.1.1. In the same way, it has to set a limit to the length it accepts for string literals; see Section 4.1.2. is reworded to say something along the lines of: Receivers MUST accept integers up to 62 bits long section 4.1.1, but MAY choose to not handle larger integers, in which case they return QPACKDECOMPRESSIONFAILED. Receivers MUST accept any strings up to maximum table length -32, or return QPACKDECOMPRESSIONFAILED. It wasn't clear to me whether integers bigger than 62 bits are ever likely in practice, I presume not ...
A decoder that actually counts insertions (instead of using modulo arithmetic) will likely fail when the integer value it uses overflows. Of course, one does not have to use or for the count. To avoid an overflow, there are math libraries that support arbitrarily large numbers.
The text is really attempting to say that an implementation MUST NOT continue to process to infinity; bounds must exist for basic sanity. What those bounds will be is implementation-dependent. Saying that they're limited to the table size is only true on the encoder stream; request streams can have string literals greater than the table size (consider the degenerate case of zero). HTTP limits could be pushed down to QPACK such that the library will refuse to decode a larger string than the implementation would accept; I don't think that's necessarily required though.
I don't think that using arbitrarily sized integer libraries is the answer here due to the performance overheads of such libraries. My concerns are two fold: (1) It is unclear what arbitrary limit receivers should apply. E.g., is 255 bytes enough for a string? Is a 64 bit signed integer enough for an integer? (2) Senders probably won't really know that the reason the stream has failed is because they are hitting some arbitrary limit in the receiver, and even if they did then I'm not sure there is anything that they can do about it. Hence, another suggestion is to specifying minimum expected bounds for these values? Or if these bounds are effectively provided by the HTTP spec, perhaps the appropriate section in that spec. could be referenced.
Editors, could we come to a conclusion here?
There is already a requirement that implementations be able to decode 62 bit integers. Anything larger is really unnecessary -- we intentionally encode the "Required Insert Count" on the wire in a way that bounds its size to be much smaller practically. The requirement stems from the need to decode QUIC stream IDs. I think NAME comment about bignums is about what an implementation might do if it overflowed its internal representation decoding the Required Insert Count. This is not a practical concern, and can be completely worked around with a "clever" implementation that is worried about more than 2^64 table insertions. HTTP also provides a setting to inform the peer of a maximum size of a field section (MAXFIELDSECTION_SIZE -- see HTTP/3 section 4.1.1.3), which is also a practical upper bound for any single QPACK string for HTTP/3. Perhaps the QPACK doc could provide this hint? I'll draft a PR to this effect.
FWIW, exceeding 2^60 insertions would be a tall order given data limits in QUIC; a 64-bit integer is definitely enough space for any size or length field. Implementations can use smaller values, probably reliably. There is some need for care in those cases, but I don't see the spec as bearing any responsibility for that. NAME remember that MAXFIELDSECTION_SIZE is advisory, so I wouldn't go so far as to say "practical".
So, do we have a proposal on this one?
Every (sane) implementation has a limit; what's advisory is informing your peer about your limit before they hit it, or enforcing downstream limits to short-circuit errors. Any implementation could absolutely tell the decoder not to bother decoding anything larger than what they will process and just return an error.
I'm trying to address Robert's second point: The mechanism to address that in HTTP/3 is with the advisory setting, though it's slightly different in that the setting applies to the entire field section, and it's conceivable an implementation could have another, smaller limit for any individual field name or value. It's easier to pretend that isn't the case. For these reasons, I stumbled a bit on the exact wording of the text last week and ran out of time because of other commitments. I'm thinking something along the lines of "an implementation really ought to be able to decode a string as long as their advisory setting" and/or "if an implementation has a limit on the maximum size of string it can decode, it would be really nice to inform the peer about it with the advisory setting". Is that reasonable? Or am I barking up the completely wrong tree?
If HTTP/3 already sets practical limits on what the QPACK needs to accept then it is fine to say that. Or to put this another way, the HTTP/3 implementations presumably are setting limits (or perhaps they are just relying on language/decoder limits). How are they deciding what those limits should be? How can they be sure that they will interoperate with all senders? I'm not an HTTP expert, so perhaps I'm missing something obvious here.
HTTP (not HTTP/3) has historically not communicated those limits, which are implementation-dependent. You just find out if you hit them -- status codes 413 (Content Too Large) and 414 (URI Too Long) cover these, but some implementations will also send a 400 out of discretion. HTTP/2 introduced a mechanism to inform the peer what your limit is (SETTINGSMAXHEADERLISTSIZE), which lets the failure occur further downstream and saves everyone effort -- a client or downstream proxy can fail a too-large request on behalf of the server before actually transferring it, rather than discovering the limit only after the server rejects it. It's optional, though; some endpoints prefer not to disclose their limits to avoid giving information to attackers, and some endpoints don't know how big the message is going to be when it starts processing it. HTTP/3 maintains parity with that (SETTINGSMAXFIELDSECTIONSIZE) and the feature is similarly optional. Regardless of whether they're communicated, though, sane implementations have a limit. In at least some implementations, this limit is configurable, so it can be increased in situations where you have mostly-trusted clients and a known usecase for very large headers or URIs. That's not a protocol element; I don't think we can reasonably say much more than that the QPACK library SHOULD/MUST be able to process the largest individual header or header section that its HTTP implementation can be configured to accept.
Mike, thanks for the additional context. Stating something along the lines of the following would be fine with me: sane implementations have a limit (and what they do if that limit is reached), and the QPACK library SHOULD/MUST be able to process the largest individual header or header section that its HTTP implementation can be configured to accept.
Closing this now that the IESG have approved the document and it's with the RFC editor.

An implementation has to set a limit for the values it accepts for integers, as well as for the encoded length; see prefixed-integers. In the same way, it has to set a limit to the length it accepts for  <ins> string literals; see string-literals.  These limits SHOULD be large enough to process the largest individual field the HTTP implementation can be configured to accept. If an implementation encounters a value larger than it is able to decode, this MUST be treated as a stream error of type QPACK_DECOMPRESSION_FAILED if on a request stream, or a connection error of the appropriate type if on the encoder or decoder stream. </ins> 8.


H3_STREAM_CREATION_ERROR; see errors. Each Push ID MUST only be used once in a push stream header.  If a <del> push stream header includes a Push ID that was used in another push stream header, the client MUST treat this as a connection error of type H3_ID_ERROR; see errors. </del>  6.2.3.

Adds the all-important conditional.
For clients that have sent CANCEL_PUSH, they don't know if server's push stream will still arrive or not. They have to remember Push IDs forever in order to differentiate between cancelled push and completed push.
I would appreciate some quick discussion if this issue is important to address before I approve or not.
We could make this a MAY. The other formulation we've used is "MUST ... if the client detects", making the response mandatory if the condition is detected, but not specifying the required level of effort to detect it.
I don't know that this issue is critical to address, but I agree that with certain (reasonable) implementation strategies this particular MUST becomes unenforceable / unachievable.
+1 for "MUST if the client detects" if we're going to make a change.
I think "MUST if detects" is suitable here - it points at the core problem. Simply s/MUST/MAY doesn't help people appreciate that might not be able to detect the condition. I'd also suggest that "MUST if detects" is an editorial change.
NAME can you confirm if addresses your issue?
Looks good!
Thanks. In that case I believe we have addressed this issue with an editorial change. NAME please confirm if we can merge the related PR and incorporate the change in during the RFC editor process.
Yes, the change looks good. I could actually include it as an RFC-edtior note in my approval message.
An elegant solution :)

H3_STREAM_CREATION_ERROR; see errors. Each Push ID MUST only be used once in a push stream header.  If a  <ins> client detects that a push stream header includes a Push ID that was used in another push stream header, the client MUST treat this as a connection error of type H3_ID_ERROR; see errors. </ins> 6.2.3.


initial_max_stream_data_bidi_remote, or initial_max_streams_uni and initial_max_stream_data_uni.  A server MAY store and recover the previously sent values of the max_idle_timeout, max_udp_payload_size, and disable_active_migration parameters and reject 0-RTT if it selects smaller values.  Lowering

If the client has opened a stream in 0-RTT with , and the server increases to , does this apply to this stream as well, or only to streams opened after handshake completion? Consensus in Slack seems to be that the limit should apply to all streams. The text should be explicit about that.
Isn't that already clear enough? states:
NAME This is what the definition of the TP says: Arguably, the stream used in 0-RTT is not a "newly created" stream.
Yeah, let's just be really clear about this. Though NAME quotes the section that is most important, this has proven to be a mistake common enough to spend text on.

initial_max_stream_data_bidi_remote, or initial_max_streams_uni and initial_max_stream_data_uni. <ins> A server might provide larger initial stream flow control limits for streams than the remembered values that a client applies when sending 0-RTT.  Once the handshake completes, the client updates the flow control limits on all sending streams using the updated values of initial_max_stream_data_bidi_remote and initial_max_stream_data_uni. </ins> A server MAY store and recover the previously sent values of the max_idle_timeout, max_udp_payload_size, and disable_active_migration parameters and reject 0-RTT if it selects smaller values.  Lowering


its first cryptographic handshake message, which for TLS is the ClientHello.  Servers might need to parse the entire ClientHello (e.g., to access extensions such as Server Name Identification (SNI) <del> or Application Layer Protocol Negotiation (ALPN)) in order to decide </del>  whether to accept the new incoming QUIC connection.  If the ClientHello spans multiple Initial packets, such servers would need to buffer the first received fragments, which could consume excessive Endpoints use transport parameters to authenticate the negotiation of connection IDs during the handshake; see cid-auth. <del> Application Layer Protocol Negotiation (ALPN; see ALPN) allows </del>  clients to offer multiple application protocols during connection establishment.  The transport parameters that a client includes during the handshake apply to all application protocols that the validation of the server certificate as described above), and sending an HTTP/3 request message targeting the URI to the server over that secured connection.  Unless some other mechanism is used to select <del> HTTP/3, the token "h3" is used in the Application Layer Protocol </del>  Negotiation (ALPN; see RFC7301) extension during the TLS handshake. Connectivity problems (e.g., blocking UDP) can result in QUIC 11.1. This document creates a new registration for the identification of <del> HTTP/3 in the "Application Layer Protocol Negotiation (ALPN) Protocol </del>  IDs" registry established in RFC7301. The "h3" string identifies HTTP/3:

as well as other instances of the term. RFC 7301 does indeed hyphenate (and that's correct, since "application-layer" is being used as a single unit to describe "protocol").
URL says the registry is

its first cryptographic handshake message, which for TLS is the ClientHello.  Servers might need to parse the entire ClientHello (e.g., to access extensions such as Server Name Identification (SNI)  <ins> or Application-Layer Protocol Negotiation (ALPN)) in order to decide </ins> whether to accept the new incoming QUIC connection.  If the ClientHello spans multiple Initial packets, such servers would need to buffer the first received fragments, which could consume excessive Endpoints use transport parameters to authenticate the negotiation of connection IDs during the handshake; see cid-auth.  <ins> Application-Layer Protocol Negotiation (ALPN; see ALPN) allows </ins> clients to offer multiple application protocols during connection establishment.  The transport parameters that a client includes during the handshake apply to all application protocols that the validation of the server certificate as described above), and sending an HTTP/3 request message targeting the URI to the server over that secured connection.  Unless some other mechanism is used to select  <ins> HTTP/3, the token "h3" is used in the Application-Layer Protocol </ins> Negotiation (ALPN; see RFC7301) extension during the TLS handshake. Connectivity problems (e.g., blocking UDP) can result in QUIC 11.1. This document creates a new registration for the identification of  <ins> HTTP/3 in the "Application-Layer Protocol Negotiation (ALPN) Protocol </ins> IDs" registry established in RFC7301. The "h3" string identifies HTTP/3:


8.  8.1. This document specifies two settings.  The entries in the following

RFC-to-be 9114 (draft-ietf-quic-http) includes the following note to indicate that the registrations have a status of permanent and the Change Controller is the IETF. Should a similar statement be included in this document? From RFC-to-be 9114: The initial allocations in these registries created in this document are all assigned permanent status and list a change controller of the IETF and a contact of the HTTP working group (EMAIL). In addition, note that the padding in the Settings, Stream Types, and Error Codes differs from what appears in the IANA registry. IANA included the following note when they notified us that their actions for RFC-to-be 9114 were complete: NOTE: In the new registries, the padding has been adjusted for consistency from one registry to another and with URL We understand that there may be a request to change it. We have asked Mike (as editor of RFC-to-be 9114) to review, as the padding for the HTTP/3 registries is now inconsistent with the padding for the HTTP/2 registries. Please review and dicuss and let us know if any updates are needed.
Fixed in .
The QUIC registry policies, imported to HTTP/3, specify that a change controller and their contact information should be listed with each permanent registration. QPACK doesn't provide one, though almost certainly it should be the HTTP WG.

8. <ins> This document makes multiple registrations in the registries defined by HTTP3.  The allocations created by this document are all assigned permanent status and list a change controller of the IETF and a contact of the HTTP working group (ietf-http-wg@w3.org). </ins> 8.1. This document specifies two settings.  The entries in the following


(error-handling). Once a receiver advertises a stream limit using the MAX_STREAMS <del> frame, advertising a smaller limit has no effect.  A receiver MUST ignore any MAX_STREAMS frame that does not increase the stream limit. </del>  As with stream and connection flow control, this document leaves implementations to decide when and how many streams should be

Rather than saying who ignores MAX_STREAMS, we can just that it is ignored.
has the following requirement: frame, advertising a smaller limit has no effect. A receiver MUST ignore any MAXSTREAMS frame that does not increase the stream limit. I believe this should be: frame, advertising a smaller limit has no effect. A sender MUST ignore any MAXSTREAMS frame that does not increase the stream limit. This would be in line with the similar requirements for MAXSTREAMDATA and MAXDATA in : is not an error to advertise a smaller limit, but the smaller limit has no effect. [...] A sender MUST ignore any MAXSTREAMDATA or MAXDATA frames that do not increase flow control limits.
I believe the sentence was intended to read: "A receiver(of the frame) MUST ignore any MAX_STREAMS frame that does not increase the stream limit."
Using "receiver" in this context is confusing, maybe it could just be replaced by "endpoint": frame, advertising a smaller limit has no effect. An endpoint MUST ignore any MAX_STREAMS frame that does not increase the stream limit. Or just take the language from : ignored.
Yeah, this is the right fix.

(error-handling). Once a receiver advertises a stream limit using the MAX_STREAMS  <ins> frame, advertising a smaller limit has no effect.  MAX_STREAMS frames that do not increase the stream limit MUST be ignored. </ins> As with stream and connection flow control, this document leaves implementations to decide when and how many streams should be


STOP_SENDING requests that a peer cease transmission on a stream. A STOP_SENDING frame can be sent for streams in the Recv or Size <del> Known states; see stream-send-states.  Receiving a STOP_SENDING frame </del>  for a locally-initiated stream that has not yet been created MUST be treated as a connection error of type STREAM_STATE_ERROR.  An endpoint that receives a STOP_SENDING frame for a receive-only stream a peer of the maximum amount of data that can be sent on a stream. A MAX_STREAM_DATA frame can be sent for streams in the Recv state; <del> see stream-send-states.  Receiving a MAX_STREAM_DATA frame for a </del>  locally-initiated stream that has not yet been created MUST be treated as a connection error of type STREAM_STATE_ERROR.  An endpoint that receives a MAX_STREAM_DATA frame for a receive-only

Tommy points out that we accidentally cited the sending parts, but these are receive states.
Very editorial nit: The section has the following text: The states referenced here are in fact receive stream states, not send stream states. Should this be: The same goes for MAXSTREAM_DATA:

STOP_SENDING requests that a peer cease transmission on a stream. A STOP_SENDING frame can be sent for streams in the Recv or Size  <ins> Known states; see stream-recv-states.  Receiving a STOP_SENDING frame </ins> for a locally-initiated stream that has not yet been created MUST be treated as a connection error of type STREAM_STATE_ERROR.  An endpoint that receives a STOP_SENDING frame for a receive-only stream a peer of the maximum amount of data that can be sent on a stream. A MAX_STREAM_DATA frame can be sent for streams in the Recv state;  <ins> see stream-recv-states.  Receiving a MAX_STREAM_DATA frame for a </ins> locally-initiated stream that has not yet been created MUST be treated as a connection error of type STREAM_STATE_ERROR.  An endpoint that receives a MAX_STREAM_DATA frame for a receive-only


since the sender will still reduce its sending rate exponentially under persistent congestion (pto).  5. At a high level, an endpoint measures the time from when a packet was

Just in case you want to use this, I've rebased. I'll replay my suggestions too.
RFC 3390 states (and RFC 5681 has similar text): If the SYN or SYN/ACK is lost, the initial window used by a sender after a correctly transmitted SYN MUST be one segment consisting of MSS bytes. For safety reasons we should add similar text to reduce cwnd to the minimum congestion window when loss is observed/confirmed during the handshake.
NAME NAME I just spotted this deviation when reviewing a TCP issue.
Is that a fair comparison? SYN - SYN/ACK is the exchange of just two packets. A QUIC handshake will involve significantly more packets: at least 3 (ClientHello, ServerHello + Cert + SFIN, CFIN), in practice probably 4-5, depending on the size of the certificate. And even more when TLS client authentication is used.
I don't think we should change this, particularly at this point. As Marten said, there are typically multiple packets in a QUIC handshake exchange, so it's not clear to me what the best analogue would be? Also, Initial and Handshake keys can be discarded prior to ever processing an ACK, so there are cases one might not know whether the Initial or Handshake packets area lost. Also, I expect TCP SYN and SYN/ACKs are treated specially in many networks, so the odds of losing them is extra low in practice.
Let's decouple when to change anything (and if at all) from the issue discussion and its resolution. No congestion reaction to loss seems incorrect to me particularly if multiple packets are involved (which increases the probability). From point of view of network the loss of handshake packets should still be subject to a cc reaction otherwise under extreme congestion you could have collapse just due to new handshakes.
Loss does result in a reaction. My understanding is that lost packets are reported as lost, the congestion window is reduced, and a recovery period started, just like everywhere else. The TCP behaviour is analogous to detecting persistent congestion, which I suppose is the defense QUIC provides. That is consistent and seems reasonable enough to me. If that is acceptable, we could add a note explaining the difference from TCP. That is, QUIC does not treat loss of the first packets specially like TCP does, relying instead on the same loss detection and persistent congestion mechanisms that apply to all other packets; the only difference in handling is the retention of PTO during the handshake, which exists to address deadlocks caused by anti-amplification protections.
Yes, as NAME stated, detected losses trigger a reduction in the congestion window. Additionally, PTO has exponential backoff, even though the CWND does not collapse immediately. Adding a note about the differences from TCP seems sensible to me. Additionally, TCP collapses the congestion window and declares packets lost because that's how its mechanism to send a single (ie: RTO) packet works. QUIC can send a single packet without declaring packets lost or collapsing the congestion window.
As long as detected losses during handshake result in a reaction, we are good to go. Let's add clarifying text and close this. Thanks!

since the sender will still reduce its sending rate exponentially under persistent congestion (pto). <ins> 4.9. TCP treats the loss of SYN or SYN-ACK packet as persistent congestion and reduces the congestion window to one packet (RFC5681).  QUIC treats loss of a packet containing handshake data the same as other losses. </ins> 5. At a high level, an endpoint measures the time from when a packet was


A variable-length integer error code that indicates the reason for closing this connection.  A CONNECTION_CLOSE frame of type 0x1c uses codes from the space defined in transport-error-codes.  A <del> CONNECTION_CLOSE frame of type 0x1d uses codes from the application protocol error code space; see app-error-codes. </del>  A variable-length integer encoding the type of frame that triggered the error.  A value of 0 (equivalent to the mention of

This avoids the implication of a single error code space. Even if one is permissible, that is not necessary.
NAME originally posted in URL a comment highlighting that although HTTP/3 uses a single error code space for connection and stream errors, there is no requirement for other application protocol mappings to do the same. I found the text in URL to give me the wrong assumptions. This is the only mention of an error code space in the text that will make it into RFC. So I suggest in the offending paragraph we delete the 2 occurrences of "space" and just state that the frame contains a value, either defined in transport [ref] or application [ref]
"uses codes defined by the application protocol"?

A variable-length integer error code that indicates the reason for closing this connection.  A CONNECTION_CLOSE frame of type 0x1c uses codes from the space defined in transport-error-codes.  A  <ins> CONNECTION_CLOSE frame of type 0x1d uses codes defined by the application protocol; see app-error-codes. </ins> A variable-length integer encoding the type of frame that triggered the error.  A value of 0 (equivalent to the mention of


becoming idle.  Non-ack-eliciting packets are eventually acknowledged when the endpoint sends an ACK frame in response to other events.  In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack- eliciting packet either: for connections made by the endpoint and for other users of the network. <del> An endpoint that is only sending ACK frames will not receive acknowledgments from its peer unless those acknowledgments are included in packets with ack-eliciting frames.  An endpoint SHOULD send an ACK frame with other frames when there are new ack-eliciting packets to acknowledge.  When only non-ack-eliciting packets need to be acknowledged, an endpoint MAY wait until an ack-eliciting packet has been received to include an ACK frame with outgoing frames. A receiver MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments. </del> 13.2.2. A receiver determines how frequently to send acknowledgments in

There is a little connective tissue added here to connect to the ACK tracking thing.
NAME -- ptal when you get a chance
In the Loss Recovery Pseudocode, is initialized to 0: URL This can result in dividing by zero if one implements a Cubic congestion controller () that incorporates (as the ). Cubic specifies the , used in congestion avoidance, as: An endpoint can enter congestion avoidance without receiving any acks for any ack-eliciting packets (only non-ack eliciting packets). In such a scenario, would still be 0, due to the requirement from : Since is 0 when is calculated, the divide by 0 occurs. This could be addressed by initializing to instead of 0.
FWIW this was changed from back to 0 in URL
I feel the existing pseudocode is ok, because minrtt in the text and pseudocode is used for the purpose of rejecting potentially bad RTT samples, and is not a general purpose minrtt. URL For example, BBR uses a windowed min_rtt that's fairly different. This does bring up an edge case I hadn't thought much about, where no ack-eliciting packets are acknowledged, but a packet is declared lost. A compliant transport implementation shouldn't ACK only ACK-only packets, but a non-compliant one could.

This does bring up an edge case I hadn't thought much about, where no ack-eliciting packets are acknowledged, but a packet is declared lost. A compliant transport implementation shouldn't ACK only ACK-only packets, but a non-compliant one could. The situation we saw was under severe packet loss, the peer sending probe packets containing a PING and ACK for non ack eliciting packets (ACKs and PADDING). The ACK-eliciting packets we send are getting dropped, so eventually we declare an ACK-eliciting packet lost and enter Recovery. When the next ACK comes in for a packet sent after we entered Recovery, we enter Congestion Avoidance and experience the issue with .
I'm still a bit unclear. Under what circumstances would a compliant peer send an ACK that only acknowledges non ack-eliciting packets?
After a probe timeout. Would that be non-compliant?
In regards to the issue originally raised about minrtt, I still feel the minrtt is not general purpose, so the originally stated issue is not a problem in the context of QUIC recovery. Other discussion follows. First, you'd have to complete the handshake without an RTT sample, which seems unlikely, but possible, so let's assume that. A PTO would send an ack-eliciting packet, and when the ACK for that packet came back, you'd have an RTT sample. However, if the peer was sending ACK+PING for every other ACK+PADDING packet, then you're correct that the incoming ACK bundled with the PING would not create an RTT measurement, but would allow any previously sent ACK-eliciting packets to be declared as lost if the packet threshold was reached. In regards to "peer sending probe packets containing a PING and ACK for non ack eliciting packets (ACKs and PADDING)", if you're saying that the peer is sending those in response to every ACK+PADDING packet, that sounds non-compliant to me. In regards to whether it's ok to send ACK+PING in response to ACK+PADDING, I re-read "Sending ACK Frames"(URL) and it says: "An endpoint MUST NOT send a non-ack-eliciting packet in response to a non-ack-eliciting packet, even if there are packet gaps that precede the received packet." Are you sending PADDING+PING due to that prohibition? I'm a bit concerned that could cause an infinite or near-infinite loop under the wrong circumstance, which was exactly the issue the paragraph highlights. The last paragraph does specifically preclude sending ack-eliciting packets in response to every non-ack-eliciting packet: "A receiver MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments." It may make sense to move that final paragraph up, as it's a bit disconnected at the moment?
Agree that its not a problem within the context of QUIC recovery, I just wanted to call it out as an issue I experienced. If there wasn't much reason to initialize to 0 perhaps initializing to a value that is actually possible would make sense (and would prevent issues like the one I saw), but its not a big deal. Just to clarify, only the peer is sending PINGS in the scenario we saw (actually PADDING+PING+ACK) The peer is sending ack-eliciting packets (PADDING+PING+ACK) due to PTO timeouts, its not a case of upgrading non-ack-eliciting packets to ack-eliciting by throwing in a PING every time, more that the ACKs are getting included when the probes get sent. I did find this paragraph confusing until I read URL, I'm not sure moving it up would help without some additional rewording.
LG, one possible suggestion to a sentence I've been confused by before.

becoming idle.  Non-ack-eliciting packets are eventually acknowledged when the endpoint sends an ACK frame in response to other events. <ins> An endpoint that is only sending ACK frames will not receive acknowledgments from its peer unless those acknowledgments are included in packets with ack-eliciting frames.  An endpoint SHOULD send an ACK frame with other frames when there are new ack-eliciting packets to acknowledge.  When only non-ack-eliciting packets need to be acknowledged, an endpoint MAY choose not to send an ACK frame with outgoing frames until an ack-eliciting packet has been received. An endpoint that is only sending non-ack-eliciting packets might choose to occasionally add an ack-eliciting frame to those packets to ensure that it receives an acknowledgment; see ack-tracking.  In that case, an endpoint MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments. </ins> In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack- eliciting packet either: for connections made by the endpoint and for other users of the network.  13.2.2. A receiver determines how frequently to send acknowledgments in


The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and <del> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </del>  This document defines requirements on future QUIC versions, even where normative language is not used. Indicates that x is A bits long Indicates that x can be any length from A to B; A can be omitted <del> to indicate a minimum of zero bits and B can be omitted to </del>  indicate no set upper limit; values in this format always end on a byte boundary <del> Indicates that x, with a length described by L, has a fixed value of C </del>  <del> Indicates that x is repeated zero or more times (and that each instance is length L) </del>  This document uses network byte order (that is, big endian) values. Fields are placed starting from the high-order bits of each byte. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and <del> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </del>  Commonly used terms in the document are described below. Indicates that x is A bits long Indicates that x holds an integer value using the variable-length <del> encoding in </del>  Indicates that x can be any length from A to B; A can be omitted <del> to indicate a minimum of zero bits and B can be omitted to </del>  indicate no set upper limit; values in this format always end on a byte boundary <del> Indicates that x has a fixed value of C with the length described by L, which can use any of the three length forms above </del>  Indicates that x has a value in the range from C to D, inclusive, with the length described by L, as above <del> Indicates that x is optional (and has length of L) </del>  <del> Indicates that zero or more instances of x are present (and that each instance is length L) </del>  This document uses network byte order (that is, big endian) values. Fields are placed starting from the high-order bits of each byte. becoming idle.  Non-ack-eliciting packets are eventually acknowledged when the endpoint sends an ACK frame in response to other events.  In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack- eliciting packet either: for connections made by the endpoint and for other users of the network. <del> An endpoint that is only sending ACK frames will not receive acknowledgments from its peer unless those acknowledgments are included in packets with ack-eliciting frames.  An endpoint SHOULD send an ACK frame with other frames when there are new ack-eliciting packets to acknowledge.  When only non-ack-eliciting packets need to be acknowledged, an endpoint MAY wait until an ack-eliciting packet has been received to include an ACK frame with outgoing frames. A receiver MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments. </del> 13.2.2. A receiver determines how frequently to send acknowledgments in A variable-length integer error code that indicates the reason for closing this connection.  A CONNECTION_CLOSE frame of type 0x1c uses codes from the space defined in transport-error-codes.  A <del> CONNECTION_CLOSE frame of type 0x1d uses codes from the application protocol error code space; see app-error-codes. </del>  A variable-length integer encoding the type of frame that triggered the error.  A value of 0 (equivalent to the mention of The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and <del> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </del>  This document uses the terminology established in QUIC-TRANSPORT. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and <del> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </del>  This document uses the variable-length integer encoding from QUIC- TRANSPORT. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and <del> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </del>  Definitions of terms that are used in this document:

For those drafts that are in AUTH48.
This PR makes me happy.9000! Very cool!

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and  <ins> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </ins> This document defines requirements on future QUIC versions, even where normative language is not used. Indicates that x is A bits long Indicates that x can be any length from A to B; A can be omitted  <ins> to indicate a minimum of zero bits, and B can be omitted to </ins> indicate no set upper limit; values in this format always end on a byte boundary  <ins> Indicates that x has a fixed value of C; the length of x is described by L, which can use any of the length forms above </ins>  <ins> Indicates that x is repeated zero or more times and that each instance has a length of L </ins> This document uses network byte order (that is, big endian) values. Fields are placed starting from the high-order bits of each byte. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and  <ins> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </ins> Commonly used terms in the document are described below. Indicates that x is A bits long Indicates that x holds an integer value using the variable-length  <ins> encoding described in </ins> Indicates that x can be any length from A to B; A can be omitted  <ins> to indicate a minimum of zero bits, and B can be omitted to </ins> indicate no set upper limit; values in this format always end on a byte boundary  <ins> Indicates that x has a fixed value of C; the length of x is described by L, which can use any of the length forms above </ins> Indicates that x has a value in the range from C to D, inclusive, with the length described by L, as above  <ins> Indicates that x is optional and has a length of L </ins>  <ins> Indicates that x is repeated zero or more times and that each instance has a length of L </ins> This document uses network byte order (that is, big endian) values. Fields are placed starting from the high-order bits of each byte. becoming idle.  Non-ack-eliciting packets are eventually acknowledged when the endpoint sends an ACK frame in response to other events. <ins> An endpoint that is only sending ACK frames will not receive acknowledgments from its peer unless those acknowledgments are included in packets with ack-eliciting frames.  An endpoint SHOULD send an ACK frame with other frames when there are new ack-eliciting packets to acknowledge.  When only non-ack-eliciting packets need to be acknowledged, an endpoint MAY choose not to send an ACK frame with outgoing frames until an ack-eliciting packet has been received. An endpoint that is only sending non-ack-eliciting packets might choose to occasionally add an ack-eliciting frame to those packets to ensure that it receives an acknowledgment; see ack-tracking.  In that case, an endpoint MUST NOT send an ack-eliciting frame in all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgments. </ins> In order to assist loss detection at the sender, an endpoint SHOULD generate and send an ACK frame without delay when it receives an ack- eliciting packet either: for connections made by the endpoint and for other users of the network.  13.2.2. A receiver determines how frequently to send acknowledgments in A variable-length integer error code that indicates the reason for closing this connection.  A CONNECTION_CLOSE frame of type 0x1c uses codes from the space defined in transport-error-codes.  A  <ins> CONNECTION_CLOSE frame of type 0x1d uses codes defined by the application protocol; see app-error-codes. </ins> A variable-length integer encoding the type of frame that triggered the error.  A value of 0 (equivalent to the mention of The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and  <ins> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </ins> This document uses the terminology established in QUIC-TRANSPORT. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and  <ins> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </ins> This document uses the variable-length integer encoding from QUIC- TRANSPORT. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and  <ins> "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here. </ins> Definitions of terms that are used in this document: