diff --git a/draft-ietf-quic-qpack.md b/draft-ietf-quic-qpack.md index a28de2c175..9122f8222c 100644 --- a/draft-ietf-quic-qpack.md +++ b/draft-ietf-quic-qpack.md @@ -127,6 +127,19 @@ The dynamic table consists of a list of header fields maintained in first-in, first-out order. The dynamic table is initially empty. Entries are added by instructions on the encoder stream (see {{encoder-stream}}). +The maximum size of the dynamic table can be modified by the encoder, subject to +a decoder-controlled limit (see {{configuration}} and {{size-update}}). The +initial maximum size is determined by the corresponding setting when HTTP +requests or responses are first permitted to be sent. For HTTP/QUIC +servers and HTTP/QUIC clients when 0-RTT is not attempted or is rejected, +this means that the initial maximum table size is the value of the setting +in the peer's SETTINGS frame. For clients using 0-RTT data in HTTP/QUIC, +this means that the table size is the remembered value of the setting, +even if the server later specifies a larger maximum in its SETTINGS frame. +If the server does specify a larger maximum in response to a successful 0-RTT +request, the client encoder MUST recalculate its "MaxEntries" (see +{{absolute-indexing}}). + Before a new entry is added to the dynamic table, entries are evicted from the end of the dynamic table until the size of the dynamic table is less than or equal to (maximum size - new entry size) or until the table is empty. @@ -145,6 +158,8 @@ The dynamic table can contain duplicate entries (i.e., entries with the same name and same value). Therefore, duplicate entries MUST NOT be treated as an error by a decoder. +### Maximum Table Size + The encoder decides how to update the dynamic table and as such can control how much memory is used by the dynamic table. To limit the memory requirements of the decoder, the dynamic table size is strictly bounded. @@ -162,12 +177,45 @@ the dynamic table is less than or equal to the maximum size. This mechanism can be used to completely clear entries from the dynamic table by setting a maximum size of 0, which can subsequently be restored. -### Absolute and Relative Indexing {#indexing} +### Calculating Table Size + +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 octets (as defined +in {{string-literals}}), its value's length in octets, and 32. + +The size of an entry is calculated using the length of its name and value +without any Huffman encoding applied. + +### Absolute Indexing Each entry possesses both an absolute index which is fixed for the lifetime of that entry and a relative index which changes over time based on the context of -the reference. The first entry inserted has an absolute index of "1"; indices -increase sequentially with each insertion. +the reference. + +The absolute index takes on the values in the range + +~~~ + [ 0, MaxEntries * 2 - 1 ] +~~~ + +MaxEntries is the maximum number of entries that the dynamic table can have. +The smallest entry has empty name and value strings and has the size of 32. +The MaxEntries is calculated as + +~~~ + MaxEntries = floor( MaxTableSize / 32 ) +~~~ + +MaxTableSize is the maximum size of the dynamic table as specified by the +decoder (see {{maximum-table-size}}). + +All arithmetic performed on the absolute index is modulo "MaxEntries * 2". +The first entry inserted has an absolute index of "0". Each subsequent +insertion increments the absolute index by 1. The next value after +"MaxEntries * 2 - 1" is "0". + +### Relative Indexing The relative index begins at zero and increases in the opposite direction from the absolute index. Determining which entry has a relative index of "0" depends @@ -251,14 +299,33 @@ Because QUIC does not guarantee order between data on different streams, a header block might reference an entry in the dynamic table that has not yet been received. -Each header block contains a Largest Reference which identifies the table state -necessary for decoding. If the greatest absolute index in the dynamic table is -less than the value of the Largest Reference, the stream is considered -"blocked." While blocked, header field data should remain in the blocked -stream's flow control window. When the Largest Reference is zero, the frame -contains no references to the dynamic table and can always be processed -immediately. A stream becomes unblocked when the greatest absolute index in the -dynamic table becomes greater than or equal to the Largest Reference for all +Each header block contains a Largest Reference field which identifies the +table state necessary for decoding. + +When the Largest Reference value is not specified, the frame contains no +references to the dynamic table and can always be processed immediately. + +When it is specified, the Largest Reference value is compared with +the absolute index value of the next entry to be inserted into the +dynamic table. That entry's absolute index value divides the absolute +index range into two equal parts, each "MaxEntries" in size. The next +entry's absolute index value and "MaxEntries - 1" values that follow it +constitute the Future; "MaxEntries" values preceding the next entry's +absolute index value constitute the Past. + +The lower bound of the Past part of the range is guaranteed by the +fact that the table cannot grow larger than "MaxEntries", as older +entries will get evicted. The higher bound of the Future is ensured +by the insertion throttling (see {{insertion-throttling}}). + +If the Largest Reference is in the Past, the decoder is presumed to +possess all dynamic entries necessary for decoding of the header block; +an unresolved reference MUST be treated as a stream error. Otherwise, +the stream is considered "blocked." While blocked, header field data +should remain in the blocked stream's flow control window. + +A stream becomes unblocked when the Largest Reference value falls in +the Past relative to the latest entry's absolute index for all header blocks the decoder has started reading from the stream. If a decoder encounters a header block where the actual largest reference is not equal to the largest reference declared in the prefix, it MAY treat this as a stream error of @@ -312,6 +379,11 @@ for example because the encoder or the decoder have chosen not to risk blocked streams, the decoder sends a Table State Synchronize instruction (see {{table-state-synchronize}}). +### Insertion Throttling + +The encoder MUST NOT create -- either via insertion or duplication -- more +than "MaxEntries" unacknowledged dynamic table entries. + # Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", @@ -573,7 +645,7 @@ before using it. ### Header Acknowledgement -After processing a header block whose declared Largest Reference is not zero, +After processing a header block whose declared Largest Reference is specified, the decoder emits a Header Acknowledgement instruction on the decoder stream. The instruction begins with the '1' one-bit pattern and includes the request stream's stream ID, encoded as a 7-bit prefix integer. It is used by the @@ -653,8 +725,14 @@ Header data is prefixed with two integers, `Largest Reference` and `Base Index`. the block. Blocking decoders use the Largest Reference to determine when it is safe to process the rest of the block. +Because zero is a valid absolute dynamic index value, the index of the +largest referenced entry is incremented by 1 before it is recorded in the +`Largest Reference` field. If the header block does not reference the +dynamic table, this field is set to zero: this indicates that the value +is not specified. + `Base Index` is used to resolve references in the dynamic table as described in -{{indexing}}. +{{relative-indexing}}. To save space, Base Index is encoded relative to Largest Reference using a one-bit sign and the `Delta Base Index` value. A sign bit of 0 indicates that