From 0580d78fb6ed4ed06dd756e02ec401799a892b56 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 27 Aug 2018 18:01:19 +1000 Subject: [PATCH 1/6] Unified ACK frame This takes the design discussed on the list and enacts it. This turns out to be quite simple. Lots of red in this change. This treats ECT(1) as equivalent to unmarked, meaning that QUIC won't be able to use ECT(1) without an extension or revision. That keeps the encoding simpler. Closes #1439. --- draft-ietf-quic-recovery.md | 47 ++++---- draft-ietf-quic-transport.md | 213 ++++++++++------------------------- 2 files changed, 77 insertions(+), 183 deletions(-) diff --git a/draft-ietf-quic-recovery.md b/draft-ietf-quic-recovery.md index a55a92186d..577a3bcc68 100644 --- a/draft-ietf-quic-recovery.md +++ b/draft-ietf-quic-recovery.md @@ -88,14 +88,9 @@ when, and only when, they appear in all capitals, as shown here. Definitions of terms that are used in this document: -ACK frames: - -: ACK frames refer to both ACK and ACK_ECN frames in this - document. - ACK-only: -: Any packet containing only an ACK or ACK_ECN frame. +: Any packet containing only an ACK frame. In-flight: @@ -105,8 +100,7 @@ In-flight: Retransmittable Frames: -: All frames besides ACK, ACK_ECN, or PADDING are considered - retransmittable. +: All frames besides ACK or PADDING are considered retransmittable. Retransmittable Packets: @@ -132,17 +126,17 @@ mechanisms ensure that data and frames that need reliable delivery are acknowledged or declared lost and sent in new packets as necessary. The types of frames contained in a packet affect recovery and congestion control logic: -* All packets are acknowledged, though packets that contain only ACK, - ACK_ECN, and PADDING frames are not acknowledged immediately. +* All packets are acknowledged, though packets that contain only ACK and PADDING + frames are not acknowledged immediately. * Long header packets that contain CRYPTO frames are critical to the performance of the QUIC handshake and use shorter timers for acknowledgement and retransmission. -* Packets that contain only ACK and ACK_ECN frames do not count toward - congestion control limits and are not considered in-flight. Note that this - means PADDING frames cause packets to contribute toward bytes in flight - without directly causing an acknowledgment to be sent. +* Packets that contain only ACK frames do not count toward congestion control + limits and are not considered in-flight. Note that this means PADDING frames + cause packets to contribute toward bytes in flight without directly causing an + acknowledgment to be sent. ## Relevant Differences Between QUIC and TCP @@ -765,6 +759,7 @@ Pseudocode for OnPacketAcked follows: acked_packet.packet_number > largest_sent_before_rto): OnRetransmissionTimeoutVerified( acked_packet.packet_number) + ProcessECN(packet) handshake_count = 0 tlp_count = 0 rto_count = 0 @@ -1063,11 +1058,6 @@ kLossReductionFactor: Variables required to implement the congestion control mechanisms are described in this section. -ecn_ce_counter: -: The highest value reported for the ECN-CE counter by the peer in an ACK_ECN - frame. This variable is used to detect increases in the reported ECN-CE - counter. - bytes_in_flight: : The sum of the size in bytes of all sent packets that contain at least one retransmittable or PADDING frame, and have not been acked or declared @@ -1098,7 +1088,6 @@ variables as follows: bytes_in_flight = 0 end_of_recovery = 0 ssthresh = infinite - ecn_ce_counter = 0 ~~~ ### On Packet Sent @@ -1153,16 +1142,13 @@ detected. Starts a new recovery period and reduces the congestion window. ### Process ECN Information -Invoked when an ACK_ECN frame is received from the peer. +Invoked when a packet is newly acknowledged. This triggers a new congestion +event if the peer indicates that the packet was ECN-CE marked. ~~~ - ProcessECN(ack): - // If the ECN-CE counter reported by the peer has increased, - // this could be a new congestion event. - if (ack.ce_counter > ecn_ce_counter): - ecn_ce_counter = ack.ce_counter - // Start a new congestion event if the last acknowledged - // packet is past the end of the previous recovery epoch. + ProcessECN(packet): + // A ECN-CE marked packet indicates congestion. + if (packet.ce_marked): CongestionEvent(ack.largest_acked_packet) ~~~ @@ -1250,6 +1236,11 @@ This document has no IANA actions. Yet. > **RFC Editor's Note:** Please remove this section prior to > publication of a final version of this document. +## Since draft-ietf-quic-recovery-14 + +- Improve reporting for ECN-CE marked packets (#????) + + ## Since draft-ietf-quic-recovery-13 - Corrected the lack of ssthresh reduction in CongestionEvent pseudocode (#1598) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index ae0b3bdc04..527d731921 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1156,7 +1156,6 @@ document. | 0x10 - 0x17 | STREAM | {{frame-stream}} | | 0x18 | CRYPTO | {{frame-crypto}} | | 0x19 | NEW_TOKEN | {{frame-new-token}} | -| 0x1a | ACK_ECN | {{frame-ack-ecn}} | {: #frame-types title="Frame Types"} All QUIC frames are idempotent. That is, a valid frame does not cause @@ -1875,46 +1874,20 @@ Congestion Experienced (CE) codepoint set by a network device that is experiencing congestion. On receiving a packet with an ECT or CE codepoint, an endpoint that can access -the IP ECN codepoints increases the corresponding ECT(0), ECT(1), or CE count, -and includes these counters in subsequent (see {{processing-and-ack}}) ACK_ECN -frames (see {{frame-ack-ecn}}). +the IP ECN codepoints records the markings for that packet. This information is +reported in ACK frames (see {{processing-and-ack}}). Packets bearing ECT(1) are +reported as though they were not marked. A packet detected by a receiver as a duplicate does not affect the receiver's -local ECN codepoint counts; see ({{security-ecn}}) for relevant security +local ECN codepoint reporting; see ({{security-ecn}}) for relevant security concerns. -If an endpoint receives a packet without an ECT or CE codepoint, it responds per -{{processing-and-ack}} with an ACK frame. - If an endpoint does not have access to received ECN codepoints, it acknowledges -received packets per {{processing-and-ack}} with an ACK frame. - -If a packet sent with an ECT codepoint is newly acknowledged by the peer in an -ACK frame, the endpoint stops setting ECT codepoints in subsequent packets, with -the expectation that either the network or the peer no longer supports ECN. - -To protect the connection from arbitrary corruption of ECN codepoints by the -network, an endpoint verifies the following when an ACK_ECN frame is received: - -* The increase in ECT(0) and ECT(1) counters MUST be at least the number of - packets newly acknowledged that were sent with the corresponding codepoint. - -* The total increase in ECT(0), ECT(1), and CE counters reported in the ACK_ECN - frame MUST be at least the total number of packets newly acknowledged in this - ACK_ECN frame. - -An endpoint could miss acknowledgements for a packet when ACK frames are lost. -It is therefore possible for the total increase in ECT(0), ECT(1), and CE -counters to be greater than the number of packets acknowledged in an ACK frame. -When this happens, the local reference counts MUST be increased to match the -counters in the ACK frame. - -Upon successful verification, an endpoint continues to set ECT codepoints in -subsequent packets with the expectation that the path is ECN-capable. +all received packets as though they were not marked. -If verification fails, then the endpoint ceases setting ECT codepoints in -subsequent packets with the expectation that either the network or the peer does -not support ECN. +If a packet sent with an ECT codepoint is newly acknowledged by the peer as +unmarked, the endpoint stops setting ECT codepoints in subsequent packets, with +the expectation that either the network path or peer no longer supports ECN. If an endpoint sets ECT codepoints on outgoing packets and encounters a retransmission timeout due to the absence of acknowledgments from the peer (see @@ -3281,7 +3254,13 @@ An ACK frame is shown below. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Block Count (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Blocks (*) ... +| ACK Block 1 (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| ACK Block 2 (i) ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| ... ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +| ACK Block N (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ {: #ack-format title="ACK Frame Format"} @@ -3309,103 +3288,70 @@ ACK Delay: ACK Block Count: -: A variable-length integer specifying the number of Additional ACK Block (and - Gap) fields after the First ACK Block. +: A variable-length integer specifying the number of ACK Blocks in addition to + the first. A value of 0 indicates that there is only one ACK Block. ACK Blocks: -: Contains one or more blocks of packet numbers which have been successfully - received, see {{ack-block-section}}. +: An ACK block is encoded as a variable-length integer. The encoding of the ACK + Block is described more in {{ack-blocks}}. -### ACK Block Section {#ack-block-section} +### ACK Blocks {#ack-blocks} -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. +Each ACK Block in an ACK frame describes a contiguous range of packets, as well +as the observed type of the packets in that range. Each range of packets is +attributed a type, which is encoded into the two least significant bits of the +decoded variable-length integer value. The size of the range is encoded into +the remainder of the value. -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. +The two least significant bits of the decoded value of the ACK Block describe +the type. That is, the type of an ACK block is found by: -~~~ - 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 (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Gap (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Additional ACK Block (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Gap (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Additional ACK Block (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Gap (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| Additional ACK Block (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -~~~ -{: #ack-block-format title="ACK Block Section"} +``` +ack_type_i = decode_varint() & 3 +``` -Each ACK Block acknowledges a contiguous range of packets by indicating the -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, -given a largest packet number for the ACK, the smallest value is determined by -the formula: +The four types of ACK Block are: -~~~ - smallest = largest - ack_block -~~~ +Gap (0): -The range of packets that are acknowledged by the ACK block include the range -from the smallest packet number to the largest, inclusive. +: A gap describes a range of packets that are not acknowledged. This does not + mean that these packets were not received, but that this ACK frame does not + include an acknowledgment for those packets. -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. +Unmarked (1): -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. +: Unmarked packets are those packets that are acknowledged, but for which the + ECN marking is either not present, ECT(1), or unknown. -The value of the Gap field establishes the largest packet number value for the -ACK block that follows the gap using the following formula: +ECT(0) Marked (2): -~~~ - 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_ENCODING_ERROR indicating an error in an ACK frame. +: Packets that are ECT(0) marked are acknowledged using a type of 3. -The fields in the ACK Block Section are: +ECN-CE Marked (3): -First ACK Block: +: Packets that are ECN-CE marked are acknowledged using a type of 3. -: A variable-length integer indicating the number of contiguous packets - preceding the Largest Acknowledged that are being acknowledged. +The range of acknowledged values in each ACK Block is inclusive of its largest +value and is described in numerically decreasing order. Each ACK Block includes +at least one value; a encoded value of 0 indicates that the range contains one +packet number. Each range is described starts at one lower than the minimum +value from the previous range. The first ACK Block starts with the Largest +Acknowledged packet number and describes a range up and including that packet +number. Thus, the ranges of packets covered by each ACK Block can found with: -Gap (repeated): +``` +ack_range_i = [ low: largest_i - (decode_varint() >> 2), + high: largest_i ] +ack_largest_i+1 = ack_range_i[low] - 1 +``` -: 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. +For example, the hex sequence 0x00 indicates a gap of one packet, the sequence +0x05 indicates two unmarked packets, the sequence 0x4037 indicates that there +are 53 packets with ECN-CE markings, and the sequence 0x80b1d34a indicates that +there are 5826980 packets that are ECT(1) marked. -ACK Block (repeated): - -: A variable-length integer indicating the number of contiguous acknowledged - packets preceding the largest packet number, as determined by the - preceding Gap. ### Sending ACK Frames @@ -3456,49 +3402,6 @@ Endpoints SHOULD send acknowledgments for packets containing CRYPTO frames with a reduced delay; see Section 4.3.1 of {{QUIC-RECOVERY}}. -## ACK_ECN Frame {#frame-ack-ecn} - -The ACK_ECN frame (type=0x1a) is used by an endpoint that provides ECN feedback -for packets received with ECN codepoints of ECT(0), ECT(1), or CE in the -packet's IP header. - -~~~ - 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 Delay (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ECT(0) Count (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ECT(1) Count (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ECN-CE Count (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Block Count (i) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Blocks (*) ... -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -~~~ -{: #ACN_ECN_FRAME_FORMAT title="ACK_ECN Frame Format"} - -An ACK_ECN frame contains all the elements of the ACK frame ({{frame-ack}}) with -the addition of three counts following the ACK Delay field. - -ECT(0) Count: -: A variable-length integer representing the total number packets received with - the ECT(0) codepoint. - -ECT(1) Count: -: A variable-length integer representing the total number packets received with - the ECT(1) codepoint. - -CE Count: -: A variable-length integer representing the total number packets received with - the CE codepoint. - - ## PATH_CHALLENGE Frame {#frame-path-challenge} Endpoints can use PATH_CHALLENGE frames (type=0x0e) to check reachability to the From 12f063a04fc50258b9f0ffd6575e30de82613903 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Mon, 27 Aug 2018 19:48:31 +1000 Subject: [PATCH 2/6] ECT(0) = Type 2 --- draft-ietf-quic-transport.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 527d731921..db717b3216 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3325,9 +3325,9 @@ Unmarked (1): : Unmarked packets are those packets that are acknowledged, but for which the ECN marking is either not present, ECT(1), or unknown. -ECT(0) Marked (2): +ECT Marked (2): -: Packets that are ECT(0) marked are acknowledged using a type of 3. +: Packets that are ECT(0) marked are acknowledged using a type of 2. ECN-CE Marked (3): From ac7659251f6fd46c0f08683fc1e7eb9dcacd8a43 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Tue, 28 Aug 2018 09:55:24 +1000 Subject: [PATCH 3/6] Editorial feedback --- draft-ietf-quic-transport.md | 43 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index db717b3216..7fcd26459a 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -1866,7 +1866,8 @@ provide feedback about ECN markings received (if accessible). To verify both that a path supports ECN and the peer can provide ECN feedback, an endpoint MUST set the ECT(0) codepoint in the IP header of all outgoing -packets {{!RFC8311}}. +packets {{!RFC8311}}. Endpoints can use a different default marking, but this +needs to be negotiated. If an ECT codepoint set in the IP header is not corrupted by a network device, then a received packet contains either the codepoint sent by the peer or the @@ -1875,8 +1876,10 @@ experiencing congestion. On receiving a packet with an ECT or CE codepoint, an endpoint that can access the IP ECN codepoints records the markings for that packet. This information is -reported in ACK frames (see {{processing-and-ack}}). Packets bearing ECT(1) are -reported as though they were not marked. +reported in ACK frames (see {{processing-and-ack}}). Packets bearing an ECT +marking other than the negotiated type are reported as though they were not +marked. That is, absent any different negotiation, ECT(1) marked packets are +acknowledged as unmarked. A packet detected by a receiver as a duplicate does not affect the receiver's local ECN codepoint reporting; see ({{security-ecn}}) for relevant security @@ -3254,13 +3257,13 @@ An ACK frame is shown below. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ACK Block Count (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Block 1 (i) ... +| ACK Block 1 (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Block 2 (i) ... +| ACK Block 2 (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -| ACK Block N (i) ... +| ACK Block N (i) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~~~ {: #ack-format title="ACK Frame Format"} @@ -3293,7 +3296,7 @@ ACK Block Count: ACK Blocks: -: An ACK block is encoded as a variable-length integer. The encoding of the ACK +: An ACK Block is encoded as a variable-length integer. The encoding of the ACK Block is described more in {{ack-blocks}}. @@ -3309,7 +3312,9 @@ The two least significant bits of the decoded value of the ACK Block describe the type. That is, the type of an ACK block is found by: ``` -ack_type_i = decode_varint() & 3 +ack_block_i = decode_varint() +ack_type_i = ack_block_i & 3 +ack_size_i = ack_block_i >> 2 ``` The four types of ACK Block are: @@ -3327,23 +3332,25 @@ Unmarked (1): ECT Marked (2): -: Packets that are ECT(0) marked are acknowledged using a type of 2. +: Packets that are marked with the negotiated ECT marking are acknowledged using + a type of 2. ECN-CE Marked (3): : Packets that are ECN-CE marked are acknowledged using a type of 3. -The range of acknowledged values in each ACK Block is inclusive of its largest -value and is described in numerically decreasing order. Each ACK Block includes -at least one value; a encoded value of 0 indicates that the range contains one -packet number. Each range is described starts at one lower than the minimum -value from the previous range. The first ACK Block starts with the Largest -Acknowledged packet number and describes a range up and including that packet -number. Thus, the ranges of packets covered by each ACK Block can found with: +The range of acknowledged packet numbers in each ACK Block is inclusive of its +largest packet number and is described in numerically decreasing order. Each +ACK Block includes at least one value; a encoded value of 0 indicates that the +range contains one packet number. Each range is described starts at one lower +than the minimum value from the previous range. The first ACK Block starts with +the Largest Acknowledged packet number and describes a range up and including +that packet number. Thus, ranges of packet numbers covered by each ACK Block +can found with: ``` -ack_range_i = [ low: largest_i - (decode_varint() >> 2), - high: largest_i ] +ack_range_i = { low: largest_i - ack_size_i, + high: largest_i } ack_largest_i+1 = ack_range_i[low] - 1 ``` From 8ff41ed9befc27cf2d11a84c919f1be3b1eb0e6d Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 29 Aug 2018 09:48:53 +1000 Subject: [PATCH 4/6] Refactor recovery draft to remove ProcessECN --- draft-ietf-quic-recovery.md | 51 ++++++++++++++----------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/draft-ietf-quic-recovery.md b/draft-ietf-quic-recovery.md index 577a3bcc68..bd733aa478 100644 --- a/draft-ietf-quic-recovery.md +++ b/draft-ietf-quic-recovery.md @@ -704,16 +704,11 @@ Pseudocode for OnAckReceived and UpdateRtt follow: UpdateRtt(latest_rtt, ack.ack_delay) // Find all newly acked packets. for acked_packet in DetermineNewlyAckedPackets(): - OnPacketAcked(acked_packet.packet_number) + OnPacketAcked(acked_packet, largest_acked_packet) DetectLostPackets(ack.largest_acked_packet) SetLossDetectionTimer() - // Process ECN information if present. - if (ACK frame contains ECN information): - ProcessECN(ack) - - UpdateRtt(latest_rtt, ack_delay): // min_rtt ignores ack delay. min_rtt = min(min_rtt, latest_rtt) @@ -740,8 +735,9 @@ When a packet is acked for the first time, the following OnPacketAcked function is called. Note that a single ACK frame may newly acknowledge several packets. OnPacketAcked must be called once for each of these newly acked packets. -OnPacketAcked takes one parameter, acked_packet, which is the struct of the -newly acked packet. +OnPacketAcked takes the acknowledged packet, acked_packet, which is the struct +of the newly acked packet. It also takes the largest acknowledged packet, which +is used to mark the start of a congestion event if the packet is ECN-CE marked. If this is the first acknowledgement following RTO, check if the smallest newly acknowledged packet is one sent by the RTO, and if so, inform congestion control @@ -750,7 +746,7 @@ of a verified RTO, similar to F-RTO {{?RFC5682}}. Pseudocode for OnPacketAcked follows: ~~~ - OnPacketAcked(acked_packet): + OnPacketAcked(acked_packet, largest_acked): if (!acked_packet.is_ack_only): OnPacketAckedCC(acked_packet) // If a packet sent prior to RTO was acked, then the RTO @@ -759,7 +755,11 @@ Pseudocode for OnPacketAcked follows: acked_packet.packet_number > largest_sent_before_rto): OnRetransmissionTimeoutVerified( acked_packet.packet_number) - ProcessECN(packet) + + // A ECN-CE marked packet indicates congestion. + if (acked_packet.ce_marked): + CongestionEvent(largest_acked) + handshake_count = 0 tlp_count = 0 rto_count = 0 @@ -976,16 +976,16 @@ congestion window. ## Recovery Period -Recovery is a period of time beginning with detection of a lost packet or an -increase in the ECN-CE counter. Because QUIC retransmits stream data and control -frames, not packets, it defines the end of recovery as a packet sent after the -start of recovery being acknowledged. This is slightly different from TCP's -definition of recovery, which ends when the lost packet that started recovery is -acknowledged. +Recovery is a period of time beginning with detection of a lost packet or +receipt of an acknowledgment for an ECN-CE marked packet. Because QUIC +retransmits stream data and control frames, not packets, it defines the end of +recovery as a packet sent after the start of recovery being acknowledged. This +is slightly different from TCP's definition of recovery, which ends when the +lost packet that started recovery is acknowledged. The recovery period limits congestion window reduction to once per round trip. During recovery, the congestion window remains unchanged irrespective of new -losses or increases in the ECN-CE counter. +losses or acknowledgment of ECN-CE marked packets. ## Tail Loss Probe @@ -1126,8 +1126,8 @@ acked_packet from sent_packets. ### On New Congestion Event -Invoked from ProcessECN and OnPacketsLost when a new congestion event is -detected. Starts a new recovery period and reduces the congestion window. +Invoked when a new congestion event is detected. Starts a new recovery period +and reduces the congestion window. ~~~ CongestionEvent(packet_number): @@ -1140,19 +1140,6 @@ detected. Starts a new recovery period and reduces the congestion window. ssthresh = congestion_window ~~~ -### Process ECN Information - -Invoked when a packet is newly acknowledged. This triggers a new congestion -event if the peer indicates that the packet was ECN-CE marked. - -~~~ - ProcessECN(packet): - // A ECN-CE marked packet indicates congestion. - if (packet.ce_marked): - CongestionEvent(ack.largest_acked_packet) -~~~ - - ### On Packets Lost Invoked by loss detection from DetectLostPackets when new packets From 78cd18f2f4183947e602d10bf9e9a445e88a69d3 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 29 Aug 2018 09:49:14 +1000 Subject: [PATCH 5/6] Try to clean up description of ACK Blocks --- draft-ietf-quic-transport.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index 7fcd26459a..cf4fc6d5de 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3302,14 +3302,16 @@ ACK Blocks: ### ACK Blocks {#ack-blocks} -Each ACK Block in an ACK frame describes a contiguous range of packets, as well -as the observed type of the packets in that range. Each range of packets is -attributed a type, which is encoded into the two least significant bits of the -decoded variable-length integer value. The size of the range is encoded into -the remainder of the value. - -The two least significant bits of the decoded value of the ACK Block describe -the type. That is, the type of an ACK block is found by: +Each ACK Block in an ACK frame describes a contiguous range of packets. Each +ACK Block includes the size of the block and whether the range represents +unacknowledged packets (a gap), or the type of ECN marking the recipient +observed for packets that are acknowledged. + +The acknowledgment type and size of the range are packed into a single +variable-length integer. The two least significant bits of the decoded value +encode the acknowledgment type. The size of the range is found by +right-shifting the value by two bits. That is, an ACK block is decoded by +decoding the integer and splitting it into a type and size: ``` ack_block_i = decode_varint() From 2ebf211e28aef7a7805042e6c4beec0774e71248 Mon Sep 17 00:00:00 2001 From: Martin Thomson Date: Wed, 29 Aug 2018 09:52:55 +1000 Subject: [PATCH 6/6] Gee, I'm glad no one checked these... --- draft-ietf-quic-transport.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/draft-ietf-quic-transport.md b/draft-ietf-quic-transport.md index cf4fc6d5de..a4cdbfd92f 100644 --- a/draft-ietf-quic-transport.md +++ b/draft-ietf-quic-transport.md @@ -3347,8 +3347,9 @@ ACK Block includes at least one value; a encoded value of 0 indicates that the range contains one packet number. Each range is described starts at one lower than the minimum value from the previous range. The first ACK Block starts with the Largest Acknowledged packet number and describes a range up and including -that packet number. Thus, ranges of packet numbers covered by each ACK Block -can found with: +that packet number. + +Thus, ranges of packet numbers covered by each ACK Block can found with: ``` ack_range_i = { low: largest_i - ack_size_i, @@ -3358,8 +3359,8 @@ ack_largest_i+1 = ack_range_i[low] - 1 For example, the hex sequence 0x00 indicates a gap of one packet, the sequence 0x05 indicates two unmarked packets, the sequence 0x4037 indicates that there -are 53 packets with ECN-CE markings, and the sequence 0x80b1d34a indicates that -there are 5826980 packets that are ECT(1) marked. +are 14 packets with ECN-CE markings, and the sequence 0x80b1d34a indicates that +there are 2913491 packets that are ECT(1) marked. ### Sending ACK Frames