From 473d9e7fe1845931528c0bbcc039175bd51a3bf5 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 13 Oct 2017 21:52:01 +1100 Subject: [PATCH 01/10] Transport integer encoding proposal This proposal replaces all integer encodings in frames with a unified variable-length encoding format. It simplifies the encoding considerably, most noticeably in the ACK frame, which I have largely rewritten. This change increases the number of streams to 2^62, but reduces the number of packets and octets per stream to that same number. Both are very large values anyway. I kept the 2^10 scaling on the connection-level flow control window, so that goes to 2^72 now. The cost for ACK is a negligible decrease in efficiency for larger gaps or ACK blocks (mainly between 64 and 255 in length). This is counteracted by an increase in efficiency if there are occasional ranges or gaps larger than 255, which were previously very difficult to encode correctly. As previously discussed, the timestamp format is removed. In its place, we use the same integer encoding, but with a scaling value, or exponent, that is signaled in transport parameters, that should allow common ACK delays to be expressed in fewer octets (an exponent of 0 only allows for 16ms to be encoded in two octets, but the default exponent is 8, allowing up to 128ms of ACK delay to be encoded on two octets with an 8us resolution). I haven't made any changes for HTTP yet, I plan to do that in a separate PR. --- draft-ietf-quic-transport.md | 369 ++++++++++++++++++++--------------- 1 file changed, 208 insertions(+), 161 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 3921b99db7..92aedcd956 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -174,6 +174,9 @@ x (A) x (A/B/C) ... : Indicates that x is one of A, B, or C bits long +x (i) ... +: Indicates that x uses the variable length encoding in {{integer-encoding}} + x (*) ... : Indicates that x is variable-length @@ -710,14 +713,15 @@ client. ## Packet Numbers {#packet-numbers} The packet number is a 64-bit unsigned number and is used as part of a -cryptographic nonce for packet encryption. Each endpoint maintains a separate -packet number for sending and receiving. The packet number for sending MUST -increase by at least one after sending any packet, unless otherwise specified -(see {{initial-packet-number}}). +cryptographic nonce for packet encryption. Only the low 62 bits of this value +are used (see {{integer-encoding}} for details). Each endpoint maintains a +separate packet number for sending and receiving. The packet number for sending +MUST increase by at least one after sending any packet, unless otherwise +specified (see {{initial-packet-number}}). A QUIC endpoint MUST NOT reuse a packet number within the same connection (that is, under the same cryptographic keys). If the packet number for sending -reaches 2^64 - 1, the sender MUST close the connection without sending a +reaches 2^62 - 1, the sender MUST close the connection without sending a CONNECTION_CLOSE frame or any further packets; a server MAY send a Stateless Reset ({{stateless-reset}}) in response to further packets that it receives. @@ -845,8 +849,8 @@ explained in more detail as they are referenced later in the document. | 0x0b | NEW_CONNECTION_ID | {{frame-new-connection-id}} | | 0x0c | STOP_SENDING | {{frame-stop-sending}} | | 0x0d | PONG | {{frame-pong}} | -| 0xa0 - 0xbf | ACK | {{frame-ack}} | -| 0xc0 - 0xff | STREAM | {{frame-stream}} | +| 0x0e | ACK | {{frame-ack}} | +| 0x10 - 0x17 | STREAM | {{frame-stream}} | {: #frame-types title="Frame Types"} # Life of a Connection @@ -1081,6 +1085,7 @@ language from Section 3 of {{!I-D.ietf-tls-tls13}}. omit_connection_id(4), max_packet_size(5), stateless_reset_token(6), + ack_delay_scale(7), (65535) } TransportParameterId; @@ -1189,6 +1194,13 @@ max_packet_size (0x0005): Values below 1200 are invalid. This limit only applies to protected packets ({{packet-protected}}). +ack_delay_exponent (0x0007): + +: An 8-bit unsigned integer value indicating an exponent used to decode the ACK + Delay field in the ACK frame, see {{frame-ack}}. If this value is absent, a + default value of 3 is assumed (indicating a multiplier of 8). Values above 20 + are invalid. + ### Values of Transport Parameters for 0-RTT {#zerortt-parameters} @@ -1818,6 +1830,38 @@ packet. The use of these frames and various frame header bits are described in subsequent sections. +## Variable-Length Integer Encoding {#integer-encoding} + +QUIC frames use a common variable-length encoding for all non-negative integer +values. This encoding ensures that smaller integer values need fewer octets to +encode. + +The QUIC variable-length integer encoding reserves the two most significant bits +of the first octet to encode a length value. The length of the integer is two +to the power of the integer value of those two bits, in octets. The integer +value is encoded on the remaining bits, in network byte order. + +This means that integers are encoded on 1, 2, 4, or 8 octets and can encode 6, +14, 30, or 62 bit values respectively. {{integer-summary}} summarizes the +encoding properties. + +| 2Bit | Length | Usable Bits | Range | +|:-----|:-------|:------------|:----------------------| +| 00 | 1 | 6 | 0-63 | +| 01 | 2 | 14 | 0-16384 | +| 10 | 4 | 30 | 0-1073741824 | +| 11 | 8 | 62 | 0-4611686018427387904 | +{: #integer-summary title="Summary of Integer Encodings"} + +For example, the eight octet sequence c2 19 7c 5e ff 14 e8 8c (in hexadecimal) +decodes to the decimal value 151288809941952652; the four octet sequence 9d 7f +3e 7d decodes to 494878333; the two octet sequence 7b bd decodes to 15293; and +the single octet 25 decodes to 37 (as does the two octet sequence 40 25). + +Error codes ({{error-codes}}) are described using integers, but do not use this +encoding. + + ## PADDING Frame {#frame-padding} The PADDING frame (type=0x00) has no semantic value. PADDING frames can be used @@ -1844,13 +1888,11 @@ The RST_STREAM frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Stream ID (32) | +| Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Application Error Code (16) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| | -+ Final Offset (64) + -| | +| Final Offset (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ @@ -1858,7 +1900,8 @@ The fields are: Stream ID: -: The 32-bit Stream ID of the stream being terminated. +: A variable-length integer encoding of the Stream ID of the stream being + terminated. Application Protocol Error Code: @@ -1867,7 +1910,7 @@ Application Protocol Error Code: Final Offset: -: A 64-bit unsigned integer indicating the absolute byte offset of the end of +: A variable-length integer indicating the absolute byte offset of the end of data written on this stream by the RST_STREAM sender. @@ -1886,7 +1929,7 @@ The CONNECTION_CLOSE frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Error Code (16) | Reason Phrase Length (16) | +| Error Code (16) | Reason Phrase Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reason Phrase (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -1903,7 +1946,7 @@ Error Code: Reason Phrase Length: -: A 16-bit unsigned number specifying the length of the reason phrase in bytes. +: A variable-length integer specifying the length of the reason phrase in bytes. Note that a CONNECTION_CLOSE frame cannot be split between packets, so in practice any limits on packet size will also limit the space available for a reason phrase. @@ -1937,9 +1980,7 @@ The frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| | -+ Maximum Data (64) + -| | +| Maximum Data (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ @@ -1947,7 +1988,7 @@ The fields in the MAX_DATA frame are as follows: Maximum Data: -: A 64-bit unsigned integer indicating the maximum amount of data that can be +: A variable-length integer indicating the maximum amount of data that can be sent on the entire connection, in units of octets. All data sent in STREAM frames counts toward this limit, with the exception of @@ -1970,11 +2011,9 @@ The frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Stream ID (32) | +| Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| | -+ Maximum Stream Data (64) + -| | +| Maximum Stream Data (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ @@ -1982,11 +2021,12 @@ The fields in the MAX_STREAM_DATA frame are as follows: Stream ID: -: The stream ID of the stream that is affected. +: The stream ID of the stream that is affected encoded as a variable-length + integer. Maximum Stream Data: -: A 64-bit unsigned integer indicating the maximum amount of data that can be +: A variable-length integer indicating the maximum amount of data that can be sent on the identified stream, in units of octets. When counting data toward this limit, an endpoint accounts for the largest @@ -2013,14 +2053,16 @@ The frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Maximum Stream ID (32) | +| Maximum Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ The fields in the MAX_STREAM_ID frame are as follows: Maximum Stream ID: -: ID of the maximum peer-initiated stream ID for the connection. + +: ID of the maximum peer-initiated stream ID for the connection encoded as a + variable-length integer. Loss or reordering can mean that a MAX_STREAM_ID frame can be received which states a lower stream limit than the client has previously received. @@ -2104,7 +2146,7 @@ The STREAM_BLOCKED frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Stream ID (32) | +| Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ @@ -2112,7 +2154,7 @@ The STREAM_BLOCKED frame contains a single field: Stream ID: -: A 32-bit unsigned number indicating the stream which is flow control blocked. +: A variable-length integer indicating the stream which is flow control blocked. ## STREAM_ID_BLOCKED Frame {#frame-stream-id-blocked} @@ -2138,7 +2180,7 @@ The NEW_CONNECTION_ID is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Sequence (16) | +| Sequence (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Connection ID (64) + @@ -2158,12 +2200,11 @@ The fields are: Sequence: -: A 16-bit sequence number. This value starts at 0 and increases by 1 for each - connection ID that is provided by the server. The sequence value can wrap; - the value 65535 is followed by 0. When wrapping the sequence field, the - server MUST ensure that a value with the same sequence has been received and - acknowledged by the client. The connection ID that is assigned during the - handshake is assumed to have a sequence of 65535. +: A variable-length integer. This value starts at 0 and increases by 1 for each + connection ID that is provided by the server. The connection ID that is + assigned during the handshake is assumed to have a sequence of -1. That is, + the value selected during the handshake comes immediately before the first + value that a server can send. Connection ID: @@ -2187,7 +2228,7 @@ The STOP_SENDING frame is as follows: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Stream ID (32) | +| Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Application Error Code (16) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -2197,7 +2238,7 @@ The fields are: Stream ID: -: The 32-bit Stream ID of the stream being ignored. +: A variable-length integer carrying the Stream ID of the stream being ignored. Application Error Code: @@ -2220,13 +2261,13 @@ endpoint, the endpoint MAY generate a connection error of type UNSOLICITED_PONG. ## ACK Frame {#frame-ack} -Receivers send ACK frames to inform senders which packets they have received and -processed, as well as which packets are considered missing. The ACK frame -contains between 1 and 256 ACK blocks. ACK blocks are ranges of acknowledged -packets. Implementations MUST NOT generate packets that only contain ACK frames -in response to packets which only contain ACK frames. However, they SHOULD -acknowledge packets containing only ACK frames when sending ACK frames in -response to other packets. +Receivers send ACK frames (type=0xe) to inform senders which packets they have +received and processed, as well as which packets are considered missing. The +ACK frame contains any number of ACK blocks. ACK blocks are ranges of +acknowledged packets. Implementations MUST NOT generate packets that only +contain ACK frames in response to packets which only contain ACK +frames. However, they SHOULD acknowledge packets containing only ACK frames when +sending ACK frames in response to other packets. To limit ACK blocks to those that have not yet been received by the sender, the receiver SHOULD track which ACK frames have been acknowledged by its peer. Once @@ -2256,25 +2297,8 @@ the server. A sender MAY intentionally skip packet numbers to introduce entropy into the connection, to avoid opportunistic acknowledgement attacks. The sender SHOULD close the connection if an unsent packet number is acknowledged. The format of -the ACK frame is efficient at expressing blocks of missing packets; skipping -packet numbers between 1 and 255 effectively provides up to 8 bits of efficient -entropy on demand, which should be adequate protection against most -opportunistic acknowledgement attacks. - -The type byte for a ACK frame contains embedded flags, and is formatted as -`101NLLMM`. These bits are parsed as follows: - -* The first three bits must be set to 101 indicating that this is an ACK frame. - -* The `N` bit indicates whether the frame contains a Num Blocks field. - -* The two `LL` bits encode the length of the Largest Acknowledged field. - The values 00, 01, 02, and 03 indicate lengths of 8, 16, 32, and 64 - bits respectively. - -* The two `MM` bits encode the length of the ACK Block Length fields. - The values 00, 01, 02, and 03 indicate lengths of 8, 16, 32, and 64 - bits respectively. +the ACK frame is efficient at expressing even long blocks of missing packets, +allowing for larger, unpredictable gaps. An ACK frame is shown below. @@ -2282,38 +2306,36 @@ An ACK frame is shown below. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -|[Num Blocks(8)]| -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Largest Acknowledged (8/16/32/64) ... +| Largest Acknowledged (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Delay (16) | +| ACK Delay (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Block Section (*) ... +| ACK Blocks (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ {: #ack-format title="ACK Frame Format"} The fields in the ACK frame are as follows: -Num Blocks (opt): - -: An optional 8-bit unsigned value specifying the number of additional ACK - blocks (besides the required First ACK Block) in this ACK frame. Only present - if the 'N' flag bit is 1. - Largest Acknowledged: -: A variable-sized unsigned value representing the largest packet number the - peer is acknowledging in this packet (typically the largest that the peer has - seen thus far.) +: A variable-length integer representing the largest packet number the peer is + acknowledging. Typically, this is the largest packet number that the peer has + received prior to generating the ACK frame. ACK Delay: -: The time from when the largest acknowledged packet, as indicated in the - Largest Acknowledged field, was received by this peer to when this ACK was - sent. +: A variable-length integer including the time in microseconds that the largest + acknowledged packet, as indicated in the Largest Acknowledged field, was + received by this peer to when this ACK was sent. The value of the ACK Delay + field is scaled by multiplying the encoded value by the 2 to the power of the + value of the `ack_delay_exponent` transport parameter set by the sender of the + ACK frame. The `ack_delay_exponent` defaults to 3, or a multiplier of 8 (see + {{transport-parameter-definitions}}). Scaling in this fashion allows for a + larger range of values with a shorter encoding at the cost of lower + resolution. -ACK Block Section: +ACK Blocks: : Contains one or more blocks of packet numbers which have been successfully received, see {{ack-block-section}}. @@ -2321,65 +2343,92 @@ ACK Block Section: ### ACK Block Section {#ack-block-section} -The ACK Block Section contains between one and 256 blocks of packet numbers -which have been successfully received. If the Num Blocks field is absent, only -the First ACK Block length is present in this section. Otherwise, the Num Blocks -field indicates how many additional blocks follow the First ACK Block Length -field. +The ACK Block Section consists of alternating ACK Blocks and Gaps. A First Ack +Block is followed by a variable number of alternating Gap and Additional ACK +Blocks. The sequence ends with a Gap that is set to 0. + +ACK Blocks and Gaps use a relative integer encoding for efficiency. As long as +contiguous ranges of packets are small, the variable-length integer encoding +ensures that each range can be expressed in a minimal number of octets. ~~~ 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| First ACK Block Length (8/16/32/64) ... +| First ACK Block (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| [Gap 1 (8)] | [ACK Block 1 Length (8/16/32/64)] ... +| Gap (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| [Gap 2 (8)] | [ACK Block 2 Length (8/16/32/64)] ... +| Additional ACK Block (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ... +| Gap (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Additional ACK Block (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| [Gap N (8)] | [ACK Block N Length (8/16/32/64)] ... +| Final Gap (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ {: #ack-block-format title="ACK Block Section"} -The fields in the ACK Block Section are: -First ACK Block Length: +Each ACK Block acknowledges a contiguous range of packets by indicating the +number of packets that acknowledged preceding the largest packet number in that +block. A value of zero indicates that only the largest packet number is +acknowledged. Larger ACK Block values indicate a larger range, with +corresponding lower values for the smallest packet number in the range. Thus, +given a largest packet number for the ACK, the smallest value is determined by +the formula: + +~~~ + smallest = largest - ack_block +~~~ + +The range of packets that are acknowledged by the ACK block include the range +from the smallest packet number to the largest, inclusive. + +The largest value for the First ACK Block is determined by the Largest +Acknowledged field; the largest for Additional ACK Blocks is determined by +cumulatively subtracting the size of all preceding ACK Blocks and Gaps. -: An unsigned packet number delta that indicates the number of contiguous - additional packets being acknowledged starting at the Largest Acknowledged. +Each Gap indicates a range of packets that are not being acknowledged. This +value MUST be non-zero for all gaps except the final gap. The Final Gap field +has a value of 0, which is used to indicate the end of the ACK frame. -Gap To Next Block (opt, repeated): +The value of the Gap field establishes the largest packet number value for the +ACK block that follows the gap using the following formula: -: An unsigned number specifying the number of contiguous missing packets from - the end of the previous ACK block to the start of the next. Repeated "Num - Blocks" times. +~~~ + largest = previous_smallest - gap - 1 +~~~ + +If the calculated value for largest or smallest packet number for any ACK Block +is negative, an endpoint MUST generate a connection error of type FRAME_ERROR +indicating an error in an ACK frame (that is, 0x1TBD). + +The fields in the ACK Block Section are: + +First ACK Block: -ACK Block Length (opt, repeated): +: A variable-length indicating the number of contiguous packets in addition to + the Largest Acknowledged that are being acknowledged. -: An unsigned packet number delta that indicates the number of contiguous - packets being acknowledged starting after the end of the previous gap. - Repeated "Num Blocks" times. +Gap (repeated): +: A non-zero, variable-length integer indicating specifying the number of + contiguous unacknowledged packets, starting from the packet number one lower + than the smallest in the preceding ACK Block. -#### Time Format +ACK Block (repeated): -DISCUSS_AND_REPLACE: Perhaps make this format simpler. +: A variable-length integer indicating the number of contiguous acknowledged + packets in addition to the largest packet number, as determined by the + preceding Gap. -The time format used in the ACK frame above is a 16-bit unsigned float with 11 -explicit bits of mantissa and 5 bits of explicit exponent, specifying time in -microseconds. The bit format is loosely modeled after IEEE 754. For example, 1 -microsecond is represented as 0x1, which has an exponent of zero, presented in -the 5 high order bits, and mantissa of 1, presented in the 11 low order bits. -When the explicit exponent is greater than zero, an implicit high-order 12th bit -of 1 is assumed in the mantissa. For example, a floating value of 0x800 has an -explicit exponent of 1, as well as an explicit mantissa of 0, but then has an -effective mantissa of 4096 (12th bit is assumed to be 1). Additionally, the -actual exponent is one-less than the explicit exponent, and the value represents -4096 microseconds. Any values larger than the representable range are clamped -to 0xFFFF. +Final Gap (repeated): + +: A zero-valued, variable-length integer indicating the end of the ACK frame. ### ACK Frames and Packet Protection @@ -2422,30 +2471,25 @@ by a client in protected packets, because it is certain that the server is able to decipher the packet. -## STREAM Frame {#frame-stream} - -STREAM frames implicitly create a stream and carry stream data. The type byte -for a STREAM frame contains embedded flags, and is formatted as `11FSSOOD`. -These bits are parsed as follows: - -* The first two bits must be set to 11, indicating that this is a STREAM frame. +## STREAM Frames {#frame-stream} -* `F` is the FIN bit, which is used for stream termination. +STREAM frames implicitly create a stream and carry stream data. There are eight +types of STREAM frame from 0x10 to 0x17. The value of the three low-order bits +of the frame type determine the fields that are present in the frame. -* The `SS` bits encode the length of the Stream ID header field. - The values 00, 01, 02, and 03 indicate lengths of 8, 16, 24, and 32 bits - long respectively. +* The FIN bit (0x01) of the frame type is set only on frames that contain the + final offset of the stream. Setting this bit indicates that the frame + contains the end of the stream data. -* The `OO` bits encode the length of the Offset header field. - The values 00, 01, 02, and 03 indicate lengths of 0, 16, 32, and - 64 bits long respectively. +* The LEN bit (0x02) in the frame type is set to indicate that there is a Length + field present. If this bit is set to 0, the Length field is absent and the + Stream Data field extends to the end of the packet. If this bit is set to 1, + the Length field is present. -* The `D` bit indicates whether a Data Length field is present in the STREAM - header. When set to 0, this field indicates that the Stream Data field - extends to the end of the packet. When set to 1, this field indicates that - Data Length field contains the length (in bytes) of the Stream Data field. - The option to omit the length should only be used when the packet is a - "full-sized" packet, to avoid the risk of corruption via padding. +* The OFF bit (0x04) in the frame type is set to indicate that there is an + Offset field present. When set to 1, the Offset field is present; when set to + 0, the Offset field is absent and the Stream Data starts at an offset of 0 + (that is, the frame contains the first octets of the stream). A STREAM frame is shown below. @@ -2453,11 +2497,13 @@ A STREAM frame is shown below. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Stream ID (8/16/24/32) ... +| Stream ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Offset (0/16/32/64) ... +| [Offset (i)] ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| [Data Length (16)] | Stream Data (*) ... +| [Length (i)] ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Stream Data (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ {: #stream-format title="STREAM Frame Format"} @@ -2466,21 +2512,19 @@ The STREAM frame contains the following fields: Stream ID: -: The stream ID of the stream (see {{stream-id}}). +: A variable-length integer indicating the stream ID of the stream (see + {{stream-id}}). Offset: -: A variable-sized unsigned number specifying the byte offset in the stream for - the data in this STREAM frame. When the offset length is 0, the offset is 0. - The first byte in the stream has an offset of 0. The largest offset delivered - on a stream - the sum of the re-constructed offset and data length - MUST be - less than 2^64. +: A variable-sized integer specifying the byte offset in the stream for the data + in this STREAM frame. THis field is present when the OFF bit is set to 1. + When the Offset field is absent, the offset is 0. -Data Length: +Length: -: An optional 16-bit unsigned number specifying the length of the Stream Data - field in this STREAM frame. This field is present when the `D` bit is set to - 1. +: An variable-length integer specifying the length of the Stream Data field in + this STREAM frame. This field is present when the LEN bit is set to 1. Stream Data: @@ -2490,6 +2534,10 @@ A stream frame's Stream Data MUST NOT be empty, unless the FIN bit is set. When the FIN flag is sent on an empty STREAM frame, the offset in the STREAM frame is the offset of the next byte that would be sent. +The first byte in the stream has an offset of 0. The largest offset delivered +on a stream - the sum of the re-constructed offset and data length - MUST be +less than 2^62. + Stream multiplexing is achieved by interleaving STREAM frames from multiple streams into one or more QUIC packets. A single QUIC packet can include multiple STREAM frames from one or more streams. @@ -2664,13 +2712,13 @@ for some applications. ## Stream Identifiers {#stream-id} -Streams are identified by an unsigned 32-bit integer, referred to as the Stream +Streams are identified by an unsigned 62-bit integer, referred to as the Stream ID. To avoid Stream ID collision, clients MUST initiate streams using -odd-numbered Stream IDs; servers MUST initiate streams using -even-numbered Stream IDs. If an endpoint receives a frame which -corresponds to a stream which is allocated to it (i.e., odd-numbered for -the client or even-numbered for the server) but which it has not yet -created, it MUST close the connection with error code STREAM_STATE_ERROR. +odd-numbered Stream IDs; servers MUST initiate streams using even-numbered +Stream IDs. If an endpoint receives a frame which corresponds to a stream which +is allocated to it (i.e., odd-numbered for the client or even-numbered for the +server) but which it has not yet created, it MUST close the connection with +error code STREAM_STATE_ERROR. Stream ID 0 (0x0) is reserved for the cryptographic handshake. Stream 0 MUST NOT be used for application data, and is the first client-initiated stream. @@ -2680,9 +2728,8 @@ in sequential order. Open streams can be used in any order. Streams that are used out of order result in lower-numbered streams in the same direction being counted as open. -Stream IDs are usually encoded as a 32-bit integer, though the STREAM frame -({{frame-stream}}) permits a shorter encoding when the leading bits of the -stream ID are zero. +Stream IDs are usually encoded as a variable-length integer +(see {{integer-encoding}}). ## Life of a Stream {#stream-states} @@ -2936,7 +2983,7 @@ sender or during delivery to the application at the receiver. When new data is to be sent on a stream, a sender MUST set the encapsulating STREAM frame's offset field to the stream offset of the first byte of this new data. The first byte of data that is sent on a stream has the stream offset 0. -The largest offset delivered on a stream MUST be less than 2^64. A receiver +The largest offset delivered on a stream MUST be less than 2^62. A receiver MUST ensure that received stream data is delivered to the application as an ordered byte-stream. Data received out of order MUST be buffered for later delivery, as long as it is not in violation of the receiver's flow control From 06112c66869ae5cb7b1e741cf46417cad9ca7477 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 16 Oct 2017 10:19:27 +1100 Subject: [PATCH 02/10] Review comments --- draft-ietf-quic-transport.md | 63 +++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 92aedcd956..9dd854cb9d 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -712,12 +712,11 @@ client. ## Packet Numbers {#packet-numbers} -The packet number is a 64-bit unsigned number and is used as part of a -cryptographic nonce for packet encryption. Only the low 62 bits of this value -are used (see {{integer-encoding}} for details). Each endpoint maintains a -separate packet number for sending and receiving. The packet number for sending -MUST increase by at least one after sending any packet, unless otherwise -specified (see {{initial-packet-number}}). +The packet number is an integer in the range 0 to 2^62-1. The value is used in +determining the cryptographic nonce for packet encryption. Each endpoint +maintains a separate packet number for sending and receiving. The packet number +for sending MUST increase by at least one after sending any packet, unless +otherwise specified (see {{initial-packet-number}}). A QUIC endpoint MUST NOT reuse a packet number within the same connection (that is, under the same cryptographic keys). If the packet number for sending @@ -725,10 +724,11 @@ reaches 2^62 - 1, the sender MUST close the connection without sending a CONNECTION_CLOSE frame or any further packets; a server MAY send a Stateless Reset ({{stateless-reset}}) in response to further packets that it receives. -To reduce the number of bits required to represent the packet number over the -wire, only the least significant bits of the packet number are transmitted. The -actual packet number for each packet is reconstructed at the receiver based on -the largest packet number received on a successfully authenticated packet. +For the packet header, the number of bits required to represent the packet +number are reduced by including only the least significant bits of the packet +number. The actual packet number for each packet is reconstructed at the +receiver based on the largest packet number received on a successfully +authenticated packet. A packet number is decoded by finding the packet number value that is closest to the next expected packet. The next expected packet is the highest received @@ -1085,7 +1085,7 @@ language from Section 3 of {{!I-D.ietf-tls-tls13}}. omit_connection_id(4), max_packet_size(5), stateless_reset_token(6), - ack_delay_scale(7), + ack_delay_exponent(7), (65535) } TransportParameterId; @@ -1837,9 +1837,9 @@ values. This encoding ensures that smaller integer values need fewer octets to encode. The QUIC variable-length integer encoding reserves the two most significant bits -of the first octet to encode a length value. The length of the integer is two -to the power of the integer value of those two bits, in octets. The integer -value is encoded on the remaining bits, in network byte order. +of the first octet to encode the base 2 logarithm of the integer encoding length +in octets. The integer value is encoded on the remaining bits, in network byte +order. This means that integers are encoded on 1, 2, 4, or 8 octets and can encode 6, 14, 30, or 62 bit values respectively. {{integer-summary}} summarizes the @@ -2320,7 +2320,7 @@ The fields in the ACK frame are as follows: Largest Acknowledged: : A variable-length integer representing the largest packet number the peer is - acknowledging. Typically, this is the largest packet number that the peer has + acknowledging; this is usually the largest packet number that the peer has received prior to generating the ACK frame. ACK Delay: @@ -2349,7 +2349,7 @@ Blocks. The sequence ends with a Gap that is set to 0. ACK Blocks and Gaps use a relative integer encoding for efficiency. As long as contiguous ranges of packets are small, the variable-length integer encoding -ensures that each range can be expressed in a minimal number of octets. +ensures that each range can be expressed in a small number of octets. ~~~ 0 1 2 3 @@ -2411,8 +2411,8 @@ The fields in the ACK Block Section are: First ACK Block: -: A variable-length indicating the number of contiguous packets in addition to - the Largest Acknowledged that are being acknowledged. +: A variable-length indicating the number of contiguous packets preceding the + Largest Acknowledged that are being acknowledged. Gap (repeated): @@ -2423,10 +2423,10 @@ Gap (repeated): ACK Block (repeated): : A variable-length integer indicating the number of contiguous acknowledged - packets in addition to the largest packet number, as determined by the + packets preceding the largest packet number, as determined by the preceding Gap. -Final Gap (repeated): +Final Gap: : A zero-valued, variable-length integer indicating the end of the ACK frame. @@ -2473,13 +2473,14 @@ to decipher the packet. ## STREAM Frames {#frame-stream} -STREAM frames implicitly create a stream and carry stream data. There are eight -types of STREAM frame from 0x10 to 0x17. The value of the three low-order bits -of the frame type determine the fields that are present in the frame. +STREAM frames implicitly create a stream and carry stream data. The STREAM +frame takes the form 0b00010XXX (or the set of values from 0x10 to 0x17). The +value of the three low-order bits of the frame type determine the fields that +are present in the frame. * The FIN bit (0x01) of the frame type is set only on frames that contain the final offset of the stream. Setting this bit indicates that the frame - contains the end of the stream data. + marks the end of the stream. * The LEN bit (0x02) in the frame type is set to indicate that there is a Length field present. If this bit is set to 0, the Length field is absent and the @@ -2489,7 +2490,8 @@ of the frame type determine the fields that are present in the frame. * The OFF bit (0x04) in the frame type is set to indicate that there is an Offset field present. When set to 1, the Offset field is present; when set to 0, the Offset field is absent and the Stream Data starts at an offset of 0 - (that is, the frame contains the first octets of the stream). + (that is, the frame contains the first octets of the stream, or the end of a + stream that includes no data). A STREAM frame is shown below. @@ -2518,13 +2520,15 @@ Stream ID: Offset: : A variable-sized integer specifying the byte offset in the stream for the data - in this STREAM frame. THis field is present when the OFF bit is set to 1. + in this STREAM frame. This field is present when the OFF bit is set to 1. When the Offset field is absent, the offset is 0. Length: -: An variable-length integer specifying the length of the Stream Data field in - this STREAM frame. This field is present when the LEN bit is set to 1. +: A variable-length integer specifying the length of the Stream Data field in + this STREAM frame. This field is present when the LEN bit is set to 1. When + the LEN bit is set to 0, the Stream Data field consumes all the remaining + octets in the packet. Stream Data: @@ -2728,8 +2732,7 @@ in sequential order. Open streams can be used in any order. Streams that are used out of order result in lower-numbered streams in the same direction being counted as open. -Stream IDs are usually encoded as a variable-length integer -(see {{integer-encoding}}). +Stream IDs are encoded as a variable-length integer (see {{integer-encoding}}). ## Life of a Stream {#stream-states} From 66c5285f8e84786b7cb99dcab744f227c7f16843 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 16 Oct 2017 10:30:00 +1100 Subject: [PATCH 03/10] Add a length field to ACK --- draft-ietf-quic-transport.md | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 9dd854cb9d..4f90db3bb8 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2306,7 +2306,9 @@ An ACK frame is shown below. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Largest Acknowledged (i) ... +| ACK Frame Length (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Largest Acknowledged (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Delay (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -2317,6 +2319,11 @@ An ACK frame is shown below. The fields in the ACK frame are as follows: +ACK Frame Length: + +: The length of the remainder of the ACK frame in octets. The length is + measured from the start of the encoded Largest Acknowledged field. + Largest Acknowledged: : A variable-length integer representing the largest packet number the peer is @@ -2367,12 +2374,13 @@ ensures that each range can be expressed in a small number of octets. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Final Gap (i) ... +| Gap (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| Additional ACK Block (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ {: #ack-block-format title="ACK Block Section"} - Each ACK Block acknowledges a contiguous range of packets by indicating the number of packets that acknowledged preceding the largest packet number in that block. A value of zero indicates that only the largest packet number is @@ -2392,20 +2400,20 @@ The largest value for the First ACK Block is determined by the Largest Acknowledged field; the largest for Additional ACK Blocks is determined by cumulatively subtracting the size of all preceding ACK Blocks and Gaps. -Each Gap indicates a range of packets that are not being acknowledged. This -value MUST be non-zero for all gaps except the final gap. The Final Gap field -has a value of 0, which is used to indicate the end of the ACK frame. +Each Gap indicates a range of packets that are not being acknowledged. The +number of packets in the gap is one higher than the encoded value of the Gap +Field. The value of the Gap field establishes the largest packet number value for the ACK block that follows the gap using the following formula: ~~~ - largest = previous_smallest - gap - 1 + largest = previous_smallest - gap - 2 ~~~ If the calculated value for largest or smallest packet number for any ACK Block is negative, an endpoint MUST generate a connection error of type FRAME_ERROR -indicating an error in an ACK frame (that is, 0x1TBD). +indicating an error in an ACK frame (that is, 0x10d). The fields in the ACK Block Section are: @@ -2417,8 +2425,8 @@ First ACK Block: Gap (repeated): : A non-zero, variable-length integer indicating specifying the number of - contiguous unacknowledged packets, starting from the packet number one lower - than the smallest in the preceding ACK Block. + contiguous unacknowledged packets preceding the packet number one lower than + the smallest in the preceding ACK Block. ACK Block (repeated): @@ -2426,9 +2434,11 @@ ACK Block (repeated): packets preceding the largest packet number, as determined by the preceding Gap. -Final Gap: - -: A zero-valued, variable-length integer indicating the end of the ACK frame. +If the repeated Gap and ACK Block fields do not end precisely at the end of +sequence of octets indicated by the ACK Frame Length field, or the ACK Frame +Length field indicates a length that exceeds the space available in the packet, +an endpoint MUST generate a connection error of type FRAME_ERROR indicating an +error in an ACK frame (that is, 0x10d) ### ACK Frames and Packet Protection From fd78bccd18ebb8fdca9fc6a0cb963d8e992b12b5 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Tue, 17 Oct 2017 14:27:50 +1100 Subject: [PATCH 04/10] Use a count rather than a length --- draft-ietf-quic-transport.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 4f90db3bb8..3d76c8e372 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2306,12 +2306,12 @@ An ACK frame is shown below. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Frame Length (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Largest Acknowledged (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Delay (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| ACK Block Count (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Blocks (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ @@ -2319,11 +2319,6 @@ An ACK frame is shown below. The fields in the ACK frame are as follows: -ACK Frame Length: - -: The length of the remainder of the ACK frame in octets. The length is - measured from the start of the encoded Largest Acknowledged field. - Largest Acknowledged: : A variable-length integer representing the largest packet number the peer is @@ -2342,6 +2337,10 @@ ACK Delay: larger range of values with a shorter encoding at the cost of lower resolution. +ACK Block Count: + +: The number of Additional ACK Block (and Gap) fields after the First ACK Block. + ACK Blocks: : Contains one or more blocks of packet numbers which have been successfully @@ -2352,11 +2351,14 @@ ACK Blocks: The ACK Block Section consists of alternating ACK Blocks and Gaps. A First Ack Block is followed by a variable number of alternating Gap and Additional ACK -Blocks. The sequence ends with a Gap that is set to 0. - -ACK Blocks and Gaps use a relative integer encoding for efficiency. As long as -contiguous ranges of packets are small, the variable-length integer encoding -ensures that each range can be expressed in a small number of octets. +Blocks. The number of Additional ACK Blocks and Gaps is determined by the ACK +Block Count field. + +ACK Blocks and Gaps use a relative integer encoding for efficiency. Though each +encoded value is positive, the values are subtracted, so that ACK Blocks +describe progressively lower-numbered packets. As long as contiguous ranges of +packets are small, the variable-length integer encoding ensures that each range +can be expressed in a small number of octets. ~~~ 0 1 2 3 From 5c120d002958013b939db714517d98ddebfc97a3 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 19 Oct 2017 13:34:49 +1100 Subject: [PATCH 05/10] Subtract one from ranges --- draft-ietf-quic-transport.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 3d76c8e372..03b8422b09 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1848,9 +1848,9 @@ encoding properties. | 2Bit | Length | Usable Bits | Range | |:-----|:-------|:------------|:----------------------| | 00 | 1 | 6 | 0-63 | -| 01 | 2 | 14 | 0-16384 | -| 10 | 4 | 30 | 0-1073741824 | -| 11 | 8 | 62 | 0-4611686018427387904 | +| 01 | 2 | 14 | 0-16383 | +| 10 | 4 | 30 | 0-1073741823 | +| 11 | 8 | 62 | 0-4611686018427387903 | {: #integer-summary title="Summary of Integer Encodings"} For example, the eight octet sequence c2 19 7c 5e ff 14 e8 8c (in hexadecimal) From 7be15c0a449392c2843a35792209bad600829eec Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Fri, 20 Oct 2017 10:18:29 +1100 Subject: [PATCH 06/10] Editorial fixup --- draft-ietf-quic-transport.md | 42 ++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 03b8422b09..1a7d5e2a22 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2349,16 +2349,16 @@ ACK Blocks: ### ACK Block Section {#ack-block-section} -The ACK Block Section consists of alternating ACK Blocks and Gaps. A First Ack -Block is followed by a variable number of alternating Gap and Additional ACK -Blocks. The number of Additional ACK Blocks and Gaps is determined by the ACK -Block Count field. +The ACK Block Section consists of alternating Gap and ACK Block fields in +descending packet number order. A First Ack Block field is followed by a +variable number of alternating Gap and Additional ACK Blocks. The number of Gap +and Additional ACK Block fields is determined by the ACK Block Count field. -ACK Blocks and Gaps use a relative integer encoding for efficiency. Though each -encoded value is positive, the values are subtracted, so that ACK Blocks -describe progressively lower-numbered packets. As long as contiguous ranges of -packets are small, the variable-length integer encoding ensures that each range -can be expressed in a small number of octets. +Gap and ACK Block fields use a relative integer encoding for efficiency. Though +each encoded value is positive, the values are subtracted, so that each ACK +Block describes progressively lower-numbered packets. As long as contiguous +ranges of packets are small, the variable-length integer encoding ensures that +each range can be expressed in a small number of octets. ~~~ 0 1 2 3 @@ -2384,7 +2384,7 @@ can be expressed in a small number of octets. {: #ack-block-format title="ACK Block Section"} Each ACK Block acknowledges a contiguous range of packets by indicating the -number of packets that acknowledged preceding the largest packet number in that +number of acknowledged packets that precede the largest packet number in that block. A value of zero indicates that only the largest packet number is acknowledged. Larger ACK Block values indicate a larger range, with corresponding lower values for the smallest packet number in the range. Thus, @@ -2421,14 +2421,14 @@ The fields in the ACK Block Section are: First ACK Block: -: A variable-length indicating the number of contiguous packets preceding the - Largest Acknowledged that are being acknowledged. +: A variable-length integer indicating the number of contiguous packets + preceding the Largest Acknowledged that are being acknowledged. Gap (repeated): -: A non-zero, variable-length integer indicating specifying the number of - contiguous unacknowledged packets preceding the packet number one lower than - the smallest in the preceding ACK Block. +: A variable-length integer indicating specifying the number of contiguous + unacknowledged packets preceding the packet number one lower than the smallest + in the preceding ACK Block. ACK Block (repeated): @@ -2436,12 +2436,6 @@ ACK Block (repeated): packets preceding the largest packet number, as determined by the preceding Gap. -If the repeated Gap and ACK Block fields do not end precisely at the end of -sequence of octets indicated by the ACK Frame Length field, or the ACK Frame -Length field indicates a length that exceeds the space available in the packet, -an endpoint MUST generate a connection error of type FRAME_ERROR indicating an -error in an ACK frame (that is, 0x10d) - ### ACK Frames and Packet Protection @@ -2531,9 +2525,9 @@ Stream ID: Offset: -: A variable-sized integer specifying the byte offset in the stream for the data - in this STREAM frame. This field is present when the OFF bit is set to 1. - When the Offset field is absent, the offset is 0. +: A variable-length integer specifying the byte offset in the stream for the + data in this STREAM frame. This field is present when the OFF bit is set to + 1. When the Offset field is absent, the offset is 0. Length: From 12d0946ccaba1bab42b8d3bbb0f12214d13dbc8c Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 18 Oct 2017 17:28:31 +1100 Subject: [PATCH 07/10] Maximal change for HTTP integer encoding This didn't turn out to be that disruptive. I'm somewhat worried that I missed something actually. Given that the changes are small, I think that I would prefer this over #887 for #877. The most interesting change here is that extension frame types that mention Stream IDs will have to change. I am not aware of any proposed thus far, so maybe it's not too much of a cost to bear. It further confirms my view that we shouldn't be using Stream IDs at this layer anyway. Based on this, I don't see any need for a middle-ground change. The biggest cost here is in taking the larger Stream ID space, not in taking the integer encoding. --- draft-ietf-quic-http.md | 103 ++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index 074a2b8672..f8b7c63ad6 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -85,6 +85,9 @@ defined in {{!RFC2119}}. Field definitions are given in Augmented Backus-Naur Form (ABNF), as defined in {{!RFC5234}}. +This document uses the variable-length integer encoding from +{{QUIC-TRANSPORT}}. + # QUIC Advertisement @@ -362,7 +365,7 @@ This header consists of a 32-bit Push ID, which identifies a server push (see 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Push ID (32) | +| Push ID (i) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~~~ {: #fig-push-stream-header title="Push Stream Header"} @@ -415,6 +418,9 @@ All frames have the following format: ~~~~~~~~~~ {: #fig-frame title="HTTP/QUIC frame format"} +Note that the first four octets of the frame use a fixed-size encoding; a +variable-length integer encoding is used for the contents of frames. + ## Frame Definitions {#frames} ### DATA {#frame-data} @@ -485,9 +491,9 @@ The flags defined are: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prioritized Request ID (32) | + | Prioritized Request ID (i) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Stream Dependency ID (32) | + | Stream Dependency ID (i) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Weight (8) | +-+-+-+-+-+-+-+-+ @@ -497,16 +503,16 @@ The flags defined are: The PRIORITY frame payload has the following fields: Prioritized Request ID: - : A 32-bit identifier for a request. This contains the stream ID of a request - stream when the PUSH_PRIORITIZED flag is clear, or a Push ID when the - PUSH_PRIORITIZED flag is set. + : A variable-length integer that identifies a request. This contains + the Stream ID of a request stream when the PUSH_PRIORITIZED flag is clear, + or a Push ID when the PUSH_PRIORITIZED flag is set. Stream Dependency ID: - : A 32-bit stream identifier for a dependent request. This contains the - stream ID of a request stream when the PUSH_DEPENDENT flag is clear, or a - Push ID when the PUSH_DEPENDENT flag is set. A request stream ID of 0 - indicates a dependency on the root stream. For details of dependencies, - see {{priority}} and {{!RFC7540}}, Section 5.3. + : A variable length integer that identifies a dependent request. This + contains the Stream ID of a request stream when the PUSH_DEPENDENT flag is + clear, or a Push ID when the PUSH_DEPENDENT flag is set. A request Stream + ID of 0 indicates a dependency on the root stream. For details of + dependencies, see {{priority}} and {{!RFC7540}}, Section 5.3. Weight: : An unsigned 8-bit integer representing a priority weight for the stream (see @@ -534,15 +540,18 @@ HTTP_MALFORMED_PRIORITY error, unless it references stream ID 0. A PRIORITY that sets a PUSH_PRIORITIZED or PUSH_DEPENDENT flag, but then references a non-existent Push ID MUST be treated as a HTTP_MALFORMED_PRIORITY error. -The length of a PRIORITY frame is 9 octets. A PRIORITY frame with any other -length MUST be treated as a connection error of type HTTP_MALFORMED_PRIORITY. +A PRIORITY frame MUST contain only the identified fields. A PRIORITY frame that +contains more or fewer fields, or a PRIORITY frame that includes a truncated +integer encoding MUST be treated as a connection error of type +HTTP_MALFORMED_PRIORITY. ### CANCEL_PUSH {#frame-cancel-push} The CANCEL_PUSH frame (type=0x3) is used to request cancellation of server push prior to the push stream being created. The CANCEL_PUSH frame identifies a -server push request by Push ID (see {{frame-push-promise}}). +server push request by Push ID (see {{frame-push-promise}}) using a +variable-length integer. When a server receives this frame, it aborts sending the response for the identified server push. If the server has not yet started to send the server @@ -569,8 +578,9 @@ that is being cancelled (see {{frame-push-promise}}). If the client receives a CANCEL_PUSH frame, that frame might identify a Push ID that has not yet been mentioned by a PUSH_PROMISE frame. -A server MUST treat a CANCEL_PUSH frame payload that is other than 4 octets in -length as a connection error of type HTTP_MALFORMED_CANCEL_PUSH. +A server MUST treat a CANCEL_PUSH frame payload does not contain exactly one +variable-length integer as a connection error of type +HTTP_MALFORMED_CANCEL_PUSH. ### SETTINGS {#frame-settings} @@ -605,7 +615,7 @@ value. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier (16) | Length (16) | + | Identifier (16) | Length (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Contents (?) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -638,20 +648,17 @@ HTTP_MALFORMED_SETTINGS. #### Integer encoding -Settings which are integers are transmitted in network byte order. Leading -zero octets are permitted, but implementations SHOULD use only as many bytes as -are needed to represent the value. An integer MUST NOT be represented in more -bytes than would be used to transfer the maximum permitted value. +Settings which are integers use the QUIC variable-length integer encoding. #### Defined SETTINGS Parameters {#settings-parameters} The following settings are defined in HTTP/QUIC: SETTINGS_HEADER_TABLE_SIZE (0x1): - : An integer with a maximum value of 2^32 - 1. This value MUST be zero. + : An integer with a maximum value of 2^30 - 1. This value MUST be zero. SETTINGS_MAX_HEADER_LIST_SIZE (0x6): - : An integer with a maximum value of 2^32 - 1 + : An integer with a maximum value of 2^30 - 1 #### Usage in 0-RTT @@ -691,7 +698,7 @@ server to client, as in HTTP/2. The PUSH_PROMISE frame defines no flags. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Push ID (32) | + | Push ID (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Header Block (*) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -701,9 +708,9 @@ server to client, as in HTTP/2. The PUSH_PROMISE frame defines no flags. The payload consists of: Push ID: -: A 32-bit identifier for the server push request. A push ID is used in push - stream header ({{server-push}}), CANCEL_PUSH frames ({{frame-cancel-push}}), - and PRIORITY frames ({{frame-priority}}). +: A variable-length integer that identifies the server push request. A push ID + is used in push stream header ({{server-push}}), CANCEL_PUSH frames + ({{frame-cancel-push}}), and PRIORITY frames ({{frame-priority}}). Header Block: : HPACK-compressed request headers for the promised response. @@ -743,10 +750,12 @@ administrative actions, like server maintenance. GOAWAY by itself does not close a connection. (Note that clients do not need to send GOAWAY to gracefully close a connection; they simply stop making new requests.) -The GOAWAY frame does not define any flags, and the payload is a QUIC stream -identifier. The GOAWAY frame applies to the connection, not a specific stream. -An endpoint MUST treat a GOAWAY frame on a stream other than the control stream -as a connection error ({{errors}}) of type HTTP_WRONG_STREAM. +The GOAWAY frame does not define any flags, and the payload is a QUIC Stream ID +encoded as a variable-length integer. + +The GOAWAY frame applies to the connection, not a specific stream. An endpoint +MUST treat a GOAWAY frame on a stream other than the control stream as a +connection error ({{errors}}) of type HTTP_WRONG_STREAM. New client requests might already have been sent before the client receives the server's GOAWAY frame. The GOAWAY frame contains the stream identifier of the @@ -841,14 +850,15 @@ sending a MAX_PUSH_ID frame as the server fulfills or cancels server pushes. The MAX_PUSH_ID frame has no defined flags. -The MAX_PUSH_ID frame carries a 32-bit Push ID that identifies the maximum value -for a Push ID that the server can use (see {{frame-push-promise}}). A -MAX_PUSH_ID frame cannot reduce the maximum Push ID; receipt of a MAX_PUSH_ID -that contains a smaller value than previously received MUST be treated as a -connection error of type HTTP_MALFORMED_MAX_PUSH_ID. +The MAX_PUSH_ID frame carries a single variable-length integer that identifies +the maximum value for a Push ID that the server can use (see +{{frame-push-promise}}). A MAX_PUSH_ID frame cannot reduce the maximum Push ID; +receipt of a MAX_PUSH_ID that contains a smaller value than previously received +MUST be treated as a connection error of type HTTP_MALFORMED_MAX_PUSH_ID. -A server MUST treat a MAX_PUSH_ID frame payload that is other than 4 octets in -length as a connection error of type HTTP_MALFORMED_MAX_PUSH_ID. +A server MUST treat a MAX_PUSH_ID frame payload that does not contain a single +variable-length integer as a connection error of type +HTTP_MALFORMED_MAX_PUSH_ID. # Connection Management @@ -966,6 +976,13 @@ applicable to both protocols at once. These departures are noted in this section. +## Streams {#h2-streams} + +HTTP/QUIC permits use of a larger number of streams (2^62-1) then HTTP/2. The +considerations about exhaustion of stream identifier space apply, though the +space is significantly larger such that it is likely that other limits in QUIC +are reached first, such asthe limit on the connection flow control window. + ## HTTP Frame Types {#h2-frames} Many framing concepts from HTTP/2 can be elided away on QUIC, because the @@ -999,7 +1016,13 @@ HEADERS frames. To achieve in-order delivery of priority changes in HTTP/QUIC, PRIORITY frames are sent on the control stream and the PRIORITY section is removed from the HEADERS frame. -Other than this issue, frame type HTTP/2 extensions are typically portable to +Frame type definitions in HTTP/QUIC often use the QUIC variable-length integer +encoding. In particular, Stream IDs use this encoding, which allow for a larger +range of possible values than the encoding used in HTTP/2. Redefinition of the +encoding of extension frame types might be necessary if the encoding includes a +Stream ID. + +Other than these issues, frame type HTTP/2 extensions are typically portable to QUIC simply by replacing Stream 0 in HTTP/2 with Stream 1 in HTTP/QUIC. HTTP/QUIC extensions will not assume ordering, but would not be harmed by ordering, and would be portable to HTTP/2 in the same manner. @@ -1342,7 +1365,7 @@ The original authors of this specification were Robbie Shade and Mike Warres. ## Since draft-ietf-quic-http-06 -Nothing yet. +- Changes for integer encodings in QUIC (#595) ## Since draft-ietf-quic-http-05 From cdae8c393e691843e9e6efc939c2f398e2811312 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 19 Oct 2017 09:52:00 +1100 Subject: [PATCH 08/10] Missed a few fixed-size integers And a nit --- draft-ietf-quic-http.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index f8b7c63ad6..e738d42776 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -358,8 +358,8 @@ allows a server to fulfill promises in the order that best suits its needs. The server push response is conveyed on a push stream. A push stream is a server-initiated stream. A push stream includes a header (see {{fig-push-stream-header}}) that identifies the PUSH_PROMISE that it fulfills. -This header consists of a 32-bit Push ID, which identifies a server push (see -{{frame-push-promise}}). +This header consists of a Push ID, encoded as a variable-length integer. The +Push ID identifies a server push (see {{frame-push-promise}}). ~~~~~ 0 1 2 3 @@ -370,9 +370,9 @@ This header consists of a 32-bit Push ID, which identifies a server push (see ~~~~~ {: #fig-push-stream-header title="Push Stream Header"} -A push stream always starts with a 32-bit Push ID. A client MUST treat -receiving a push stream that contains fewer than 4 octets as a connection error -of type HTTP_MALFORMED_PUSH. +A push stream always starts with a Push ID. A client MUST treat receiving a +push stream that contains a truncated variable-length integer as a connection +error of type HTTP_MALFORMED_PUSH. A server SHOULD use Push IDs sequentially, starting at 0. A client uses the MAX_PUSH_ID frame ({{frame-max-push-id}}) to limit the number of pushes that a @@ -981,7 +981,7 @@ These departures are noted in this section. HTTP/QUIC permits use of a larger number of streams (2^62-1) then HTTP/2. The considerations about exhaustion of stream identifier space apply, though the space is significantly larger such that it is likely that other limits in QUIC -are reached first, such asthe limit on the connection flow control window. +are reached first, such as the limit on the connection flow control window. ## HTTP Frame Types {#h2-frames} From 8aaa5e076bbf745f3d36c1f032fbd641860fe899 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Thu, 19 Oct 2017 11:27:55 +1100 Subject: [PATCH 09/10] More fixed-size integer residue --- draft-ietf-quic-http.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-http.md b/draft-ietf-quic-http.md index e738d42776..adf73f3e83 100644 --- a/draft-ietf-quic-http.md +++ b/draft-ietf-quic-http.md @@ -572,8 +572,9 @@ type HTTP_WRONG_STREAM. The CANCEL_PUSH frame has no defined flags. -The CANCEL_PUSH frame carries a 32-bit Push ID that identifies the server push -that is being cancelled (see {{frame-push-promise}}). +The CANCEL_PUSH frame carries a Push ID encoded as a variable-length integer. +The Push ID identifies the server push that is being cancelled (see +{{frame-push-promise}}). If the client receives a CANCEL_PUSH frame, that frame might identify a Push ID that has not yet been mentioned by a PUSH_PROMISE frame. From 89c99638de57e4bb58c36c6309c7647daf3648f6 Mon Sep 17 00:00:00 2001 From: Mike Bishop Date: Mon, 30 Oct 2017 16:25:13 -0700 Subject: [PATCH 10/10] Redundant duplication is unnecessary --- draft-ietf-quic-transport.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 1a7d5e2a22..3a6afb7c46 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -2426,9 +2426,9 @@ First ACK Block: Gap (repeated): -: A variable-length integer indicating specifying the number of contiguous - unacknowledged packets preceding the packet number one lower than the smallest - in the preceding ACK Block. +: A variable-length integer indicating the number of contiguous unacknowledged + packets preceding the packet number one lower than the smallest in the + preceding ACK Block. ACK Block (repeated):