From aaa83ef0d6f64e77fd4015e0038821566af9301e Mon Sep 17 00:00:00 2001 From: Mike Bishop Date: Mon, 4 Apr 2022 15:46:21 -0400 Subject: [PATCH 1/4] Differences in text output --- rfc9114.md | 2 +- draft-ietf-quic-qpack.md => rfc9204.md | 213 ++++++++++++------------- 2 files changed, 101 insertions(+), 114 deletions(-) rename draft-ietf-quic-qpack.md => rfc9204.md (93%) diff --git a/rfc9114.md b/rfc9114.md index 1a59c3ed63..93683202eb 100644 --- a/rfc9114.md +++ b/rfc9114.md @@ -1143,9 +1143,9 @@ using QUIC: data sent over a QUIC stream always maps to a particular HTTP transaction or to the entire HTTP/3 connection context. *[control stream]: #control-streams +*[control streams]: control streams *[push stream]: #push-streams *[request stream]: #request-streams -*[control streams]: #control-streams *[push streams]: #push-streams *[request streams]: #request-streams diff --git a/draft-ietf-quic-qpack.md b/rfc9204.md similarity index 93% rename from draft-ietf-quic-qpack.md rename to rfc9204.md index accfa6a7f4..cf883dd67e 100644 --- a/draft-ietf-quic-qpack.md +++ b/rfc9204.md @@ -1,6 +1,7 @@ --- title: "QPACK: Header Compression for HTTP/3" abbrev: QPACK +number: 9204 docname: draft-ietf-quic-qpack-latest date: {DATE} category: std @@ -44,24 +45,6 @@ normative: org: Akamai Technologies role: editor - QUIC-TRANSPORT: - title: "QUIC: A UDP-Based Multiplexed and Secure Transport" - date: {DATE} - seriesinfo: - RFC: 9000 - DOI: 10.17487/RFC9000 - author: - - - ins: J. Iyengar - name: Jana Iyengar - org: Fastly - role: editor - - - ins: M. Thomson - name: Martin Thomson - org: Mozilla - role: editor - SEMANTICS: I-D.ietf-httpbis-semantics RFC2360: @@ -92,17 +75,17 @@ informative: --- abstract -This specification defines QPACK, a compression format for efficiently -representing HTTP fields, to be used in HTTP/3. This is a variation of HPACK -compression that seeks to reduce head-of-line blocking. +This specification defines QPACK: a compression format for efficiently +representing HTTP fields that is to be used in HTTP/3. This is a variation of +HPACK compression that seeks to reduce head-of-line blocking. --- middle # Introduction -The QUIC transport protocol ({{QUIC-TRANSPORT}}) is designed to support HTTP -semantics, and its design subsumes many of the features of HTTP/2 +The QUIC transport protocol ({{!QUIC-TRANSPORT=RFC9000}}) is designed to support +HTTP semantics, and its design subsumes many of the features of HTTP/2 ({{?RFC7540}}). HTTP/2 uses HPACK ({{!RFC7541}}) for compression of the header and trailer sections. If HPACK were used for HTTP/3 ({{HTTP3}}), it would induce head-of-line blocking for field sections due to built-in assumptions of a @@ -121,7 +104,7 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", document are to be interpreted as described in BCP 14 {{!RFC2119}} {{!RFC8174}} when, and only when, they appear in all capitals, as shown here. -Definitions of terms that are used in this document: +The following terms are used in this document: HTTP fields: @@ -174,22 +157,22 @@ Insert Count: : The total number of entries inserted in the dynamic table. -QPACK is a name, not an acronym. +Note that QPACK is a name, not an abbreviation. ## Notational Conventions -Diagrams use the format described in {{Section 3.1 of RFC2360}}, with the -following additional conventions: +Diagrams in this document use the format described in {{Section 3.1 of +RFC2360}}, with the following additional conventions: x (A) -: Indicates that x is A bits long +: Indicates that x is A bits long. x (A+) : Indicates that x uses the prefixed integer encoding defined in {{prefixed-integers}}, beginning with an A-bit prefix. x ... -: Indicates that x is variable-length and extends to the end of the region. +: Indicates that x is variable length and extends to the end of the region. # Compression Process Overview @@ -251,7 +234,7 @@ the decoder; see {{header-acknowledgment}}. To ensure that the encoder is not prevented from adding new entries, the encoder can avoid referencing entries that are close to eviction. Rather than reference such an entry, the encoder can emit a Duplicate instruction -({{duplicate}}), and reference the duplicate instead. +({{duplicate}}) and reference the duplicate instead. Determining which entries are too close to eviction to reference is an encoder preference. One heuristic is to target a fixed amount of available space in the @@ -294,7 +277,7 @@ referenced dynamic table entries. For a field section encoded with no references to the dynamic table, the Required Insert Count is zero. When the decoder receives an encoded field section with a Required Insert Count -greater than its own Insert Count, the stream cannot be processed immediately, +greater than its own Insert Count, the stream cannot be processed immediately and is considered "blocked"; see {{blocked-decoding}}. The decoder specifies an upper bound on the number of streams that can be @@ -310,29 +293,29 @@ becoming blocked. An encoder can decide whether to risk having a stream become blocked. If permitted by the value of SETTINGS_QPACK_BLOCKED_STREAMS, compression efficiency can often be improved by referencing dynamic table entries that are still in -transit, but if there is loss or reordering the stream can become blocked at the -decoder. An encoder can avoid the risk of blocking by only referencing dynamic -table entries that have been acknowledged, but this could mean using literals. -Since literals make the encoded field section larger, this can result in the -encoder becoming blocked on congestion or flow control limits. +transit, but if there is loss or reordering, the stream can become blocked at +the decoder. An encoder can avoid the risk of blocking by only referencing +dynamic table entries that have been acknowledged, but this could mean using +literals. Since literals make the encoded field section larger, this can result +in the encoder becoming blocked on congestion or flow-control limits. -### Avoiding Flow Control Deadlocks +### Avoiding Flow-Control Deadlocks Writing instructions on streams that are limited by flow control can produce deadlocks. -A decoder might stop issuing flow control credit on the stream that carries an +A decoder might stop issuing flow-control credit on the stream that carries an encoded field section until the necessary updates are received on the encoder -stream. If the granting of flow control credit on the encoder stream (or the +stream. If the granting of flow-control credit on the encoder stream (or the connection as a whole) depends on the consumption and release of data on the stream carrying the encoded field section, a deadlock might result. More generally, a stream containing a large instruction can become deadlocked if -the decoder withholds flow control credit until the instruction is completely +the decoder withholds flow-control credit until the instruction is completely received. To avoid these deadlocks, an encoder SHOULD NOT write an instruction unless -sufficient stream and connection flow control credit is available for the entire +sufficient stream and connection flow-control credit is available for the entire instruction. ### Known Received Count @@ -346,8 +329,8 @@ order to be able to send Insert Count Increment instructions. A Section Acknowledgment instruction ({{header-acknowledgment}}) implies that the decoder has received all dynamic table state necessary to decode the field section. If the Required Insert Count of the acknowledged field section is -greater than the current Known Received Count, Known Received Count is updated -to that Required Insert Count value. +greater than the current Known Received Count, the Known Received Count is +updated to that Required Insert Count value. An Insert Count Increment instruction ({{insert-count-increment}}) increases the Known Received Count by its Increment parameter. See {{new-table-entries}} for @@ -374,7 +357,7 @@ decoder's Insert Count, the field section can be processed immediately. Otherwise, the stream on which the field section was received becomes blocked. 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, +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 greater than or equal to the Required Insert Count for all encoded @@ -418,7 +401,7 @@ any updates to the dynamic table have been received. The Section Acknowledgment and Stream Cancellation instructions permit the encoder to remove references to entries in the dynamic table. When an entry -with absolute index lower than the Known Received Count has zero references, +with an absolute index lower than the Known Received Count has zero references, then it is considered evictable; see {{blocked-insertion}}. #### New Table Entries @@ -429,7 +412,7 @@ when to emit Insert Count Increment instructions; see dynamic table entry will provide the timeliest feedback to the encoder, but could be redundant with other decoder feedback. By delaying an Insert Count Increment instruction, the decoder might be able to coalesce multiple Insert -Count Increment instructions, or replace them entirely with Section +Count Increment instructions or replace them entirely with Section Acknowledgments; see {{header-acknowledgment}}. However, delaying too long may lead to compression inefficiencies if the encoder waits for an entry to be acknowledged before using it. @@ -466,7 +449,7 @@ Note that the QPACK static table is indexed from 0, whereas the HPACK static table is indexed from 1. When the decoder encounters an invalid static table index in a field line -representation it MUST treat this as a connection error of type +representation, it MUST treat this as a connection error of type QPACK_DECOMPRESSION_FAILED. If this index is received on the encoder stream, this MUST be treated as a connection error of type QPACK_ENCODER_STREAM_ERROR. @@ -532,7 +515,7 @@ it can choose to use a lower dynamic table capacity; see {{set-dynamic-capacity}}. For clients using 0-RTT data in HTTP/3, the server's maximum table capacity is -the remembered value of the setting, or zero if the value was not previously +the remembered value of the setting or zero if the value was not previously sent. When the client's 0-RTT value of the SETTING is zero, the server MAY set it to a non-zero value in its SETTINGS frame. If the remembered value is non-zero, the server MUST send the same non-zero value in its SETTINGS frame. If @@ -545,8 +528,8 @@ rejected, the maximum table capacity is 0 until the encoder processes a SETTINGS frame with a non-zero value of SETTINGS_QPACK_MAX_TABLE_CAPACITY. When the maximum table capacity is zero, the encoder MUST NOT insert entries -into the dynamic table, and MUST NOT send any encoder instructions on the -encoder stream. +into the dynamic table and MUST NOT send any encoder instructions on the encoder +stream. ### Absolute Indexing {#indexing} @@ -611,7 +594,7 @@ In this example, Base = n - 2 Post-Base indices are used in field line representations for entries with absolute indices greater than or equal to Base, starting at 0 for the entry with -absolute index equal to Base, and increasing in the same direction as the +absolute index equal to Base and increasing in the same direction as the absolute index. Post-Base indices allow an encoder to process a field section in a single pass @@ -657,14 +640,14 @@ HPACK defines string literals to begin on a byte boundary. They begin with a single bit flag, denoted as 'H' in this document (indicating whether the string is Huffman-coded), followed by the Length encoded as a 7-bit prefix integer, and finally Length bytes of data. When Huffman encoding is enabled, the Huffman -table from {{Section B of RFC7541}} is used without modification and Length +table from {{Section B of RFC7541}} is used without modification, and Length indicates the size of the string after encoding. This document expands the definition of string literals by permitting them to begin other than on a byte boundary. An "N-bit prefix string literal" begins mid-byte, with the first (8-N) bits allocated to a previous field. The string -uses one bit for the Huffman flag, followed by the Length encoded as an -(N-1)-bit prefix integer. The prefix size, N, can have a value between 2 and 8 +uses one bit for the Huffman flag, followed by the Length encoded as a +(N-1)-bit prefix integer. The prefix size, N, can have a value between 2 and 8, inclusive. The remainder of the string literal is unmodified. A string literal without a prefix length noted is an 8-bit prefix string literal @@ -683,15 +666,15 @@ QPACK defines two unidirectional stream types: to encoder. HTTP/3 endpoints contain a QPACK encoder and decoder. Each endpoint MUST -initiate at most one encoder stream and at most one decoder stream. Receipt of a -second instance of either stream type MUST be treated as a connection error of -type H3_STREAM_CREATION_ERROR. +initiate, at most, one encoder stream and, at most, one decoder stream. Receipt +of a second instance of either stream type MUST be treated as a connection error +of type H3_STREAM_CREATION_ERROR. These streams MUST NOT be closed. Closure of either unidirectional stream type MUST be treated as a connection error of type H3_CLOSED_CRITICAL_STREAM. An endpoint MAY avoid creating an encoder stream if it will not be used (for -example if its encoder does not wish to use the dynamic table, or if the maximum +example, if its encoder does not wish to use the dynamic table or if the maximum size of the dynamic table permitted by the peer is zero). An endpoint MAY avoid creating a decoder stream if its decoder sets the maximum @@ -736,7 +719,7 @@ Reducing the dynamic table capacity can cause entries to be evicted; see evictable; see {{blocked-insertion}}. Changing the capacity of the dynamic table is not acknowledged as this instruction does not insert an entry. -### Insert With Name Reference +### Insert with Name Reference An encoder adds an entry to the dynamic table where the field name matches the field name of an entry stored in the static or the dynamic table using an @@ -763,13 +746,13 @@ literal; see {{string-literals}}. {: title="Insert Field Line -- Indexed Name"} -### Insert With Literal Name +### Insert with Literal Name An encoder adds an entry to the dynamic table where both the field name and the field value are represented as string literals using an instruction that starts with the '01' 2-bit pattern. -This is followed by the name represented as a 6-bit prefix string literal, and +This is followed by the name represented as a 6-bit prefix string literal and the value represented as an 8-bit prefix string literal; see {{string-literals}}. @@ -803,7 +786,7 @@ prefix; see {{prefixed-integers}}. ~~~~~~~~~~ {:#fig-index-with-duplication title="Duplicate"} -The existing entry is re-inserted into the dynamic table without resending +The existing entry is reinserted into the dynamic table without resending either the name or the value. This is useful to avoid adding a reference to an older entry, which might block inserting new entries. @@ -822,8 +805,8 @@ instruction starts with the '1' 1-bit pattern, followed by the field section's associated stream ID encoded as a 7-bit prefix integer; see {{prefixed-integers}}. -This instruction is used as described in {{known-received-count}} and -in {{state-synchronization}}. +This instruction is used as described in Sections {{< Date: Mon, 4 Apr 2022 17:18:21 -0400 Subject: [PATCH 2/4] More edits, particularly regarding XML --- rfc9204.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/rfc9204.md b/rfc9204.md index cf883dd67e..3af340d3e4 100644 --- a/rfc9204.md +++ b/rfc9204.md @@ -248,7 +248,7 @@ absolute index lower than the draining index, the number of unacknowledged references to those entries will eventually become zero, allowing them to be evicted. -~~~~~~~~~~ drawing +~~~~~~~~~~ ascii-art <-- Newer Entries Older Entries --> (Larger Indicies) (Smaller Indicies) +--------+---------------------------------+----------+ @@ -550,7 +550,7 @@ refers to the most recently inserted value in the dynamic table. Note that this means the entry referenced by a given relative index will change while interpreting instructions on the encoder stream. -~~~~~ drawing +~~~~~ ascii-art +-----+---------------+-------+ | n-1 | ... | d | Absolute Index + - - +---------------+ - - - + @@ -573,7 +573,7 @@ sections and dynamic table updates are processed out of order. In a field line representation, a relative index of 0 refers to the entry with absolute index equal to Base - 1. -~~~~~ drawing +~~~~~ ascii-art Base | V @@ -601,7 +601,7 @@ Post-Base indices allow an encoder to process a field section in a single pass and include references to entries added while processing this (or other) field sections. -~~~~~ drawing +~~~~~ ascii-art Base | V @@ -700,7 +700,7 @@ an instruction that starts with the '001' 3-bit pattern. This is followed by the new dynamic table capacity represented as an integer with a 5-bit prefix; see {{prefixed-integers}}. -~~~~~~~~~~ drawing +~~~~~~~~~~ ascii-art 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 1 | Capacity (5+) | @@ -733,7 +733,7 @@ table. The field name reference is followed by the field value represented as a string literal; see {{string-literals}}. -~~~~~~~~~~ drawing +~~~~~~~~~~ ascii-art 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 1 | T | Name Index (6+) | @@ -756,7 +756,7 @@ This is followed by the name represented as a 6-bit prefix string literal and the value represented as an 8-bit prefix string literal; see {{string-literals}}. -~~~~~~~~~~ drawing +~~~~~~~~~~ ascii-art 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 1 | H | Name Length (5+) | @@ -778,7 +778,7 @@ instruction that starts with the '000' 3-bit pattern. This is followed by the relative index of the existing entry represented as an integer with a 5-bit prefix; see {{prefixed-integers}}. -~~~~~~~~~~ drawing +~~~~~~~~~~ ascii-art 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | Index (5+) | @@ -805,10 +805,10 @@ instruction starts with the '1' 1-bit pattern, followed by the field section's associated stream ID encoded as a 7-bit prefix integer; see {{prefixed-integers}}. -This instruction is used as described in Sections {{< Date: Mon, 4 Apr 2022 17:23:45 -0400 Subject: [PATCH 3/4] Acknowledgements in RFC9000 style --- rfc9204.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/rfc9204.md b/rfc9204.md index 3af340d3e4..dd63724c81 100644 --- a/rfc9204.md +++ b/rfc9204.md @@ -1852,20 +1852,23 @@ people. The compression design team did substantial work exploring the problem space and influencing the initial draft version of this document. The contributions of -design team members Roberto Peon, Martin Thomson, and Dmitri Tikhonov are +design team members , , and are gratefully acknowledged. The following people also provided substantial contributions to this document: -- Bence Béky -- Alessandro Ghedini -- Ryan Hamilton -- Robin Marx -- Patrick McManus -- -- Lucas Pardue -- Biren Roy -- Ian Swett +
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
This document draws heavily on the text of {{!RFC7541}}. The indirect input of those authors is also gratefully acknowledged. From 8cabfdb5b586fe01ef4abe938262b596a5870bb2 Mon Sep 17 00:00:00 2001 From: Mike Bishop Date: Fri, 15 Apr 2022 15:29:17 -0400 Subject: [PATCH 4/4] My suggested modifications --- rfc9204.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rfc9204.md b/rfc9204.md index dd63724c81..b5e70f5101 100644 --- a/rfc9204.md +++ b/rfc9204.md @@ -640,7 +640,7 @@ HPACK defines string literals to begin on a byte boundary. They begin with a single bit flag, denoted as 'H' in this document (indicating whether the string is Huffman-coded), followed by the Length encoded as a 7-bit prefix integer, and finally Length bytes of data. When Huffman encoding is enabled, the Huffman -table from {{Section B of RFC7541}} is used without modification, and Length +table from {{Section B of RFC7541}} is used without modification and Length indicates the size of the string after encoding. This document expands the definition of string literals by permitting them to @@ -1212,8 +1212,8 @@ attack into a linear-time attack. QPACK mitigates, but does not completely prevent, attacks modeled on CRIME ({{CRIME}}) by forcing a guess to match an entire field line rather than individual characters. An attacker can only learn whether a guess is correct or -not, so it is reduced to a brute-force guess for the field values associated -with a given field name. +not, so the attacker is reduced to a brute-force guess for the field values +associated with a given field name. Therefore, the viability of recovering specific field values depends on the entropy of values. As a result, values with high entropy are unlikely to be @@ -1378,7 +1378,7 @@ immediately sent due to flow control is not affected by this limit. Implementations should limit the size of unsent data, especially on the decoder stream where flexibility to choose what to send is limited. Possible responses to an excess of unsent data might include limiting the ability of the peer to -open new streams, reading only from the encoder stream or closing the +open new streams, reading only from the encoder stream, or closing the connection.