| draft-ietf-quic-recovery-19.txt | draft-ietf-quic-recovery-20.txt | |||
|---|---|---|---|---|
| QUIC J. Iyengar, Ed. | QUIC J. Iyengar, Ed. | |||
| Internet-Draft Fastly | Internet-Draft Fastly | |||
| Intended status: Standards Track I. Swett, Ed. | Intended status: Standards Track I. Swett, Ed. | |||
| Expires: September 12, 2019 Google | Expires: October 25, 2019 Google | |||
| March 11, 2019 | April 23, 2019 | |||
| QUIC Loss Detection and Congestion Control | QUIC Loss Detection and Congestion Control | |||
| draft-ietf-quic-recovery-19 | draft-ietf-quic-recovery-20 | |||
| Abstract | Abstract | |||
| This document describes loss detection and congestion control | This document describes loss detection and congestion control | |||
| mechanisms for QUIC. | mechanisms for QUIC. | |||
| Note to Readers | Note to Readers | |||
| Discussion of this draft takes place on the QUIC working group | Discussion of this draft takes place on the QUIC working group | |||
| mailing list (quic@ietf.org), which is archived at | mailing list (quic@ietf.org), which is archived at | |||
| skipping to change at page 1, line 42 ¶ | skipping to change at page 1, line 42 ¶ | |||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
| working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| This Internet-Draft will expire on September 12, 2019. | This Internet-Draft will expire on October 25, 2019. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2019 IETF Trust and the persons identified as the | Copyright (c) 2019 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents | Provisions Relating to IETF Documents | |||
| (https://trustee.ietf.org/license-info) in effect on the date of | (https://trustee.ietf.org/license-info) in effect on the date of | |||
| publication of this document. Please review these documents | publication of this document. Please review these documents | |||
| skipping to change at page 2, line 24 ¶ | skipping to change at page 2, line 24 ¶ | |||
| Table of Contents | Table of Contents | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 | |||
| 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4 | 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 4 | |||
| 3. Design of the QUIC Transmission Machinery . . . . . . . . . . 5 | 3. Design of the QUIC Transmission Machinery . . . . . . . . . . 5 | |||
| 3.1. Relevant Differences Between QUIC and TCP . . . . . . . . 5 | 3.1. Relevant Differences Between QUIC and TCP . . . . . . . . 5 | |||
| 3.1.1. Separate Packet Number Spaces . . . . . . . . . . . . 6 | 3.1.1. Separate Packet Number Spaces . . . . . . . . . . . . 6 | |||
| 3.1.2. Monotonically Increasing Packet Numbers . . . . . . . 6 | 3.1.2. Monotonically Increasing Packet Numbers . . . . . . . 6 | |||
| 3.1.3. No Reneging . . . . . . . . . . . . . . . . . . . . . 6 | 3.1.3. No Reneging . . . . . . . . . . . . . . . . . . . . . 6 | |||
| 3.1.4. More ACK Ranges . . . . . . . . . . . . . . . . . . . 6 | 3.1.4. More ACK Ranges . . . . . . . . . . . . . . . . . . . 7 | |||
| 3.1.5. Explicit Correction For Delayed ACKs . . . . . . . . 7 | 3.1.5. Explicit Correction For Delayed Acknowledgements . . 7 | |||
| 4. Generating Acknowledgements . . . . . . . . . . . . . . . . . 7 | 4. Generating Acknowledgements . . . . . . . . . . . . . . . . . 7 | |||
| 4.1. Crypto Handshake Data . . . . . . . . . . . . . . . . . . 8 | 4.1. Crypto Handshake Data . . . . . . . . . . . . . . . . . . 7 | |||
| 4.2. ACK Ranges . . . . . . . . . . . . . . . . . . . . . . . 8 | 4.2. ACK Ranges . . . . . . . . . . . . . . . . . . . . . . . 8 | |||
| 4.3. Receiver Tracking of ACK Frames . . . . . . . . . . . . . 8 | 4.3. Receiver Tracking of ACK Frames . . . . . . . . . . . . . 8 | |||
| 5. Computing the RTT estimate . . . . . . . . . . . . . . . . . 8 | 4.4. Measuring and Reporting Host Delay . . . . . . . . . . . 8 | |||
| 6. Loss Detection . . . . . . . . . . . . . . . . . . . . . . . 9 | 5. Estimating the Round-Trip Time . . . . . . . . . . . . . . . 9 | |||
| 6.1. Acknowledgement-based Detection . . . . . . . . . . . . . 9 | 5.1. Generating RTT samples . . . . . . . . . . . . . . . . . 9 | |||
| 6.1.1. Packet Threshold . . . . . . . . . . . . . . . . . . 10 | 5.2. Estimating min_rtt . . . . . . . . . . . . . . . . . . . 10 | |||
| 6.1.2. Time Threshold . . . . . . . . . . . . . . . . . . . 10 | 5.3. Estimating smoothed_rtt and rttvar . . . . . . . . . . . 10 | |||
| 6.2. Crypto Retransmission Timeout . . . . . . . . . . . . . . 11 | 6. Loss Detection . . . . . . . . . . . . . . . . . . . . . . . 11 | |||
| 6.2.1. Retry and Version Negotiation . . . . . . . . . . . . 12 | 6.1. Acknowledgement-based Detection . . . . . . . . . . . . . 11 | |||
| 6.2.2. Discarding Keys and Packet State . . . . . . . . . . 12 | 6.1.1. Packet Threshold . . . . . . . . . . . . . . . . . . 12 | |||
| 6.3. Probe Timeout . . . . . . . . . . . . . . . . . . . . . . 12 | 6.1.2. Time Threshold . . . . . . . . . . . . . . . . . . . 12 | |||
| 6.3.1. Computing PTO . . . . . . . . . . . . . . . . . . . . 13 | 6.2. Crypto Retransmission Timeout . . . . . . . . . . . . . . 13 | |||
| 6.3.2. Sending Probe Packets . . . . . . . . . . . . . . . . 13 | 6.2.1. Retry and Version Negotiation . . . . . . . . . . . . 14 | |||
| 6.3.3. Loss Detection . . . . . . . . . . . . . . . . . . . 14 | 6.2.2. Discarding Keys and Packet State . . . . . . . . . . 14 | |||
| 6.4. Discussion . . . . . . . . . . . . . . . . . . . . . . . 14 | 6.3. Probe Timeout . . . . . . . . . . . . . . . . . . . . . . 15 | |||
| 7. Congestion Control . . . . . . . . . . . . . . . . . . . . . 15 | 6.3.1. Computing PTO . . . . . . . . . . . . . . . . . . . . 15 | |||
| 7.1. Explicit Congestion Notification . . . . . . . . . . . . 15 | 6.3.2. Sending Probe Packets . . . . . . . . . . . . . . . . 16 | |||
| 7.2. Slow Start . . . . . . . . . . . . . . . . . . . . . . . 15 | 6.3.3. Loss Detection . . . . . . . . . . . . . . . . . . . 17 | |||
| 7.3. Congestion Avoidance . . . . . . . . . . . . . . . . . . 15 | 6.4. Discussion . . . . . . . . . . . . . . . . . . . . . . . 17 | |||
| 7.4. Recovery Period . . . . . . . . . . . . . . . . . . . . . 16 | 7. Congestion Control . . . . . . . . . . . . . . . . . . . . . 17 | |||
| 7.5. Ignoring Loss of Undecryptable Packets . . . . . . . . . 16 | 7.1. Explicit Congestion Notification . . . . . . . . . . . . 17 | |||
| 7.6. Probe Timeout . . . . . . . . . . . . . . . . . . . . . . 16 | 7.2. Slow Start . . . . . . . . . . . . . . . . . . . . . . . 18 | |||
| 7.7. Persistent Congestion . . . . . . . . . . . . . . . . . . 16 | 7.3. Congestion Avoidance . . . . . . . . . . . . . . . . . . 18 | |||
| 7.8. Pacing . . . . . . . . . . . . . . . . . . . . . . . . . 17 | 7.4. Recovery Period . . . . . . . . . . . . . . . . . . . . . 18 | |||
| 7.9. Sending data after an idle period . . . . . . . . . . . . 18 | 7.5. Ignoring Loss of Undecryptable Packets . . . . . . . . . 18 | |||
| 7.10. Application Limited Sending . . . . . . . . . . . . . . . 18 | 7.6. Probe Timeout . . . . . . . . . . . . . . . . . . . . . . 18 | |||
| 8. Security Considerations . . . . . . . . . . . . . . . . . . . 18 | 7.7. Persistent Congestion . . . . . . . . . . . . . . . . . . 19 | |||
| 8.1. Congestion Signals . . . . . . . . . . . . . . . . . . . 18 | 7.8. Pacing . . . . . . . . . . . . . . . . . . . . . . . . . 20 | |||
| 8.2. Traffic Analysis . . . . . . . . . . . . . . . . . . . . 19 | 7.9. Under-utilizing the Congestion Window . . . . . . . . . . 20 | |||
| 8.3. Misreporting ECN Markings . . . . . . . . . . . . . . . . 19 | 8. Security Considerations . . . . . . . . . . . . . . . . . . . 21 | |||
| 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19 | 8.1. Congestion Signals . . . . . . . . . . . . . . . . . . . 21 | |||
| 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 19 | 8.2. Traffic Analysis . . . . . . . . . . . . . . . . . . . . 21 | |||
| 10.1. Normative References . . . . . . . . . . . . . . . . . . 19 | 8.3. Misreporting ECN Markings . . . . . . . . . . . . . . . . 21 | |||
| 10.2. Informative References . . . . . . . . . . . . . . . . . 20 | 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 22 | |||
| 10.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 21 | 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 22 | |||
| Appendix A. Loss Recovery Pseudocode . . . . . . . . . . . . . . 22 | 10.1. Normative References . . . . . . . . . . . . . . . . . . 22 | |||
| A.1. Tracking Sent Packets . . . . . . . . . . . . . . . . . . 22 | 10.2. Informative References . . . . . . . . . . . . . . . . . 22 | |||
| A.1.1. Sent Packet Fields . . . . . . . . . . . . . . . . . 22 | 10.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 24 | |||
| A.2. Constants of interest . . . . . . . . . . . . . . . . . . 22 | Appendix A. Loss Recovery Pseudocode . . . . . . . . . . . . . . 24 | |||
| A.3. Variables of interest . . . . . . . . . . . . . . . . . . 23 | A.1. Tracking Sent Packets . . . . . . . . . . . . . . . . . . 24 | |||
| A.4. Initialization . . . . . . . . . . . . . . . . . . . . . 24 | A.1.1. Sent Packet Fields . . . . . . . . . . . . . . . . . 24 | |||
| A.5. On Sending a Packet . . . . . . . . . . . . . . . . . . . 24 | A.2. Constants of interest . . . . . . . . . . . . . . . . . . 25 | |||
| A.6. On Receiving an Acknowledgment . . . . . . . . . . . . . 25 | A.3. Variables of interest . . . . . . . . . . . . . . . . . . 25 | |||
| A.7. On Packet Acknowledgment . . . . . . . . . . . . . . . . 27 | A.4. Initialization . . . . . . . . . . . . . . . . . . . . . 26 | |||
| A.8. Setting the Loss Detection Timer . . . . . . . . . . . . 27 | A.5. On Sending a Packet . . . . . . . . . . . . . . . . . . . 27 | |||
| A.9. On Timeout . . . . . . . . . . . . . . . . . . . . . . . 29 | A.6. On Receiving an Acknowledgment . . . . . . . . . . . . . 27 | |||
| A.10. Detecting Lost Packets . . . . . . . . . . . . . . . . . 29 | A.7. On Packet Acknowledgment . . . . . . . . . . . . . . . . 29 | |||
| Appendix B. Congestion Control Pseudocode . . . . . . . . . . . 30 | A.8. Setting the Loss Detection Timer . . . . . . . . . . . . 29 | |||
| B.1. Constants of interest . . . . . . . . . . . . . . . . . . 30 | A.9. On Timeout . . . . . . . . . . . . . . . . . . . . . . . 31 | |||
| B.2. Variables of interest . . . . . . . . . . . . . . . . . . 31 | A.10. Detecting Lost Packets . . . . . . . . . . . . . . . . . 31 | |||
| B.3. Initialization . . . . . . . . . . . . . . . . . . . . . 32 | Appendix B. Congestion Control Pseudocode . . . . . . . . . . . 32 | |||
| B.4. On Packet Sent . . . . . . . . . . . . . . . . . . . . . 32 | B.1. Constants of interest . . . . . . . . . . . . . . . . . . 32 | |||
| B.5. On Packet Acknowledgement . . . . . . . . . . . . . . . . 32 | B.2. Variables of interest . . . . . . . . . . . . . . . . . . 33 | |||
| B.6. On New Congestion Event . . . . . . . . . . . . . . . . . 33 | B.3. Initialization . . . . . . . . . . . . . . . . . . . . . 34 | |||
| B.7. Process ECN Information . . . . . . . . . . . . . . . . . 33 | B.4. On Packet Sent . . . . . . . . . . . . . . . . . . . . . 34 | |||
| B.8. On Packets Lost . . . . . . . . . . . . . . . . . . . . . 33 | B.5. On Packet Acknowledgement . . . . . . . . . . . . . . . . 34 | |||
| Appendix C. Change Log . . . . . . . . . . . . . . . . . . . . . 34 | B.6. On New Congestion Event . . . . . . . . . . . . . . . . . 35 | |||
| C.1. Since draft-ietf-quic-recovery-18 . . . . . . . . . . . . 34 | B.7. Process ECN Information . . . . . . . . . . . . . . . . . 35 | |||
| C.2. Since draft-ietf-quic-recovery-17 . . . . . . . . . . . . 35 | B.8. On Packets Lost . . . . . . . . . . . . . . . . . . . . . 36 | |||
| C.3. Since draft-ietf-quic-recovery-16 . . . . . . . . . . . . 35 | Appendix C. Change Log . . . . . . . . . . . . . . . . . . . . . 36 | |||
| C.4. Since draft-ietf-quic-recovery-14 . . . . . . . . . . . . 36 | C.1. Since draft-ietf-quic-recovery-19 . . . . . . . . . . . . 36 | |||
| C.5. Since draft-ietf-quic-recovery-13 . . . . . . . . . . . . 36 | C.2. Since draft-ietf-quic-recovery-18 . . . . . . . . . . . . 37 | |||
| C.6. Since draft-ietf-quic-recovery-12 . . . . . . . . . . . . 36 | C.3. Since draft-ietf-quic-recovery-17 . . . . . . . . . . . . 37 | |||
| C.7. Since draft-ietf-quic-recovery-11 . . . . . . . . . . . . 36 | C.4. Since draft-ietf-quic-recovery-16 . . . . . . . . . . . . 38 | |||
| C.8. Since draft-ietf-quic-recovery-10 . . . . . . . . . . . . 36 | C.5. Since draft-ietf-quic-recovery-14 . . . . . . . . . . . . 38 | |||
| C.9. Since draft-ietf-quic-recovery-09 . . . . . . . . . . . . 37 | C.6. Since draft-ietf-quic-recovery-13 . . . . . . . . . . . . 38 | |||
| C.10. Since draft-ietf-quic-recovery-08 . . . . . . . . . . . . 37 | C.7. Since draft-ietf-quic-recovery-12 . . . . . . . . . . . . 39 | |||
| C.11. Since draft-ietf-quic-recovery-07 . . . . . . . . . . . . 37 | C.8. Since draft-ietf-quic-recovery-11 . . . . . . . . . . . . 39 | |||
| C.12. Since draft-ietf-quic-recovery-06 . . . . . . . . . . . . 37 | C.9. Since draft-ietf-quic-recovery-10 . . . . . . . . . . . . 39 | |||
| C.13. Since draft-ietf-quic-recovery-05 . . . . . . . . . . . . 37 | C.10. Since draft-ietf-quic-recovery-09 . . . . . . . . . . . . 39 | |||
| C.14. Since draft-ietf-quic-recovery-04 . . . . . . . . . . . . 37 | C.11. Since draft-ietf-quic-recovery-08 . . . . . . . . . . . . 39 | |||
| C.15. Since draft-ietf-quic-recovery-03 . . . . . . . . . . . . 37 | C.12. Since draft-ietf-quic-recovery-07 . . . . . . . . . . . . 39 | |||
| C.16. Since draft-ietf-quic-recovery-02 . . . . . . . . . . . . 37 | C.13. Since draft-ietf-quic-recovery-06 . . . . . . . . . . . . 40 | |||
| C.17. Since draft-ietf-quic-recovery-01 . . . . . . . . . . . . 38 | C.14. Since draft-ietf-quic-recovery-05 . . . . . . . . . . . . 40 | |||
| C.18. Since draft-ietf-quic-recovery-00 . . . . . . . . . . . . 38 | C.15. Since draft-ietf-quic-recovery-04 . . . . . . . . . . . . 40 | |||
| C.19. Since draft-iyengar-quic-loss-recovery-01 . . . . . . . . 38 | C.16. Since draft-ietf-quic-recovery-03 . . . . . . . . . . . . 40 | |||
| Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 38 | C.17. Since draft-ietf-quic-recovery-02 . . . . . . . . . . . . 40 | |||
| Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 38 | C.18. Since draft-ietf-quic-recovery-01 . . . . . . . . . . . . 40 | |||
| C.19. Since draft-ietf-quic-recovery-00 . . . . . . . . . . . . 40 | ||||
| C.20. Since draft-iyengar-quic-loss-recovery-01 . . . . . . . . 40 | ||||
| Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 41 | ||||
| Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 41 | ||||
| 1. Introduction | 1. Introduction | |||
| QUIC is a new multiplexed and secure transport atop UDP. QUIC builds | QUIC is a new multiplexed and secure transport atop UDP. QUIC builds | |||
| on decades of transport and security experience, and implements | on decades of transport and security experience, and implements | |||
| mechanisms that make it attractive as a modern general-purpose | mechanisms that make it attractive as a modern general-purpose | |||
| transport. The QUIC protocol is described in [QUIC-TRANSPORT]. | transport. The QUIC protocol is described in [QUIC-TRANSPORT]. | |||
| QUIC implements the spirit of existing TCP loss recovery mechanisms, | QUIC implements the spirit of existing TCP loss recovery mechanisms, | |||
| described in RFCs, various Internet-drafts, and also those prevalent | described in RFCs, various Internet-drafts, and also those prevalent | |||
| skipping to change at page 7, line 7 ¶ | skipping to change at page 7, line 12 ¶ | |||
| implementations on both sides and reducing memory pressure on the | implementations on both sides and reducing memory pressure on the | |||
| sender. | sender. | |||
| 3.1.4. More ACK Ranges | 3.1.4. More ACK Ranges | |||
| QUIC supports many ACK ranges, opposed to TCP's 3 SACK ranges. In | QUIC supports many ACK ranges, opposed to TCP's 3 SACK ranges. In | |||
| high loss environments, this speeds recovery, reduces spurious | high loss environments, this speeds recovery, reduces spurious | |||
| retransmits, and ensures forward progress without relying on | retransmits, and ensures forward progress without relying on | |||
| timeouts. | timeouts. | |||
| 3.1.5. Explicit Correction For Delayed ACKs | 3.1.5. Explicit Correction For Delayed Acknowledgements | |||
| QUIC ACKs explicitly encode the delay incurred at the receiver | QUIC endpoints measure the delay incurred between when a packet is | |||
| between when a packet is received and when the corresponding ACK is | received and when the corresponding acknowledgment is sent, allowing | |||
| sent. This allows the receiver of the ACK to adjust for receiver | a peer to maintain a more accurate round-trip time estimate (see | |||
| delays, specifically the delayed ack timer, when estimating the path | Section 4.4). | |||
| RTT. This mechanism also allows a receiver to measure and report the | ||||
| delay from when a packet was received by the OS kernel, which is | ||||
| useful in receivers which may incur delays such as context-switch | ||||
| latency before a userspace QUIC receiver processes a received packet. | ||||
| 4. Generating Acknowledgements | 4. Generating Acknowledgements | |||
| QUIC SHOULD delay sending acknowledgements in response to packets, | ||||
| but MUST NOT excessively delay acknowledgements of ack-eliciting | ||||
| packets. Specifically, implementations MUST attempt to enforce a | ||||
| maximum ack delay to avoid causing the peer spurious timeouts. The | ||||
| maximum ack delay is communicated in the "max_ack_delay" transport | ||||
| parameter and the default value is 25ms. | ||||
| An acknowledgement SHOULD be sent immediately upon receipt of a | An acknowledgement SHOULD be sent immediately upon receipt of a | |||
| second ack-eliciting packet. QUIC recovery algorithms do not assume | second ack-eliciting packet. QUIC recovery algorithms do not assume | |||
| the peer sends an ACK immediately when receiving a second ack- | the peer sends an ACK immediately when receiving a second ack- | |||
| eliciting packet. | eliciting packet. | |||
| In order to accelerate loss recovery and reduce timeouts, the | In order to accelerate loss recovery and reduce timeouts, the | |||
| receiver SHOULD send an immediate ACK after it receives an out-of- | receiver SHOULD send an immediate ACK after it receives an out-of- | |||
| order packet. It could send immediate ACKs for in-order packets for | order packet. It could send immediate ACKs for in-order packets for | |||
| a period of time that SHOULD NOT exceed 1/8 RTT unless more out-of- | a period of time that SHOULD NOT exceed 1/8 RTT unless more out-of- | |||
| order packets arrive. If every packet arrives out-of- order, then an | order packets arrive. If every packet arrives out-of- order, then an | |||
| skipping to change at page 8, line 10 ¶ | skipping to change at page 7, line 47 ¶ | |||
| As an optimization, a receiver MAY process multiple packets before | As an optimization, a receiver MAY process multiple packets before | |||
| sending any ACK frames in response. In this case the receiver can | sending any ACK frames in response. In this case the receiver can | |||
| determine whether an immediate or delayed acknowledgement should be | determine whether an immediate or delayed acknowledgement should be | |||
| generated after processing incoming packets. | generated after processing incoming packets. | |||
| 4.1. Crypto Handshake Data | 4.1. Crypto Handshake Data | |||
| In order to quickly complete the handshake and avoid spurious | In order to quickly complete the handshake and avoid spurious | |||
| retransmissions due to crypto retransmission timeouts, crypto packets | retransmissions due to crypto retransmission timeouts, crypto packets | |||
| SHOULD use a very short ack delay, such as the local timer | SHOULD use a very short ack delay, such as the local timer | |||
| granularity. ACK frames MAY be sent immediately when the crypto | granularity. ACK frames SHOULD be sent immediately when the crypto | |||
| stack indicates all data for that packet number space has been | stack indicates all data for that packet number space has been | |||
| received. | received. | |||
| 4.2. ACK Ranges | 4.2. ACK Ranges | |||
| When an ACK frame is sent, one or more ranges of acknowledged packets | When an ACK frame is sent, one or more ranges of acknowledged packets | |||
| are included. Including older packets reduces the chance of spurious | are included. Including older packets reduces the chance of spurious | |||
| retransmits caused by losing previously sent ACK frames, at the cost | retransmits caused by losing previously sent ACK frames, at the cost | |||
| of larger ACK frames. | of larger ACK frames. | |||
| skipping to change at page 8, line 47 ¶ | skipping to change at page 8, line 38 ¶ | |||
| In cases without ACK frame loss, this algorithm allows for a minimum | In cases without ACK frame loss, this algorithm allows for a minimum | |||
| of 1 RTT of reordering. In cases with ACK frame loss and reordering, | of 1 RTT of reordering. In cases with ACK frame loss and reordering, | |||
| this approach does not guarantee that every acknowledgement is seen | this approach does not guarantee that every acknowledgement is seen | |||
| by the sender before it is no longer included in the ACK frame. | by the sender before it is no longer included in the ACK frame. | |||
| Packets could be received out of order and all subsequent ACK frames | Packets could be received out of order and all subsequent ACK frames | |||
| containing them could be lost. In this case, the loss recovery | containing them could be lost. In this case, the loss recovery | |||
| algorithm may cause spurious retransmits, but the sender will | algorithm may cause spurious retransmits, but the sender will | |||
| continue making forward progress. | continue making forward progress. | |||
| 5. Computing the RTT estimate | 4.4. Measuring and Reporting Host Delay | |||
| Round-trip time (RTT) is calculated when an ACK frame arrives by | An endpoint measures the delay incurred between when a packet is | |||
| computing the difference between the current time and the time the | received and when the corresponding acknowledgment is sent. The | |||
| largest acked packet was sent. An RTT sample MUST NOT be taken for a | endpoint encodes this host delay for the largest acknowledged packet | |||
| packet that is not newly acknowledged or not ack-eliciting. | in the Ack Delay field of an ACK frame (see Section 19.3 of | |||
| [QUIC-TRANSPORT]). This allows the receiver of the ACK to adjust for | ||||
| any host delays, which is important for delayed acknowledgements, | ||||
| when estimating the path RTT. In certain deployments, a packet might | ||||
| be held in the OS kernel or elsewhere on the host before being | ||||
| processed by the QUIC stack. Where possible, an endpoint MAY include | ||||
| these delays when populating the Ack Delay field in an ACK frame. | ||||
| When RTT is calculated, the ack delay field from the ACK frame SHOULD | An endpoint MUST NOT excessively delay acknowledgements of ack- | |||
| be limited to the max_ack_delay specified by the peer. Limiting | eliciting packets. The maximum ack delay is communicated in the | |||
| ack_delay to max_ack_delay ensures a peer specifying an extremely | max_ack_delay transport parameter, see Section 18.1 of | |||
| small max_ack_delay doesn't cause more spurious timeouts than a peer | [QUIC-TRANSPORT]. max_ack_delay implies an explicit contract: an | |||
| that correctly specifies max_ack_delay. It SHOULD be subtracted from | endpoint promises to never delay acknowledgments of an ack-eliciting | |||
| the RTT as long as the result is larger than the min_rtt. If the | packet by more than the indicated value. If it does, any excess | |||
| result is smaller than the min_rtt, the RTT should be used, but the | accrues to the RTT estimate and could result in spurious | |||
| ack delay field should be ignored. | retransmissions from the peer. | |||
| A sender calculates both smoothed RTT (SRTT) and RTT variance | 5. Estimating the Round-Trip Time | |||
| (RTTVAR) similar to those specified in [RFC6298], see Appendix A.6. | ||||
| A sender takes an RTT sample when an ACK frame is received that | At a high level, an endpoint measures the time from when a packet was | |||
| acknowledges a larger packet number than before (see Appendix A.6). | sent to when it is acknowledged as a round-trip time (RTT) sample. | |||
| A sender will take multiple RTT samples per RTT when multiple such | The endpoint uses RTT samples and peer-reported host delays | |||
| ACK frames are received within an RTT. When multiple samples are | (Section 4.4) to generate a statistical description of the | |||
| generated within an RTT, the smoothed RTT and RTT variance could | connection's RTT. An endpoint computes the following three values: | |||
| retain inadequate history, as suggested in [RFC6298]. Changing these | the minimum value observed over the lifetime of the connection | |||
| computations is currently an open research question. | (min_rtt), an exponentially-weighted moving average (smoothed_rtt), | |||
| and the variance in the observed RTT samples (rttvar). | ||||
| min_rtt is the minimum RTT measured over the connection, prior to | 5.1. Generating RTT samples | |||
| adjusting by ack delay. Ignoring ack delay for min RTT prevents | ||||
| intentional or unintentional underestimation of min RTT, which in | An endpoint generates an RTT sample on receiving an ACK frame that | |||
| turn prevents underestimating smoothed RTT. | meets the following two conditions: | |||
| o the largest acknowledged packet number is newly acknowledged, and | ||||
| o at least one of the newly acknowledged packets was ack-eliciting. | ||||
| The RTT sample, latest_rtt, is generated as the time elapsed since | ||||
| the largest acknowledged packet was sent: | ||||
| latest_rtt = ack_time - send_time_of_largest_acked | ||||
| An RTT sample is generated using only the largest acknowledged packet | ||||
| in the received ACK frame. This is because a peer reports host | ||||
| delays for only the largest acknowledged packet in an ACK frame. | ||||
| While the reported host delay is not used by the RTT sample | ||||
| measurement, it is used to adjust the RTT sample in subsequent | ||||
| computations of smoothed_rtt and rttvar Section 5.3. | ||||
| To avoid generating multiple RTT samples using the same packet, an | ||||
| ACK frame SHOULD NOT be used to update RTT estimates if it does not | ||||
| newly acknowledge the largest acknowledged packet. | ||||
| An RTT sample MUST NOT be generated on receiving an ACK frame that | ||||
| does not newly acknowledge at least one ack-eliciting packet. A peer | ||||
| does not send an ACK frame on receiving only non-ack-eliciting | ||||
| packets, so an ACK frame that is subsequently sent can include an | ||||
| arbitrarily large Ack Delay field. Ignoring such ACK frames avoids | ||||
| complications in subsequent smoothed_rtt and rttvar computations. | ||||
| A sender might generate multiple RTT samples per RTT when multiple | ||||
| ACK frames are received within an RTT. As suggested in [RFC6298], | ||||
| doing so might result in inadequate history in smoothed_rtt and | ||||
| rttvar. Ensuring that RTT estimates retain sufficient history is an | ||||
| open research question. | ||||
| 5.2. Estimating min_rtt | ||||
| min_rtt is the minimum RTT observed over the lifetime of the | ||||
| connection. min_rtt is set to the latest_rtt on the first sample in | ||||
| a connection, and to the lesser of min_rtt and latest_rtt on | ||||
| subsequent samples. | ||||
| An endpoint uses only locally observed times in computing the min_rtt | ||||
| and does not adjust for host delays reported by the peer | ||||
| (Section 4.4). Doing so allows the endpoint to set a lower bound for | ||||
| the smoothed_rtt based entirely on what it observes (see | ||||
| Section 5.3), and limits potential underestimation due to | ||||
| erroneously-reported delays by the peer. | ||||
| 5.3. Estimating smoothed_rtt and rttvar | ||||
| smoothed_rtt is an exponentially-weighted moving average of an | ||||
| endpoint's RTT samples, and rttvar is the endpoint's estimated | ||||
| variance in the RTT samples. | ||||
| smoothed_rtt uses path latency after adjusting RTT samples for peer- | ||||
| reported host delays (Section 4.4). A peer limits any delay in | ||||
| sending an acknowledgement for an ack-eliciting packet to no greater | ||||
| than the advertised max_ack_delay transport parameter. Consequently, | ||||
| when a peer reports an Ack Delay that is greater than its | ||||
| max_ack_delay, the delay is attributed to reasons out of the peer's | ||||
| control, such as scheduler latency at the peer or loss of previous | ||||
| ACK frames. Any delays beyond the peer's max_ack_delay are therefore | ||||
| considered effectively part of path delay and incorporated into the | ||||
| smoothed_rtt estimate. | ||||
| When adjusting an RTT sample using peer-reported acknowledgement | ||||
| delays, an endpoint: | ||||
| o MUST use the lesser of the value reported in Ack Delay field of | ||||
| the ACK frame and the peer's max_ack_delay transport parameter | ||||
| (Section 4.4). | ||||
| o MUST NOT apply the adjustment if the resulting RTT sample is | ||||
| smaller than the min_rtt. This limits the underestimation that a | ||||
| misreporting peer can cause to the smoothed_rtt. | ||||
| On the first RTT sample in a connection, the smoothed_rtt is set to | ||||
| the latest_rtt. | ||||
| smoothed_rtt and rttvar are computed as follows, similar to | ||||
| [RFC6298]. On the first RTT sample in a connection: | ||||
| smoothed_rtt = latest_rtt | ||||
| rttvar = latest_rtt / 2 | ||||
| On subsequent RTT samples, smoothed_rtt and rttvar evolve as follows: | ||||
| ack_delay = min(Ack Delay in ACK Frame, max_ack_delay) | ||||
| adjusted_rtt = latest_rtt | ||||
| if (min_rtt + ack_delay < latest_rtt): | ||||
| adjusted_rtt = latest_rtt - ack_delay | ||||
| smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt | ||||
| rttvar_sample = abs(smoothed_rtt - adjusted_rtt) | ||||
| rttvar = 3/4 * rttvar + 1/4 * rttvar_sample | ||||
| 6. Loss Detection | 6. Loss Detection | |||
| QUIC senders use both ack information and timeouts to detect lost | QUIC senders use both ack information and timeouts to detect lost | |||
| packets, and this section provides a description of these algorithms. | packets, and this section provides a description of these algorithms. | |||
| If a packet is lost, the QUIC transport needs to recover from that | If a packet is lost, the QUIC transport needs to recover from that | |||
| loss, such as by retransmitting the data, sending an updated frame, | loss, such as by retransmitting the data, sending an updated frame, | |||
| or abandoning the frame. For more information, see Section 13.2 of | or abandoning the frame. For more information, see Section 13.2 of | |||
| [QUIC-TRANSPORT]. | [QUIC-TRANSPORT]. | |||
| skipping to change at page 11, line 5 ¶ | skipping to change at page 12, line 48 ¶ | |||
| Using max(SRTT, latest_RTT) protects from the two following cases: | Using max(SRTT, latest_RTT) protects from the two following cases: | |||
| o the latest RTT sample is lower than the SRTT, perhaps due to | o the latest RTT sample is lower than the SRTT, perhaps due to | |||
| reordering where the acknowledgement encountered a shorter path; | reordering where the acknowledgement encountered a shorter path; | |||
| o the latest RTT sample is higher than the SRTT, perhaps due to a | o the latest RTT sample is higher than the SRTT, perhaps due to a | |||
| sustained increase in the actual RTT, but the smoothed SRTT has | sustained increase in the actual RTT, but the smoothed SRTT has | |||
| not yet caught up. | not yet caught up. | |||
| An endpoint might consistently record RTT samples as 0 in extremely | ||||
| low latency networks, leading to a smoothed_rtt of 0. Consequently, | ||||
| the endpoint could declare all earlier packets as lost immediately | ||||
| upon receiving an acknowledgement for a later packet. That is, the | ||||
| endpoint would not provide any reordering tolerance. To avoid | ||||
| declaring packets as lost too early, the time threshold MUST be set | ||||
| to at least kGranularity (defined in Appendix A.2). | ||||
| Implementations MAY experiment with absolute thresholds, thresholds | Implementations MAY experiment with absolute thresholds, thresholds | |||
| from previous connections, adaptive thresholds, or including RTT | from previous connections, adaptive thresholds, or including RTT | |||
| variance. Smaller thresholds reduce reordering resilience and | variance. Smaller thresholds reduce reordering resilience and | |||
| increase spurious retransmissions, and larger thresholds increase | increase spurious retransmissions, and larger thresholds increase | |||
| loss detection delay. | loss detection delay. | |||
| 6.2. Crypto Retransmission Timeout | 6.2. Crypto Retransmission Timeout | |||
| Data in CRYPTO frames is critical to QUIC transport and crypto | Data in CRYPTO frames is critical to QUIC transport and crypto | |||
| negotiation, so a more aggressive timeout is used to retransmit it. | negotiation, so a more aggressive timeout is used to retransmit it. | |||
| The initial crypto retransmission timeout SHOULD be set to twice the | The initial crypto retransmission timeout SHOULD be set to twice the | |||
| initial RTT. | initial RTT. | |||
| At the beginning, there are no prior RTT samples within a connection. | At the beginning, there are no prior RTT samples within a connection. | |||
| Resumed connections over the same network SHOULD use the previous | Resumed connections over the same network SHOULD use the previous | |||
| connection's final smoothed RTT value as the resumed connection's | connection's final smoothed RTT value as the resumed connection's | |||
| initial RTT. If no previous RTT is available, or if the network | initial RTT. If no previous RTT is available, or if the network | |||
| changes, the initial RTT SHOULD be set to 100ms. When an | changes, the initial RTT SHOULD be set to 500ms, resulting in a 1 | |||
| acknowledgement is received, a new RTT is computed and the timer | second initial handshake timeout as recommended in [RFC6298]. | |||
| SHOULD be set for twice the newly computed smoothed RTT. | ||||
| When a crypto packet is sent, the sender MUST set a timer for the | When a crypto packet is sent, the sender MUST set a timer for twice | |||
| crypto timeout period. This timer MUST be updated when a new crypto | the smoothed RTT. This timer MUST be updated when a new crypto | |||
| packet is sent. Upon timeout, the sender MUST retransmit all | packet is sent and when an acknowledgement is received which computes | |||
| unacknowledged CRYPTO data if possible. | a new RTT sample. Upon timeout, the sender MUST retransmit all | |||
| unacknowledged CRYPTO data if possible. The sender MUST NOT declare | ||||
| in-flight crypto packets as lost when the crypto timer expires. | ||||
| On each consecutive expiration of the crypto timer without receiving | ||||
| an acknowledgement for a new packet, the sender MUST double the | ||||
| crypto retransmission timeout and set a timer for this period. | ||||
| Until the server has validated the client's address on the path, the | Until the server has validated the client's address on the path, the | |||
| amount of data it can send is limited, as specified in | amount of data it can send is limited, as specified in Section 8.1 of | |||
| [QUIC-TRANSPORT]. If not all unacknowledged CRYPTO data can be sent, | [QUIC-TRANSPORT]. If not all unacknowledged CRYPTO data can be sent, | |||
| then all unacknowledged CRYPTO data sent in Initial packets should be | then all unacknowledged CRYPTO data sent in Initial packets should be | |||
| retransmitted. If no data can be sent, then no alarm should be armed | retransmitted. If no data can be sent, then no alarm should be armed | |||
| until data has been received from the client. | until data has been received from the client. | |||
| Because the server could be blocked until more packets are received, | Because the server could be blocked until more packets are received, | |||
| the client MUST start the crypto retransmission timer even if there | the client MUST ensure that the crypto retransmission timer is set if | |||
| is no unacknowledged CRYPTO data. If the timer expires and the | there is unacknowledged crypto data or if the client does not yet | |||
| client has no CRYPTO data to retransmit and does not have Handshake | have 1-RTT keys. If the crypto retransmission timer expires before | |||
| keys, it SHOULD send an Initial packet in a UDP datagram of at least | the client has 1-RTT keys, it is possible that the client may not | |||
| 1200 bytes. If the client has Handshake keys, it SHOULD send a | have any crypto data to retransmit. However, the client MUST send a | |||
| Handshake packet. | new packet, containing only PING or PADDING frames if necessary, to | |||
| allow the server to continue sending data. If Handshake keys are | ||||
| available to the client, it MUST send a Handshake packet, and | ||||
| otherwise it MUST send an Initial packet in a UDP datagram of at | ||||
| least 1200 bytes. | ||||
| On each consecutive expiration of the crypto timer without receiving | The crypto retransmission timer is not set if the time threshold | |||
| an acknowledgement for a new packet, the sender SHOULD double the | Section 6.1.2 loss detection timer is set. The time threshold loss | |||
| crypto retransmission timeout and set a timer for this period. | detection timer is expected to both expire earlier than the crypto | |||
| retransmission timeout and be less likely to spuriously retransmit | ||||
| data. The Initial and Handshake packet number spaces will typically | ||||
| contain a small number of packets, so losses are less likely to be | ||||
| detected using packet-threshold loss detection. | ||||
| When crypto packets are in flight, the probe timer (Section 6.3) is | When the crypto retransmission timer is active, the probe timer | |||
| not active. | (Section 6.3) is not active. | |||
| 6.2.1. Retry and Version Negotiation | 6.2.1. Retry and Version Negotiation | |||
| A Retry or Version Negotiation packet causes a client to send another | A Retry or Version Negotiation packet causes a client to send another | |||
| Initial packet, effectively restarting the connection process and | Initial packet, effectively restarting the connection process and | |||
| resetting congestion control and loss recovery state, including | resetting congestion control and loss recovery state, including | |||
| resetting any pending timers. Either packet indicates that the | resetting any pending timers. Either packet indicates that the | |||
| Initial was received but not processed. Neither packet can be | Initial was received but not processed. Neither packet can be | |||
| treated as an acknowledgment for the Initial. | treated as an acknowledgment for the Initial. | |||
| skipping to change at page 13, line 39 ¶ | skipping to change at page 16, line 9 ¶ | |||
| because the PTOs might be caused by loss of packets or | because the PTOs might be caused by loss of packets or | |||
| acknowledgements due to severe congestion. | acknowledgements due to severe congestion. | |||
| A sender computes its PTO timer every time an ack-eliciting packet is | A sender computes its PTO timer every time an ack-eliciting packet is | |||
| sent. A sender might choose to optimize this by setting the timer | sent. A sender might choose to optimize this by setting the timer | |||
| fewer times if it knows that more ack-eliciting packets will be sent | fewer times if it knows that more ack-eliciting packets will be sent | |||
| within a short period of time. | within a short period of time. | |||
| 6.3.2. Sending Probe Packets | 6.3.2. Sending Probe Packets | |||
| When a PTO timer expires, the sender MUST send one ack-eliciting | When a PTO timer expires, a sender MUST send at least one ack- | |||
| packet as a probe. A sender MAY send up to two ack-eliciting | eliciting packet as a probe, unless there is no data available to | |||
| packets, to avoid an expensive consecutive PTO expiration due to a | send. An endpoint MAY send up to two ack-eliciting packets, to avoid | |||
| single packet loss. | an expensive consecutive PTO expiration due to a single packet loss. | |||
| It is possible that the sender has no new or previously-sent data to | ||||
| send. As an example, consider the following sequence of events: new | ||||
| application data is sent in a STREAM frame, deemed lost, then | ||||
| retransmitted in a new packet, and then the original transmission is | ||||
| acknowledged. In the absence of any new application data, a PTO | ||||
| timer expiration now would find the sender with no new or previously- | ||||
| sent data to send. | ||||
| When there is no data to send, the sender SHOULD send a PING or other | ||||
| ack-eliciting frame in a single packet, re-arming the PTO timer. | ||||
| Alternatively, instead of sending an ack-eliciting packet, the sender | ||||
| MAY mark any packets still in flight as lost. Doing so avoids | ||||
| sending an additional packet, but increases the risk that loss is | ||||
| declared too aggressively, resulting in an unnecessary rate reduction | ||||
| by the congestion controller. | ||||
| Consecutive PTO periods increase exponentially, and as a result, | Consecutive PTO periods increase exponentially, and as a result, | |||
| connection recovery latency increases exponentially as packets | connection recovery latency increases exponentially as packets | |||
| continue to be dropped in the network. Sending two packets on PTO | continue to be dropped in the network. Sending two packets on PTO | |||
| expiration increases resilience to packet drops, thus reducing the | expiration increases resilience to packet drops, thus reducing the | |||
| probability of consecutive PTO events. | probability of consecutive PTO events. | |||
| Probe packets sent on a PTO MUST be ack-eliciting. A probe packet | Probe packets sent on a PTO MUST be ack-eliciting. A probe packet | |||
| SHOULD carry new data when possible. A probe packet MAY carry | SHOULD carry new data when possible. A probe packet MAY carry | |||
| retransmitted unacknowledged data when new data is unavailable, when | retransmitted unacknowledged data when new data is unavailable, when | |||
| skipping to change at page 14, line 18 ¶ | skipping to change at page 17, line 5 ¶ | |||
| packets, including sending new or retransmitted data based on the | packets, including sending new or retransmitted data based on the | |||
| application's priorities. | application's priorities. | |||
| When the PTO timer expires multiple times and new data cannot be | When the PTO timer expires multiple times and new data cannot be | |||
| sent, implementations must choose between sending the same payload | sent, implementations must choose between sending the same payload | |||
| every time or sending different payloads. Sending the same payload | every time or sending different payloads. Sending the same payload | |||
| may be simpler and ensures the highest priority frames arrive first. | may be simpler and ensures the highest priority frames arrive first. | |||
| Sending different payloads each time reduces the chances of spurious | Sending different payloads each time reduces the chances of spurious | |||
| retransmission. | retransmission. | |||
| When a PTO timer expires, new or previously-sent data may not be | ||||
| available to send and packets may still be in flight. A sender can | ||||
| be blocked from sending new data in the future if packets are left in | ||||
| flight. Under these conditions, a sender SHOULD mark any packets | ||||
| still in flight as lost. If a sender wishes to establish delivery of | ||||
| packets still in flight, it MAY send an ack-eliciting packet and re- | ||||
| arm the PTO timer instead. | ||||
| 6.3.3. Loss Detection | 6.3.3. Loss Detection | |||
| Delivery or loss of packets in flight is established when an ACK | Delivery or loss of packets in flight is established when an ACK | |||
| frame is received that newly acknowledges one or more packets. | frame is received that newly acknowledges one or more packets. | |||
| A PTO timer expiration event does not indicate packet loss and MUST | A PTO timer expiration event does not indicate packet loss and MUST | |||
| NOT cause prior unacknowledged packets to be marked as lost. When an | NOT cause prior unacknowledged packets to be marked as lost. When an | |||
| acknowledgement is received that newly acknowledges packets, loss | acknowledgement is received that newly acknowledges packets, loss | |||
| detection proceeds as dictated by packet and time threshold | detection proceeds as dictated by packet and time threshold | |||
| mechanisms, see Section 6.1. | mechanisms, see Section 6.1. | |||
| skipping to change at page 14, line 48 ¶ | skipping to change at page 17, line 27 ¶ | |||
| The majority of constants were derived from best common practices | The majority of constants were derived from best common practices | |||
| among widely deployed TCP implementations on the internet. | among widely deployed TCP implementations on the internet. | |||
| Exceptions follow. | Exceptions follow. | |||
| A shorter delayed ack time of 25ms was chosen because longer delayed | A shorter delayed ack time of 25ms was chosen because longer delayed | |||
| acks can delay loss recovery and for the small number of connections | acks can delay loss recovery and for the small number of connections | |||
| where less than packet per 25ms is delivered, acking every packet is | where less than packet per 25ms is delivered, acking every packet is | |||
| beneficial to congestion control and loss recovery. | beneficial to congestion control and loss recovery. | |||
| The default initial RTT of 100ms was chosen because it is slightly | ||||
| higher than both the median and mean min_rtt typically observed on | ||||
| the public internet. | ||||
| 7. Congestion Control | 7. Congestion Control | |||
| QUIC's congestion control is based on TCP NewReno [RFC6582]. NewReno | QUIC's congestion control is based on TCP NewReno [RFC6582]. NewReno | |||
| is a congestion window based congestion control. QUIC specifies the | is a congestion window based congestion control. QUIC specifies the | |||
| congestion window in bytes rather than packets due to finer control | congestion window in bytes rather than packets due to finer control | |||
| and the ease of appropriate byte counting [RFC3465]. | and the ease of appropriate byte counting [RFC3465]. | |||
| QUIC hosts MUST NOT send packets if they would increase | QUIC hosts MUST NOT send packets if they would increase | |||
| bytes_in_flight (defined in Appendix B.2) beyond the available | bytes_in_flight (defined in Appendix B.2) beyond the available | |||
| congestion window, unless the packet is a probe packet sent after a | congestion window, unless the packet is a probe packet sent after a | |||
| skipping to change at page 16, line 46 ¶ | skipping to change at page 19, line 15 ¶ | |||
| packets. | packets. | |||
| 7.7. Persistent Congestion | 7.7. Persistent Congestion | |||
| When an ACK frame is received that establishes loss of all in-flight | When an ACK frame is received that establishes loss of all in-flight | |||
| packets sent over a long enough period of time, the network is | packets sent over a long enough period of time, the network is | |||
| considered to be experiencing persistent congestion. Commonly, this | considered to be experiencing persistent congestion. Commonly, this | |||
| can be established by consecutive PTOs, but since the PTO timer is | can be established by consecutive PTOs, but since the PTO timer is | |||
| reset when a new ack-eliciting packet is sent, an explicit duration | reset when a new ack-eliciting packet is sent, an explicit duration | |||
| must be used to account for those cases where PTOs do not occur or | must be used to account for those cases where PTOs do not occur or | |||
| are substantially delayed. This duration is the equivalent of | are substantially delayed. This duration is computed as follows: | |||
| kPersistentCongestionThreshold consecutive PTOs, and is computed as | ||||
| follows: ~~~ (smoothed_rtt + 4 * rttvar + max_ack_delay) * ((2 ^ | (smoothed_rtt + 4 * rttvar + max_ack_delay) * | |||
| kPersistentCongestionThreshold) - 1) ~~~ | kPersistentCongestionThreshold | |||
| For example, assume: | For example, assume: | |||
| smoothed_rtt = 1 rttvar = 0 max_ack_delay = 0 | smoothed_rtt = 1 rttvar = 0 max_ack_delay = 0 | |||
| kPersistentCongestionThreshold = 2 | kPersistentCongestionThreshold = 3 | |||
| If an eck-eliciting packet is sent at time = 0, the following | If an eck-eliciting packet is sent at time = 0, the following | |||
| scenario would illustrate persistent congestion: | scenario would illustrate persistent congestion: | |||
| +-----+------------------------+ | +-----+------------------------+ | |||
| | t=0 | Send Pkt #1 (App Data) | | | t=0 | Send Pkt #1 (App Data) | | |||
| +-----+------------------------+ | +-----+------------------------+ | |||
| | t=1 | Send Pkt #2 (PTO 1) | | | t=1 | Send Pkt #2 (PTO 1) | | |||
| | | | | | | | | |||
| | t=3 | Send Pkt #3 (PTO 2) | | | t=3 | Send Pkt #3 (PTO 2) | | |||
| | | | | | | | | |||
| | t=7 | Send Pkt #4 (PTO 3) | | | t=7 | Send Pkt #4 (PTO 3) | | |||
| | | | | | | | | |||
| | t=8 | Recv ACK of Pkt #4 | | | t=8 | Recv ACK of Pkt #4 | | |||
| +-----+------------------------+ | +-----+------------------------+ | |||
| The first three packets are determined to be lost when the ACK of | The first three packets are determined to be lost when the ACK of | |||
| packet 4 is received at t=8. The congestion period is calculated as | packet 4 is received at t=8. The congestion period is calculated as | |||
| the time between the oldest and newest lost packets: (3 - 0) = 3. | the time between the oldest and newest lost packets: (3 - 0) = 3. | |||
| The duration for persistent congestion is equal to: (1 * ((2 ^ | The duration for persistent congestion is equal to: (1 * | |||
| kPersistentCongestionThreshold) - 1)) = 3. Because the threshold was | kPersistentCongestionThreshold) = 3. Because the threshold was | |||
| reached and because none of the packets between the oldest and the | reached and because none of the packets between the oldest and the | |||
| newest packets are acknowledged, the network is considered to have | newest packets are acknowledged, the network is considered to have | |||
| experienced persistent congestion. | experienced persistent congestion. | |||
| When persistent congestion is established, the sender's congestion | When persistent congestion is established, the sender's congestion | |||
| window MUST be reduced to the minimum congestion window | window MUST be reduced to the minimum congestion window | |||
| (kMinimumWindow). This response of collapsing the congestion window | (kMinimumWindow). This response of collapsing the congestion window | |||
| on persistent congestion is functionally similar to a sender's | on persistent congestion is functionally similar to a sender's | |||
| response on a Retransmission Timeout (RTO) in TCP [RFC5681] after | response on a Retransmission Timeout (RTO) in TCP [RFC5681] after | |||
| Tail Loss Probes (TLP) [TLP]. | Tail Loss Probes (TLP) [TLP]. | |||
| skipping to change at page 18, line 12 ¶ | skipping to change at page 20, line 30 ¶ | |||
| congestion window, or a pacer might pace out packets handed to it by | congestion window, or a pacer might pace out packets handed to it by | |||
| the congestion controller. Timely delivery of ACK frames is | the congestion controller. Timely delivery of ACK frames is | |||
| important for efficient loss recovery. Packets containing only ACK | important for efficient loss recovery. Packets containing only ACK | |||
| frames should therefore not be paced, to avoid delaying their | frames should therefore not be paced, to avoid delaying their | |||
| delivery to the peer. | delivery to the peer. | |||
| As an example of a well-known and publicly available implementation | As an example of a well-known and publicly available implementation | |||
| of a flow pacer, implementers are referred to the Fair Queue packet | of a flow pacer, implementers are referred to the Fair Queue packet | |||
| scheduler (fq qdisc) in Linux (3.11 onwards). | scheduler (fq qdisc) in Linux (3.11 onwards). | |||
| 7.9. Sending data after an idle period | 7.9. Under-utilizing the Congestion Window | |||
| A sender becomes idle if it ceases to send data and has no bytes in | ||||
| flight. A sender's congestion window MUST NOT increase while it is | ||||
| idle. | ||||
| When sending data after becoming idle, a sender MUST reset its | ||||
| congestion window to the initial congestion window (see Section 4.1 | ||||
| of [RFC5681]), unless it paces the sending of packets. A sender MAY | ||||
| retain its congestion window if it paces the sending of any packets | ||||
| in excess of the initial congestion window. | ||||
| A sender MAY implement alternate mechanisms to update its congestion | ||||
| window after idle periods, such as those proposed for TCP in | ||||
| [RFC7661]. | ||||
| 7.10. Application Limited Sending | A congestion window that is under-utilized SHOULD NOT be increased in | |||
| either slow start or congestion avoidance. This can happen due to | ||||
| insufficient application data or flow control credit. | ||||
| The congestion window should not be increased in slow start or | A sender MAY use the pipeACK method described in section 4.3 of | |||
| congestion avoidance when it is not fully utilized. The congestion | [RFC7661] to determine if the congestion window is sufficiently | |||
| window could be under-utilized due to insufficient application data | utilized. | |||
| or flow control credit. | ||||
| A sender that paces packets (see Section 7.8) might delay sending | A sender that paces packets (see Section 7.8) might delay sending | |||
| packets and not fully utilize the congestion window due to this | packets and not fully utilize the congestion window due to this | |||
| delay. A sender should not consider itself application limited if it | delay. A sender should not consider itself application limited if it | |||
| would have fully utilized the congestion window without pacing delay. | would have fully utilized the congestion window without pacing delay. | |||
| Bursting more than an intial window's worth of data into the network | ||||
| might cause short-term congestion and losses. Implemementations | ||||
| SHOULD either use pacing or reduce their congestion window to limit | ||||
| such bursts. | ||||
| A sender MAY implement alternate mechanisms to update its congestion | ||||
| window after periods of under-utilization, such as those proposed for | ||||
| TCP in [RFC7661]. | ||||
| 8. Security Considerations | 8. Security Considerations | |||
| 8.1. Congestion Signals | 8.1. Congestion Signals | |||
| Congestion control fundamentally involves the consumption of signals | Congestion control fundamentally involves the consumption of signals | |||
| - both loss and ECN codepoints - from unauthenticated entities. On- | - both loss and ECN codepoints - from unauthenticated entities. On- | |||
| path attackers can spoof or alter these signals. An attacker can | path attackers can spoof or alter these signals. An attacker can | |||
| cause endpoints to reduce their sending rate by dropping packets, or | cause endpoints to reduce their sending rate by dropping packets, or | |||
| alter send rate by changing ECN codepoints. | alter send rate by changing ECN codepoints. | |||
| skipping to change at page 19, line 46 ¶ | skipping to change at page 22, line 15 ¶ | |||
| 9. IANA Considerations | 9. IANA Considerations | |||
| This document has no IANA actions. Yet. | This document has no IANA actions. Yet. | |||
| 10. References | 10. References | |||
| 10.1. Normative References | 10.1. Normative References | |||
| [QUIC-TLS] | [QUIC-TLS] | |||
| Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure | Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure | |||
| QUIC", draft-ietf-quic-tls-19 (work in progress), March | QUIC", draft-ietf-quic-tls-20 (work in progress), April | |||
| 2019. | 2019. | |||
| [QUIC-TRANSPORT] | [QUIC-TRANSPORT] | |||
| Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | |||
| Multiplexed and Secure Transport", draft-ietf-quic- | Multiplexed and Secure Transport", draft-ietf-quic- | |||
| transport-19 (work in progress), March 2019. | transport-20 (work in progress), April 2019. | |||
| [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
| Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
| DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
| <https://www.rfc-editor.org/info/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
| [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | |||
| 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | |||
| May 2017, <https://www.rfc-editor.org/info/rfc8174>. | May 2017, <https://www.rfc-editor.org/info/rfc8174>. | |||
| skipping to change at page 23, line 17 ¶ | skipping to change at page 25, line 37 ¶ | |||
| value is 3. | value is 3. | |||
| kTimeThreshold: Maximum reordering in time before time threshold | kTimeThreshold: Maximum reordering in time before time threshold | |||
| loss detection considers a packet lost. Specified as an RTT | loss detection considers a packet lost. Specified as an RTT | |||
| multiplier. The RECOMMENDED value is 9/8. | multiplier. The RECOMMENDED value is 9/8. | |||
| kGranularity: Timer granularity. This is a system-dependent value. | kGranularity: Timer granularity. This is a system-dependent value. | |||
| However, implementations SHOULD use a value no smaller than 1ms. | However, implementations SHOULD use a value no smaller than 1ms. | |||
| kInitialRtt: The RTT used before an RTT sample is taken. The | kInitialRtt: The RTT used before an RTT sample is taken. The | |||
| RECOMMENDED value is 100ms. | RECOMMENDED value is 500ms. | |||
| kPacketNumberSpace: An enum to enumerate the three packet number | kPacketNumberSpace: An enum to enumerate the three packet number | |||
| spaces. ~~~ enum kPacketNumberSpace { Initial, Handshake, | spaces. | |||
| ApplicationData, } ~~~ | ||||
| enum kPacketNumberSpace { | ||||
| Initial, | ||||
| Handshake, | ||||
| ApplicationData, | ||||
| } | ||||
| A.3. Variables of interest | A.3. Variables of interest | |||
| Variables required to implement the congestion control mechanisms are | Variables required to implement the congestion control mechanisms are | |||
| described in this section. | described in this section. | |||
| loss_detection_timer: Multi-modal timer used for loss detection. | loss_detection_timer: Multi-modal timer used for loss detection. | |||
| crypto_count: The number of times all unacknowledged CRYPTO data has | crypto_count: The number of times all unacknowledged CRYPTO data has | |||
| been retransmitted without receiving an ack. | been retransmitted without receiving an ack. | |||
| skipping to change at page 24, line 27 ¶ | skipping to change at page 27, line 8 ¶ | |||
| detail above in Appendix A.1. | detail above in Appendix A.1. | |||
| A.4. Initialization | A.4. Initialization | |||
| At the beginning of the connection, initialize the loss detection | At the beginning of the connection, initialize the loss detection | |||
| variables as follows: | variables as follows: | |||
| loss_detection_timer.reset() | loss_detection_timer.reset() | |||
| crypto_count = 0 | crypto_count = 0 | |||
| pto_count = 0 | pto_count = 0 | |||
| latest_rtt = 0 | ||||
| smoothed_rtt = 0 | smoothed_rtt = 0 | |||
| rttvar = 0 | rttvar = 0 | |||
| min_rtt = infinite | min_rtt = 0 | |||
| time_of_last_sent_ack_eliciting_packet = 0 | time_of_last_sent_ack_eliciting_packet = 0 | |||
| time_of_last_sent_crypto_packet = 0 | time_of_last_sent_crypto_packet = 0 | |||
| for pn_space in [ Initial, Handshake, ApplicatonData ]: | for pn_space in [ Initial, Handshake, ApplicationData ]: | |||
| largest_acked_packet[pn_space] = 0 | largest_acked_packet[pn_space] = 0 | |||
| loss_time[pn_space] = 0 | loss_time[pn_space] = 0 | |||
| A.5. On Sending a Packet | A.5. On Sending a Packet | |||
| After a packet is sent, information about the packet is stored. The | After a packet is sent, information about the packet is stored. The | |||
| parameters to OnPacketSent are described in detail above in | parameters to OnPacketSent are described in detail above in | |||
| Appendix A.1.1. | Appendix A.1.1. | |||
| Pseudocode for OnPacketSent follows: | Pseudocode for OnPacketSent follows: | |||
| skipping to change at page 26, line 9 ¶ | skipping to change at page 28, line 5 ¶ | |||
| When an ACK frame is received, it may newly acknowledge any number of | When an ACK frame is received, it may newly acknowledge any number of | |||
| packets. | packets. | |||
| Pseudocode for OnAckReceived and UpdateRtt follow: | Pseudocode for OnAckReceived and UpdateRtt follow: | |||
| OnAckReceived(ack, pn_space): | OnAckReceived(ack, pn_space): | |||
| largest_acked_packet[pn_space] = | largest_acked_packet[pn_space] = | |||
| max(largest_acked_packet[pn_space], ack.largest_acked) | max(largest_acked_packet[pn_space], ack.largest_acked) | |||
| // Nothing to do if there are no newly acked packets. | ||||
| newly_acked_packets = DetermineNewlyAckedPackets(ack, pn_space) | ||||
| if (newly_acked_packets.empty()): | ||||
| return | ||||
| // If the largest acknowledged is newly acked and | // If the largest acknowledged is newly acked and | |||
| // ack-eliciting, update the RTT. | // at least one ack-eliciting was newly acked, update the RTT. | |||
| if (sent_packets[pn_space][ack.largest_acked] && | if (sent_packets[pn_space][ack.largest_acked] && | |||
| sent_packets[pn_space][ack.largest_acked].ack_eliciting): | IncludesAckEliciting(newly_acked_packets)) | |||
| latest_rtt = | latest_rtt = | |||
| now - sent_packets[pn_space][ack.largest_acked].time_sent | now - sent_packets[pn_space][ack.largest_acked].time_sent | |||
| UpdateRtt(latest_rtt, ack.ack_delay) | UpdateRtt(ack.ack_delay) | |||
| // Process ECN information if present. | // Process ECN information if present. | |||
| if (ACK frame contains ECN information): | if (ACK frame contains ECN information): | |||
| ProcessECN(ack) | ProcessECN(ack) | |||
| // Find all newly acked packets in this ACK frame | ||||
| newly_acked_packets = DetermineNewlyAckedPackets(ack, pn_space) | ||||
| if (newly_acked_packets.empty()): | ||||
| return | ||||
| for acked_packet in newly_acked_packets: | for acked_packet in newly_acked_packets: | |||
| OnPacketAcked(acked_packet.packet_number, pn_space) | OnPacketAcked(acked_packet.packet_number, pn_space) | |||
| DetectLostPackets(pn_space) | DetectLostPackets(pn_space) | |||
| crypto_count = 0 | crypto_count = 0 | |||
| pto_count = 0 | pto_count = 0 | |||
| SetLossDetectionTimer() | SetLossDetectionTimer() | |||
| UpdateRtt(latest_rtt, ack_delay): | UpdateRtt(ack_delay): | |||
| // First RTT sample. | ||||
| if (smoothed_rtt == 0): | ||||
| min_rtt = latest_rtt | ||||
| smoothed_rtt = latest_rtt | ||||
| rttvar = latest_rtt / 2 | ||||
| return | ||||
| // min_rtt ignores ack delay. | // min_rtt ignores ack delay. | |||
| min_rtt = min(min_rtt, latest_rtt) | min_rtt = min(min_rtt, latest_rtt) | |||
| // Limit ack_delay by max_ack_delay | // Limit ack_delay by max_ack_delay | |||
| ack_delay = min(ack_delay, max_ack_delay) | ack_delay = min(ack_delay, max_ack_delay) | |||
| // Adjust for ack delay if it's plausible. | // Adjust for ack delay if plausible. | |||
| if (latest_rtt - min_rtt > ack_delay): | adjusted_rtt = latest_rtt | |||
| latest_rtt -= ack_delay | if (latest_rtt > min_rtt + ack_delay): | |||
| // Based on {{RFC6298}}. | adjusted_rtt = latest_rtt - ack_delay | |||
| if (smoothed_rtt == 0): | ||||
| smoothed_rtt = latest_rtt | rttvar = 3/4 * rttvar + 1/4 * abs(smoothed_rtt - adjusted_rtt) | |||
| rttvar = latest_rtt / 2 | smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt | |||
| else: | ||||
| rttvar_sample = abs(smoothed_rtt - latest_rtt) | ||||
| rttvar = 3/4 * rttvar + 1/4 * rttvar_sample | ||||
| smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * latest_rtt | ||||
| A.7. On Packet Acknowledgment | A.7. On Packet Acknowledgment | |||
| When a packet is acknowledged for the first time, the following | When a packet is acknowledged for the first time, the following | |||
| OnPacketAcked function is called. Note that a single ACK frame may | OnPacketAcked function is called. Note that a single ACK frame may | |||
| newly acknowledge several packets. OnPacketAcked must be called once | newly acknowledge several packets. OnPacketAcked must be called once | |||
| for each of these newly acknowledged packets. | for each of these newly acknowledged packets. | |||
| OnPacketAcked takes two parameters: acked_packet, which is the struct | OnPacketAcked takes two parameters: acked_packet, which is the struct | |||
| detailed in Appendix A.1.1, and the packet number space that this ACK | detailed in Appendix A.1.1, and the packet number space that this ACK | |||
| frame was sent for. | frame was sent for. | |||
| Pseudocode for OnPacketAcked follows: | Pseudocode for OnPacketAcked follows: | |||
| OnPacketAcked(acked_packet, pn_space): | OnPacketAcked(acked_packet, pn_space): | |||
| if (acked_packet.ack_eliciting): | if (acked_packet.in_flight): | |||
| OnPacketAckedCC(acked_packet) | OnPacketAckedCC(acked_packet) | |||
| sent_packets[pn_space].remove(acked_packet.packet_number) | sent_packets[pn_space].remove(acked_packet.packet_number) | |||
| A.8. Setting the Loss Detection Timer | A.8. Setting the Loss Detection Timer | |||
| QUIC loss detection uses a single timer for all timeout loss | QUIC loss detection uses a single timer for all timeout loss | |||
| detection. The duration of the timer is based on the timer's mode, | detection. The duration of the timer is based on the timer's mode, | |||
| which is set in the packet and timer events further below. The | which is set in the packet and timer events further below. The | |||
| function SetLossDetectionTimer defined below shows how the single | function SetLossDetectionTimer defined below shows how the single | |||
| timer is set. | timer is set. | |||
| skipping to change at page 28, line 10 ¶ | skipping to change at page 30, line 10 ¶ | |||
| particularly if timers wake up late. Timers set in the past SHOULD | particularly if timers wake up late. Timers set in the past SHOULD | |||
| fire immediately. | fire immediately. | |||
| Pseudocode for SetLossDetectionTimer follows: | Pseudocode for SetLossDetectionTimer follows: | |||
| // Returns the earliest loss_time and the packet number | // Returns the earliest loss_time and the packet number | |||
| // space it's from. Returns 0 if all times are 0. | // space it's from. Returns 0 if all times are 0. | |||
| GetEarliestLossTime(): | GetEarliestLossTime(): | |||
| time = loss_time[Initial] | time = loss_time[Initial] | |||
| space = Initial | space = Initial | |||
| for pn_space in [ Handshake, ApplicatonData ]: | for pn_space in [ Handshake, ApplicationData ]: | |||
| if loss_time[pn_space] != 0 && | if loss_time[pn_space] != 0 && | |||
| (time == 0 || loss_time[pn_space] < time): | (time == 0 || loss_time[pn_space] < time): | |||
| time = loss_time[pn_space]; | time = loss_time[pn_space]; | |||
| space = pn_space | space = pn_space | |||
| return time, space | return time, space | |||
| SetLossDetectionTimer(): | SetLossDetectionTimer(): | |||
| // Don't arm timer if there are no ack-eliciting packets | ||||
| // in flight. | ||||
| if (no ack-eliciting packets in flight): | ||||
| loss_detection_timer.cancel() | ||||
| return | ||||
| loss_time, _ = GetEarliestLossTime() | loss_time, _ = GetEarliestLossTime() | |||
| if (loss_time != 0): | if (loss_time != 0): | |||
| // Time threshold loss detection. | // Time threshold loss detection. | |||
| loss_detection_timer.update(loss_time) | loss_detection_timer.update(loss_time) | |||
| return | return | |||
| if (crypto packets are in flight): | if (has unacknowledged crypto data | |||
| || endpoint is client without 1-RTT keys): | ||||
| // Crypto retransmission timer. | // Crypto retransmission timer. | |||
| if (smoothed_rtt == 0): | if (smoothed_rtt == 0): | |||
| timeout = 2 * kInitialRtt | timeout = 2 * kInitialRtt | |||
| else: | else: | |||
| timeout = 2 * smoothed_rtt | timeout = 2 * smoothed_rtt | |||
| timeout = max(timeout, kGranularity) | timeout = max(timeout, kGranularity) | |||
| timeout = timeout * (2 ^ crypto_count) | timeout = timeout * (2 ^ crypto_count) | |||
| loss_detection_timer.update( | loss_detection_timer.update( | |||
| time_of_last_sent_crypto_packet + timeout) | time_of_last_sent_crypto_packet + timeout) | |||
| return | return | |||
| // Don't arm timer if there are no ack-eliciting packets | ||||
| // in flight. | ||||
| if (no ack-eliciting packets in flight): | ||||
| loss_detection_timer.cancel() | ||||
| return | ||||
| // Calculate PTO duration | // Calculate PTO duration | |||
| timeout = | timeout = | |||
| smoothed_rtt + max(4 * rttvar, kGranularity) + max_ack_delay | smoothed_rtt + max(4 * rttvar, kGranularity) + max_ack_delay | |||
| timeout = timeout * (2 ^ pto_count) | timeout = timeout * (2 ^ pto_count) | |||
| loss_detection_timer.update( | loss_detection_timer.update( | |||
| time_of_last_sent_ack_eliciting_packet + timeout) | time_of_last_sent_ack_eliciting_packet + timeout) | |||
| A.9. On Timeout | A.9. On Timeout | |||
| skipping to change at page 29, line 18 ¶ | skipping to change at page 31, line 18 ¶ | |||
| the action to be performed. | the action to be performed. | |||
| Pseudocode for OnLossDetectionTimeout follows: | Pseudocode for OnLossDetectionTimeout follows: | |||
| OnLossDetectionTimeout(): | OnLossDetectionTimeout(): | |||
| loss_time, pn_space = GetEarliestLossTime() | loss_time, pn_space = GetEarliestLossTime() | |||
| if (loss_time != 0): | if (loss_time != 0): | |||
| // Time threshold loss Detection | // Time threshold loss Detection | |||
| DetectLostPackets(pn_space) | DetectLostPackets(pn_space) | |||
| // Retransmit crypto data if no packets were lost | // Retransmit crypto data if no packets were lost | |||
| // and there are still crypto packets in flight. | // and there is crypto data to retransmit. | |||
| else if (crypto packets are in flight): | else if (has unacknowledged crypto data): | |||
| // Crypto retransmission timeout. | // Crypto retransmission timeout. | |||
| RetransmitUnackedCryptoData() | RetransmitUnackedCryptoData() | |||
| crypto_count++ | crypto_count++ | |||
| else if (endpoint is client without 1-RTT keys): | ||||
| // Client sends an anti-deadlock packet: Initial is padded | ||||
| // to earn more anti-amplification credit, | ||||
| // a Handshake packet proves address ownership. | ||||
| if (has Handshake keys): | ||||
| SendOneHandshakePacket() | ||||
| else: | ||||
| SendOnePaddedInitialPacket() | ||||
| crypto_count++ | ||||
| else: | else: | |||
| // PTO | // PTO. Send new data if available, else retransmit old data. | |||
| // If neither is available, send a single PING frame. | ||||
| SendOneOrTwoPackets() | SendOneOrTwoPackets() | |||
| pto_count++ | pto_count++ | |||
| SetLossDetectionTimer() | SetLossDetectionTimer() | |||
| A.10. Detecting Lost Packets | A.10. Detecting Lost Packets | |||
| DetectLostPackets is called every time an ACK is received and | DetectLostPackets is called every time an ACK is received and | |||
| operates on the sent_packets for that packet number space. If the | operates on the sent_packets for that packet number space. | |||
| loss detection timer expires and the loss_time is set, the previous | ||||
| largest acknowledged packet is supplied. | ||||
| Pseudocode for DetectLostPackets follows: | Pseudocode for DetectLostPackets follows: | |||
| DetectLostPackets(pn_space): | DetectLostPackets(pn_space): | |||
| loss_time[pn_space] = 0 | loss_time[pn_space] = 0 | |||
| lost_packets = {} | lost_packets = {} | |||
| loss_delay = kTimeThreshold * max(latest_rtt, smoothed_rtt) | loss_delay = kTimeThreshold * max(latest_rtt, smoothed_rtt) | |||
| // Minimum time of kGranularity before packets are deemed lost. | ||||
| loss_delay = max(loss_delay, kGranularity) | ||||
| // Packets sent before this time are deemed lost. | // Packets sent before this time are deemed lost. | |||
| lost_send_time = now() - loss_delay | lost_send_time = now() - loss_delay | |||
| // Packets with packet numbers before this are deemed lost. | // Packets with packet numbers before this are deemed lost. | |||
| lost_pn = largest_acked_packet[pn_space] - kPacketThreshold | lost_pn = largest_acked_packet[pn_space] - kPacketThreshold | |||
| foreach unacked in sent_packets: | foreach unacked in sent_packets[pn_space]: | |||
| if (unacked.packet_number > largest_acked_packet[pn_space]): | if (unacked.packet_number > largest_acked_packet[pn_space]): | |||
| continue | continue | |||
| // Mark packet as lost, or set time when it should be marked. | // Mark packet as lost, or set time when it should be marked. | |||
| if (unacked.time_sent <= lost_send_time || | if (unacked.time_sent <= lost_send_time || | |||
| unacked.packet_number <= lost_pn): | unacked.packet_number <= lost_pn): | |||
| sent_packets.remove(unacked.packet_number) | sent_packets[pn_space].remove(unacked.packet_number) | |||
| if (unacked.in_flight): | if (unacked.in_flight): | |||
| lost_packets.insert(unacked) | lost_packets.insert(unacked) | |||
| else: | else: | |||
| if (loss_time[pn_space] == 0): | if (loss_time[pn_space] == 0): | |||
| loss_time[pn_space] = unacked.time_sent + loss_delay | loss_time[pn_space] = unacked.time_sent + loss_delay | |||
| else: | else: | |||
| loss_time[pn_space] = min(loss_time[pn_space], | loss_time[pn_space] = min(loss_time[pn_space], | |||
| unacked.time_sent + loss_delay) | unacked.time_sent + loss_delay) | |||
| // Inform the congestion controller of lost packets and | // Inform the congestion controller of lost packets and | |||
| skipping to change at page 31, line 17 ¶ | skipping to change at page 33, line 22 ¶ | |||
| account for the smaller 8 byte overhead of UDP vs 20 bytes for | account for the smaller 8 byte overhead of UDP vs 20 bytes for | |||
| TCP. The RECOMMENDED value is the minimum of 10 * | TCP. The RECOMMENDED value is the minimum of 10 * | |||
| kMaxDatagramSize and max(2* kMaxDatagramSize, 14720)). | kMaxDatagramSize and max(2* kMaxDatagramSize, 14720)). | |||
| kMinimumWindow: Minimum congestion window in bytes. The RECOMMENDED | kMinimumWindow: Minimum congestion window in bytes. The RECOMMENDED | |||
| value is 2 * kMaxDatagramSize. | value is 2 * kMaxDatagramSize. | |||
| kLossReductionFactor: Reduction in congestion window when a new loss | kLossReductionFactor: Reduction in congestion window when a new loss | |||
| event is detected. The RECOMMENDED value is 0.5. | event is detected. The RECOMMENDED value is 0.5. | |||
| kPersistentCongestionThreshold: Number of consecutive PTOs required | kPersistentCongestionThreshold: Period of time for persistent | |||
| for persistent congestion to be established. The rationale for | congestion to be established, specified as a PTO multiplier. The | |||
| this threshold is to enable a sender to use initial PTOs for | rationale for this threshold is to enable a sender to use initial | |||
| aggressive probing, as TCP does with Tail Loss Probe (TLP) [TLP] | PTOs for aggressive probing, as TCP does with Tail Loss Probe | |||
| [RACK], before establishing persistent congestion, as TCP does | (TLP) [TLP] [RACK], before establishing persistent congestion, as | |||
| with a Retransmission Timeout (RTO) [RFC5681]. The RECOMMENDED | TCP does with a Retransmission Timeout (RTO) [RFC5681]. The | |||
| value for kPersistentCongestionThreshold is 2, which is equivalent | RECOMMENDED value for kPersistentCongestionThreshold is 3, which | |||
| to having two TLPs before an RTO in TCP. | is approximately equivalent to having two TLPs before an RTO in | |||
| TCP. | ||||
| B.2. Variables of interest | B.2. Variables of interest | |||
| Variables required to implement the congestion control mechanisms are | Variables required to implement the congestion control mechanisms are | |||
| described in this section. | described in this section. | |||
| ecn_ce_counter: The highest value reported for the ECN-CE counter by | ecn_ce_counter: The highest value reported for the ECN-CE counter by | |||
| the peer in an ACK frame. This variable is used to detect | the peer in an ACK frame. This variable is used to detect | |||
| increases in the reported ECN-CE counter. | increases in the reported ECN-CE counter. | |||
| skipping to change at page 31, line 46 ¶ | skipping to change at page 34, line 5 ¶ | |||
| that contain at least one ack-eliciting or PADDING frame, and have | that contain at least one ack-eliciting or PADDING frame, and have | |||
| not been acked or declared lost. The size does not include IP or | not been acked or declared lost. The size does not include IP or | |||
| UDP overhead, but does include the QUIC header and AEAD overhead. | UDP overhead, but does include the QUIC header and AEAD overhead. | |||
| Packets only containing ACK frames do not count towards | Packets only containing ACK frames do not count towards | |||
| bytes_in_flight to ensure congestion control does not impede | bytes_in_flight to ensure congestion control does not impede | |||
| congestion feedback. | congestion feedback. | |||
| congestion_window: Maximum number of bytes-in-flight that may be | congestion_window: Maximum number of bytes-in-flight that may be | |||
| sent. | sent. | |||
| recovery_start_time: The time when QUIC first detects a loss, | congestion_recovery_start_time: The time when QUIC first detects | |||
| causing it to enter recovery. When a packet sent after this time | congestion due to loss or ECN, causing it to enter congestion | |||
| is acknowledged, QUIC exits recovery. | recovery. When a packet sent after this time is acknowledged, | |||
| QUIC exits congestion recovery. | ||||
| ssthresh: Slow start threshold in bytes. When the congestion window | ssthresh: Slow start threshold in bytes. When the congestion window | |||
| is below ssthresh, the mode is slow start and the window grows by | is below ssthresh, the mode is slow start and the window grows by | |||
| the number of bytes acknowledged. | the number of bytes acknowledged. | |||
| B.3. Initialization | B.3. Initialization | |||
| At the beginning of the connection, initialize the congestion control | At the beginning of the connection, initialize the congestion control | |||
| variables as follows: | variables as follows: | |||
| congestion_window = kInitialWindow | congestion_window = kInitialWindow | |||
| bytes_in_flight = 0 | bytes_in_flight = 0 | |||
| recovery_start_time = 0 | congestion_recovery_start_time = 0 | |||
| ssthresh = infinite | ssthresh = infinite | |||
| ecn_ce_counter = 0 | ecn_ce_counter = 0 | |||
| B.4. On Packet Sent | B.4. On Packet Sent | |||
| Whenever a packet is sent, and it contains non-ACK frames, the packet | Whenever a packet is sent, and it contains non-ACK frames, the packet | |||
| increases bytes_in_flight. | increases bytes_in_flight. | |||
| OnPacketSentCC(bytes_sent): | OnPacketSentCC(bytes_sent): | |||
| bytes_in_flight += bytes_sent | bytes_in_flight += bytes_sent | |||
| B.5. On Packet Acknowledgement | B.5. On Packet Acknowledgement | |||
| Invoked from loss detection's OnPacketAcked and is supplied with the | Invoked from loss detection's OnPacketAcked and is supplied with the | |||
| acked_packet from sent_packets. | acked_packet from sent_packets. | |||
| InRecovery(sent_time): | InCongestionRecovery(sent_time): | |||
| return sent_time <= recovery_start_time | return sent_time <= congestion_recovery_start_time | |||
| OnPacketAckedCC(acked_packet): | OnPacketAckedCC(acked_packet): | |||
| // Remove from bytes_in_flight. | // Remove from bytes_in_flight. | |||
| bytes_in_flight -= acked_packet.size | bytes_in_flight -= acked_packet.size | |||
| if (InRecovery(acked_packet.time_sent)): | if (InCongestionRecovery(acked_packet.time_sent)): | |||
| // Do not increase congestion window in recovery period. | // Do not increase congestion window in recovery period. | |||
| return | return | |||
| if (IsAppLimited()) | if (IsAppLimited()) | |||
| // Do not increase congestion_window if application | // Do not increase congestion_window if application | |||
| // limited. | // limited. | |||
| return | return | |||
| if (congestion_window < ssthresh): | if (congestion_window < ssthresh): | |||
| // Slow start. | // Slow start. | |||
| congestion_window += acked_packet.size | congestion_window += acked_packet.size | |||
| else: | else: | |||
| skipping to change at page 33, line 12 ¶ | skipping to change at page 35, line 33 ¶ | |||
| congestion_window += kMaxDatagramSize * acked_packet.size | congestion_window += kMaxDatagramSize * acked_packet.size | |||
| / congestion_window | / congestion_window | |||
| B.6. On New Congestion Event | B.6. On New Congestion Event | |||
| Invoked from ProcessECN and OnPacketsLost when a new congestion event | Invoked from ProcessECN and OnPacketsLost when a new congestion event | |||
| is detected. May start a new recovery period and reduces the | is detected. May start a new recovery period and reduces the | |||
| congestion window. | congestion window. | |||
| CongestionEvent(sent_time): | CongestionEvent(sent_time): | |||
| // Start a new congestion event if the sent time is larger | // Start a new congestion event if packet was sent after the | |||
| // than the start time of the previous recovery epoch. | // start of the previous congestion recovery period. | |||
| if (!InRecovery(sent_time)): | if (!InCongestionRecovery(sent_time)): | |||
| recovery_start_time = Now() | congestion_recovery_start_time = Now() | |||
| congestion_window *= kLossReductionFactor | congestion_window *= kLossReductionFactor | |||
| congestion_window = max(congestion_window, kMinimumWindow) | congestion_window = max(congestion_window, kMinimumWindow) | |||
| ssthresh = congestion_window | ssthresh = congestion_window | |||
| B.7. Process ECN Information | B.7. Process ECN Information | |||
| Invoked when an ACK frame with an ECN section is received from the | Invoked when an ACK frame with an ECN section is received from the | |||
| peer. | peer. | |||
| ProcessECN(ack): | ProcessECN(ack): | |||
| // If the ECN-CE counter reported by the peer has increased, | // If the ECN-CE counter reported by the peer has increased, | |||
| // this could be a new congestion event. | // this could be a new congestion event. | |||
| if (ack.ce_counter > ecn_ce_counter): | if (ack.ce_counter > ecn_ce_counter): | |||
| ecn_ce_counter = ack.ce_counter | ecn_ce_counter = ack.ce_counter | |||
| // Start a new congestion event if the last acknowledged | ||||
| // packet was sent after the start of the previous | ||||
| // recovery epoch. | ||||
| CongestionEvent(sent_packets[ack.largest_acked].time_sent) | CongestionEvent(sent_packets[ack.largest_acked].time_sent) | |||
| B.8. On Packets Lost | B.8. On Packets Lost | |||
| Invoked by loss detection from DetectLostPackets when new packets are | Invoked from DetectLostPackets when packets are deemed lost. | |||
| detected lost. | ||||
| InPersistentCongestion(largest_lost_packet): | InPersistentCongestion(largest_lost_packet): | |||
| pto = smoothed_rtt + max(4 * rttvar, kGranularity) + | pto = smoothed_rtt + max(4 * rttvar, kGranularity) + | |||
| max_ack_delay | max_ack_delay | |||
| congestion_period = | congestion_period = pto * kPersistentCongestionThreshold | |||
| pto * (2 ^ kPersistentCongestionThreshold - 1) | ||||
| // Determine if all packets in the window before the | // Determine if all packets in the window before the | |||
| // newest lost packet, including the edges, are marked | // newest lost packet, including the edges, are marked | |||
| // lost | // lost | |||
| return IsWindowLost(largest_lost_packet, congestion_period) | return IsWindowLost(largest_lost_packet, congestion_period) | |||
| OnPacketsLost(lost_packets): | OnPacketsLost(lost_packets): | |||
| // Remove lost packets from bytes_in_flight. | // Remove lost packets from bytes_in_flight. | |||
| for (lost_packet : lost_packets): | for (lost_packet : lost_packets): | |||
| bytes_in_flight -= lost_packet.size | bytes_in_flight -= lost_packet.size | |||
| largest_lost_packet = lost_packets.last() | largest_lost_packet = lost_packets.last() | |||
| // Start a new congestion epoch if the last lost packet | ||||
| // is past the end of the previous recovery epoch. | ||||
| CongestionEvent(largest_lost_packet.time_sent) | CongestionEvent(largest_lost_packet.time_sent) | |||
| // Collapse congestion window if persistent congestion | // Collapse congestion window if persistent congestion | |||
| if (InPersistentCongestion(largest_lost_packet)): | if (InPersistentCongestion(largest_lost_packet)): | |||
| congestion_window = kMinimumWindow | congestion_window = kMinimumWindow | |||
| Appendix C. Change Log | Appendix C. Change Log | |||
| *RFC Editor's Note:* Please remove this section prior to | *RFC Editor's Note:* Please remove this section prior to | |||
| publication of a final version of this document. | publication of a final version of this document. | |||
| Issue and pull request numbers are listed with a leading octothorp. | Issue and pull request numbers are listed with a leading octothorp. | |||
| C.1. Since draft-ietf-quic-recovery-18 | C.1. Since draft-ietf-quic-recovery-19 | |||
| o Send a PING if the PTO timer fires and there's nothing to send | ||||
| (#2624) | ||||
| o Set loss delay to at least kGranularity (#2617) | ||||
| o Merge application limited and sending after idle sections. Always | ||||
| limit burst size instead of requiring resetting CWND to initial | ||||
| CWND after idle (#2605) | ||||
| o Rewrite RTT estimation, allow RTT samples where a newly acked | ||||
| packet is ack-eliciting but the largest_acked is not (#2592) | ||||
| o Don't arm the handshake timer if there is no handshake data | ||||
| (#2590) | ||||
| o Clarify that the time threshold loss alarm takes precedence over | ||||
| the crypto handshake timer (#2590, #2620) | ||||
| o Change initial RTT to 500ms to align with RFC6298 (#2184) | ||||
| C.2. Since draft-ietf-quic-recovery-18 | ||||
| o Change IW byte limit to 14720 from 14600 (#2494) | o Change IW byte limit to 14720 from 14600 (#2494) | |||
| o Update PTO calculation to match RFC6298 (#2480, #2489, #2490) | o Update PTO calculation to match RFC6298 (#2480, #2489, #2490) | |||
| o Improve loss detection's description of multiple packet number | o Improve loss detection's description of multiple packet number | |||
| spaces and pseudocode (#2485, #2451, #2417) | spaces and pseudocode (#2485, #2451, #2417) | |||
| o Declare persistent congestion even if non-probe packets are sent | o Declare persistent congestion even if non-probe packets are sent | |||
| and don't make persistent congestion more aggressive than RTO | and don't make persistent congestion more aggressive than RTO | |||
| verified was (#2365, #2244) | verified was (#2365, #2244) | |||
| o Move pseudocode to the appendices (#2408) | o Move pseudocode to the appendices (#2408) | |||
| o What to send on multiple PTOs (#2380) | o What to send on multiple PTOs (#2380) | |||
| C.2. Since draft-ietf-quic-recovery-17 | C.3. Since draft-ietf-quic-recovery-17 | |||
| o After Probe Timeout discard in-flight packets or send another | o After Probe Timeout discard in-flight packets or send another | |||
| (#2212, #1965) | (#2212, #1965) | |||
| o Endpoints discard initial keys as soon as handshake keys are | o Endpoints discard initial keys as soon as handshake keys are | |||
| available (#1951, #2045) | available (#1951, #2045) | |||
| o 0-RTT state is discarded when 0-RTT is rejected (#2300) | o 0-RTT state is discarded when 0-RTT is rejected (#2300) | |||
| o Loss detection timer is cancelled when ack-eliciting frames are in | o Loss detection timer is cancelled when ack-eliciting frames are in | |||
| skipping to change at page 35, line 31 ¶ | skipping to change at page 38, line 5 ¶ | |||
| controller (#2138, 2187) | controller (#2138, 2187) | |||
| o Process ECN counts before marking packets lost (#2142) | o Process ECN counts before marking packets lost (#2142) | |||
| o Mark packets lost before resetting crypto_count and pto_count | o Mark packets lost before resetting crypto_count and pto_count | |||
| (#2208, #2209) | (#2208, #2209) | |||
| o Congestion and loss recovery state are discarded when keys are | o Congestion and loss recovery state are discarded when keys are | |||
| discarded (#2327) | discarded (#2327) | |||
| C.3. Since draft-ietf-quic-recovery-16 | C.4. Since draft-ietf-quic-recovery-16 | |||
| o Unify TLP and RTO into a single PTO; eliminate min RTO, min TLP | o Unify TLP and RTO into a single PTO; eliminate min RTO, min TLP | |||
| and min crypto timeouts; eliminate timeout validation (#2114, | and min crypto timeouts; eliminate timeout validation (#2114, | |||
| #2166, #2168, #1017) | #2166, #2168, #1017) | |||
| o Redefine how congestion avoidance in terms of when the period | o Redefine how congestion avoidance in terms of when the period | |||
| starts (#1928, #1930) | starts (#1928, #1930) | |||
| o Document what needs to be tracked for packets that are in flight | o Document what needs to be tracked for packets that are in flight | |||
| (#765, #1724, #1939) | (#765, #1724, #1939) | |||
| skipping to change at page 36, line 4 ¶ | skipping to change at page 38, line 27 ¶ | |||
| o Integrate both time and packet thresholds into loss detection | o Integrate both time and packet thresholds into loss detection | |||
| (#1969, #1212, #934, #1974) | (#1969, #1212, #934, #1974) | |||
| o Reduce congestion window after idle, unless pacing is used (#2007, | o Reduce congestion window after idle, unless pacing is used (#2007, | |||
| #2023) | #2023) | |||
| o Disable RTT calculation for packets that don't elicit | o Disable RTT calculation for packets that don't elicit | |||
| acknowledgment (#2060, #2078) | acknowledgment (#2060, #2078) | |||
| o Limit ack_delay by max_ack_delay (#2060, #2099) | o Limit ack_delay by max_ack_delay (#2060, #2099) | |||
| o Initial keys are discarded once Handshake are avaialble (#1951, | o Initial keys are discarded once Handshake are avaialble (#1951, | |||
| #2045) | #2045) | |||
| o Reorder ECN and loss detection in pseudocode (#2142) | o Reorder ECN and loss detection in pseudocode (#2142) | |||
| o Only cancel loss detection timer if ack-eliciting packets are in | o Only cancel loss detection timer if ack-eliciting packets are in | |||
| flight (#2093, #2117) | flight (#2093, #2117) | |||
| C.4. Since draft-ietf-quic-recovery-14 | C.5. Since draft-ietf-quic-recovery-14 | |||
| o Used max_ack_delay from transport params (#1796, #1782) | o Used max_ack_delay from transport params (#1796, #1782) | |||
| o Merge ACK and ACK_ECN (#1783) | o Merge ACK and ACK_ECN (#1783) | |||
| C.5. Since draft-ietf-quic-recovery-13 | C.6. Since draft-ietf-quic-recovery-13 | |||
| o Corrected the lack of ssthresh reduction in CongestionEvent | o Corrected the lack of ssthresh reduction in CongestionEvent | |||
| pseudocode (#1598) | pseudocode (#1598) | |||
| o Considerations for ECN spoofing (#1426, #1626) | o Considerations for ECN spoofing (#1426, #1626) | |||
| o Clarifications for PADDING and congestion control (#837, #838, | o Clarifications for PADDING and congestion control (#837, #838, | |||
| #1517, #1531, #1540) | #1517, #1531, #1540) | |||
| o Reduce early retransmission timer to RTT/8 (#945, #1581) | o Reduce early retransmission timer to RTT/8 (#945, #1581) | |||
| skipping to change at page 36, line 29 ¶ | skipping to change at page 39, line 4 ¶ | |||
| o Corrected the lack of ssthresh reduction in CongestionEvent | o Corrected the lack of ssthresh reduction in CongestionEvent | |||
| pseudocode (#1598) | pseudocode (#1598) | |||
| o Considerations for ECN spoofing (#1426, #1626) | o Considerations for ECN spoofing (#1426, #1626) | |||
| o Clarifications for PADDING and congestion control (#837, #838, | o Clarifications for PADDING and congestion control (#837, #838, | |||
| #1517, #1531, #1540) | #1517, #1531, #1540) | |||
| o Reduce early retransmission timer to RTT/8 (#945, #1581) | o Reduce early retransmission timer to RTT/8 (#945, #1581) | |||
| o Packets are declared lost after an RTO is verified (#935, #1582) | o Packets are declared lost after an RTO is verified (#935, #1582) | |||
| C.6. Since draft-ietf-quic-recovery-12 | C.7. Since draft-ietf-quic-recovery-12 | |||
| o Changes to manage separate packet number spaces and encryption | o Changes to manage separate packet number spaces and encryption | |||
| levels (#1190, #1242, #1413, #1450) | levels (#1190, #1242, #1413, #1450) | |||
| o Added ECN feedback mechanisms and handling; new ACK_ECN frame | o Added ECN feedback mechanisms and handling; new ACK_ECN frame | |||
| (#804, #805, #1372) | (#804, #805, #1372) | |||
| C.7. Since draft-ietf-quic-recovery-11 | C.8. Since draft-ietf-quic-recovery-11 | |||
| No significant changes. | No significant changes. | |||
| C.8. Since draft-ietf-quic-recovery-10 | C.9. Since draft-ietf-quic-recovery-10 | |||
| o Improved text on ack generation (#1139, #1159) | o Improved text on ack generation (#1139, #1159) | |||
| o Make references to TCP recovery mechanisms informational (#1195) | o Make references to TCP recovery mechanisms informational (#1195) | |||
| o Define time_of_last_sent_handshake_packet (#1171) | o Define time_of_last_sent_handshake_packet (#1171) | |||
| o Added signal from TLS the data it includes needs to be sent in a | o Added signal from TLS the data it includes needs to be sent in a | |||
| Retry packet (#1061, #1199) | Retry packet (#1061, #1199) | |||
| o Minimum RTT (min_rtt) is initialized with an infinite value | o Minimum RTT (min_rtt) is initialized with an infinite value | |||
| (#1169) | (#1169) | |||
| C.9. Since draft-ietf-quic-recovery-09 | C.10. Since draft-ietf-quic-recovery-09 | |||
| No significant changes. | No significant changes. | |||
| C.10. Since draft-ietf-quic-recovery-08 | C.11. Since draft-ietf-quic-recovery-08 | |||
| o Clarified pacing and RTO (#967, #977) | o Clarified pacing and RTO (#967, #977) | |||
| C.11. Since draft-ietf-quic-recovery-07 | C.12. Since draft-ietf-quic-recovery-07 | |||
| o Include Ack Delay in RTO(and TLP) computations (#981) | o Include Ack Delay in RTO(and TLP) computations (#981) | |||
| o Ack Delay in SRTT computation (#961) | o Ack Delay in SRTT computation (#961) | |||
| o Default RTT and Slow Start (#590) | o Default RTT and Slow Start (#590) | |||
| o Many editorial fixes. | o Many editorial fixes. | |||
| C.12. Since draft-ietf-quic-recovery-06 | C.13. Since draft-ietf-quic-recovery-06 | |||
| No significant changes. | No significant changes. | |||
| C.13. Since draft-ietf-quic-recovery-05 | C.14. Since draft-ietf-quic-recovery-05 | |||
| o Add more congestion control text (#776) | o Add more congestion control text (#776) | |||
| C.14. Since draft-ietf-quic-recovery-04 | C.15. Since draft-ietf-quic-recovery-04 | |||
| No significant changes. | No significant changes. | |||
| C.15. Since draft-ietf-quic-recovery-03 | C.16. Since draft-ietf-quic-recovery-03 | |||
| No significant changes. | No significant changes. | |||
| C.16. Since draft-ietf-quic-recovery-02 | C.17. Since draft-ietf-quic-recovery-02 | |||
| o Integrate F-RTO (#544, #409) | o Integrate F-RTO (#544, #409) | |||
| o Add congestion control (#545, #395) | o Add congestion control (#545, #395) | |||
| o Require connection abort if a skipped packet was acknowledged | o Require connection abort if a skipped packet was acknowledged | |||
| (#415) | (#415) | |||
| o Simplify RTO calculations (#142, #417) | o Simplify RTO calculations (#142, #417) | |||
| C.17. Since draft-ietf-quic-recovery-01 | C.18. Since draft-ietf-quic-recovery-01 | |||
| o Overview added to loss detection | o Overview added to loss detection | |||
| o Changes initial default RTT to 100ms | o Changes initial default RTT to 100ms | |||
| o Added time-based loss detection and fixes early retransmit | o Added time-based loss detection and fixes early retransmit | |||
| o Clarified loss recovery for handshake packets | o Clarified loss recovery for handshake packets | |||
| o Fixed references and made TCP references informative | o Fixed references and made TCP references informative | |||
| C.18. Since draft-ietf-quic-recovery-00 | C.19. Since draft-ietf-quic-recovery-00 | |||
| o Improved description of constants and ACK behavior | o Improved description of constants and ACK behavior | |||
| C.19. Since draft-iyengar-quic-loss-recovery-01 | C.20. Since draft-iyengar-quic-loss-recovery-01 | |||
| o Adopted as base for draft-ietf-quic-recovery | o Adopted as base for draft-ietf-quic-recovery | |||
| o Updated authors/editors list | o Updated authors/editors list | |||
| o Added table of contents | o Added table of contents | |||
| Acknowledgments | Acknowledgments | |||
| Authors' Addresses | Authors' Addresses | |||
| Jana Iyengar (editor) | Jana Iyengar (editor) | |||
| Fastly | Fastly | |||
| Email: jri.ietf@gmail.com | Email: jri.ietf@gmail.com | |||
| End of changes. 92 change blocks. | ||||
| 282 lines changed or deleted | 434 lines changed or added | |||
This html diff was produced by rfcdiff 1.45. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||