QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "net/third_party/quiche/src/quic/core/quic_received_packet_manager.h" |
| 6 | |
| 7 | #include <algorithm> |
| 8 | #include <limits> |
| 9 | #include <utility> |
| 10 | |
| 11 | #include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h" |
| 12 | #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" |
| 13 | #include "net/third_party/quiche/src/quic/core/quic_connection_stats.h" |
| 14 | #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" |
ianswett | 95cf383 | 2020-01-21 07:58:25 -0800 | [diff] [blame] | 15 | #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 16 | #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" |
| 17 | |
| 18 | namespace quic { |
| 19 | |
| 20 | namespace { |
| 21 | |
| 22 | // The maximum number of packets to ack immediately after a missing packet for |
| 23 | // fast retransmission to kick in at the sender. This limit is created to |
| 24 | // reduce the number of acks sent that have no benefit for fast retransmission. |
| 25 | // Set to the number of nacks needed for fast retransmit plus one for protection |
| 26 | // against an ack loss |
| 27 | const size_t kMaxPacketsAfterNewMissing = 4; |
| 28 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 29 | // One eighth RTT delay when doing ack decimation. |
| 30 | const float kShortAckDecimationDelay = 0.125; |
| 31 | } // namespace |
| 32 | |
QUICHE team | 1dfa46b | 2019-03-22 10:39:10 -0700 | [diff] [blame] | 33 | QuicReceivedPacketManager::QuicReceivedPacketManager() |
| 34 | : QuicReceivedPacketManager(nullptr) {} |
| 35 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 36 | QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats) |
| 37 | : ack_frame_updated_(false), |
| 38 | max_ack_ranges_(0), |
| 39 | time_largest_observed_(QuicTime::Zero()), |
| 40 | save_timestamps_(false), |
| 41 | stats_(stats), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 42 | num_retransmittable_packets_received_since_last_ack_sent_(0), |
| 43 | min_received_before_ack_decimation_(kMinReceivedBeforeAckDecimation), |
haoyuewang | e7415a5 | 2020-07-27 17:12:26 -0700 | [diff] [blame] | 44 | ack_frequency_(kDefaultRetransmittablePacketsBeforeAck), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 45 | ack_decimation_delay_(kAckDecimationDelay), |
| 46 | unlimited_ack_decimation_(false), |
ianswett | 95cf383 | 2020-01-21 07:58:25 -0800 | [diff] [blame] | 47 | one_immediate_ack_(false), |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 48 | ignore_order_(false), |
ianswett | 309987e | 2019-08-02 13:16:26 -0700 | [diff] [blame] | 49 | local_max_ack_delay_( |
| 50 | QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 51 | ack_timeout_(QuicTime::Zero()), |
| 52 | time_of_previous_received_packet_(QuicTime::Zero()), |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 53 | was_last_packet_missing_(false), |
| 54 | last_ack_frequency_frame_sequence_number_(-1) {} |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 55 | |
| 56 | QuicReceivedPacketManager::~QuicReceivedPacketManager() {} |
| 57 | |
| 58 | void QuicReceivedPacketManager::SetFromConfig(const QuicConfig& config, |
| 59 | Perspective perspective) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 60 | if (config.HasClientSentConnectionOption(kAKD3, perspective)) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 61 | ack_decimation_delay_ = kShortAckDecimationDelay; |
| 62 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 63 | if (config.HasClientSentConnectionOption(kAKDU, perspective)) { |
| 64 | unlimited_ack_decimation_ = true; |
| 65 | } |
ianswett | ba59483 | 2020-03-09 08:53:15 -0700 | [diff] [blame] | 66 | if (config.HasClientSentConnectionOption(k1ACK, perspective)) { |
ianswett | 95cf383 | 2020-01-21 07:58:25 -0800 | [diff] [blame] | 67 | one_immediate_ack_ = true; |
| 68 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | void QuicReceivedPacketManager::RecordPacketReceived( |
| 72 | const QuicPacketHeader& header, |
| 73 | QuicTime receipt_time) { |
| 74 | const QuicPacketNumber packet_number = header.packet_number; |
| 75 | DCHECK(IsAwaitingPacket(packet_number)) << " packet_number:" << packet_number; |
fayang | f477f73 | 2019-06-20 07:03:06 -0700 | [diff] [blame] | 76 | was_last_packet_missing_ = IsMissing(packet_number); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 77 | if (!ack_frame_updated_) { |
| 78 | ack_frame_.received_packet_times.clear(); |
| 79 | } |
| 80 | ack_frame_updated_ = true; |
| 81 | |
| 82 | if (LargestAcked(ack_frame_).IsInitialized() && |
| 83 | LargestAcked(ack_frame_) > packet_number) { |
| 84 | // Record how out of order stats. |
| 85 | ++stats_->packets_reordered; |
| 86 | stats_->max_sequence_reordering = |
| 87 | std::max(stats_->max_sequence_reordering, |
| 88 | LargestAcked(ack_frame_) - packet_number); |
| 89 | int64_t reordering_time_us = |
| 90 | (receipt_time - time_largest_observed_).ToMicroseconds(); |
| 91 | stats_->max_time_reordering_us = |
| 92 | std::max(stats_->max_time_reordering_us, reordering_time_us); |
| 93 | } |
| 94 | if (!LargestAcked(ack_frame_).IsInitialized() || |
| 95 | packet_number > LargestAcked(ack_frame_)) { |
| 96 | ack_frame_.largest_acked = packet_number; |
| 97 | time_largest_observed_ = receipt_time; |
| 98 | } |
| 99 | ack_frame_.packets.Add(packet_number); |
| 100 | |
| 101 | if (save_timestamps_) { |
| 102 | // The timestamp format only handles packets in time order. |
| 103 | if (!ack_frame_.received_packet_times.empty() && |
| 104 | ack_frame_.received_packet_times.back().second > receipt_time) { |
dschinazi | 87c39c1 | 2019-05-07 21:01:12 -0700 | [diff] [blame] | 105 | QUIC_LOG(WARNING) |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 106 | << "Receive time went backwards from: " |
| 107 | << ack_frame_.received_packet_times.back().second.ToDebuggingValue() |
| 108 | << " to " << receipt_time.ToDebuggingValue(); |
| 109 | } else { |
| 110 | ack_frame_.received_packet_times.push_back( |
| 111 | std::make_pair(packet_number, receipt_time)); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | if (least_received_packet_number_.IsInitialized()) { |
| 116 | least_received_packet_number_ = |
| 117 | std::min(least_received_packet_number_, packet_number); |
| 118 | } else { |
| 119 | least_received_packet_number_ = packet_number; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) { |
| 124 | return LargestAcked(ack_frame_).IsInitialized() && |
| 125 | packet_number < LargestAcked(ack_frame_) && |
| 126 | !ack_frame_.packets.Contains(packet_number); |
| 127 | } |
| 128 | |
| 129 | bool QuicReceivedPacketManager::IsAwaitingPacket( |
QUICHE team | b23daa7 | 2019-03-21 08:37:48 -0700 | [diff] [blame] | 130 | QuicPacketNumber packet_number) const { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 131 | return quic::IsAwaitingPacket(ack_frame_, packet_number, |
| 132 | peer_least_packet_awaiting_ack_); |
| 133 | } |
| 134 | |
| 135 | const QuicFrame QuicReceivedPacketManager::GetUpdatedAckFrame( |
| 136 | QuicTime approximate_now) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 137 | if (time_largest_observed_ == QuicTime::Zero()) { |
| 138 | // We have received no packets. |
| 139 | ack_frame_.ack_delay_time = QuicTime::Delta::Infinite(); |
| 140 | } else { |
| 141 | // Ensure the delta is zero if approximate now is "in the past". |
| 142 | ack_frame_.ack_delay_time = approximate_now < time_largest_observed_ |
| 143 | ? QuicTime::Delta::Zero() |
| 144 | : approximate_now - time_largest_observed_; |
| 145 | } |
| 146 | while (max_ack_ranges_ > 0 && |
| 147 | ack_frame_.packets.NumIntervals() > max_ack_ranges_) { |
| 148 | ack_frame_.packets.RemoveSmallestInterval(); |
| 149 | } |
| 150 | // Clear all packet times if any are too far from largest observed. |
| 151 | // It's expected this is extremely rare. |
| 152 | for (auto it = ack_frame_.received_packet_times.begin(); |
| 153 | it != ack_frame_.received_packet_times.end();) { |
| 154 | if (LargestAcked(ack_frame_) - it->first >= |
| 155 | std::numeric_limits<uint8_t>::max()) { |
| 156 | it = ack_frame_.received_packet_times.erase(it); |
| 157 | } else { |
| 158 | ++it; |
| 159 | } |
| 160 | } |
| 161 | |
dschinazi | 440ea72 | 2020-08-26 18:21:54 -0700 | [diff] [blame] | 162 | #if QUIC_FRAME_DEBUG |
| 163 | QuicFrame frame = QuicFrame(&ack_frame_); |
| 164 | frame.delete_forbidden = true; |
| 165 | return frame; |
| 166 | #else // QUIC_FRAME_DEBUG |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 167 | return QuicFrame(&ack_frame_); |
dschinazi | 440ea72 | 2020-08-26 18:21:54 -0700 | [diff] [blame] | 168 | #endif // QUIC_FRAME_DEBUG |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | void QuicReceivedPacketManager::DontWaitForPacketsBefore( |
| 172 | QuicPacketNumber least_unacked) { |
| 173 | if (!least_unacked.IsInitialized()) { |
| 174 | return; |
| 175 | } |
| 176 | // ValidateAck() should fail if peer_least_packet_awaiting_ack shrinks. |
| 177 | DCHECK(!peer_least_packet_awaiting_ack_.IsInitialized() || |
| 178 | peer_least_packet_awaiting_ack_ <= least_unacked); |
| 179 | if (!peer_least_packet_awaiting_ack_.IsInitialized() || |
| 180 | least_unacked > peer_least_packet_awaiting_ack_) { |
| 181 | peer_least_packet_awaiting_ack_ = least_unacked; |
| 182 | bool packets_updated = ack_frame_.packets.RemoveUpTo(least_unacked); |
| 183 | if (packets_updated) { |
| 184 | // Ack frame gets updated because packets set is updated because of stop |
| 185 | // waiting frame. |
| 186 | ack_frame_updated_ = true; |
| 187 | } |
| 188 | } |
| 189 | DCHECK(ack_frame_.packets.Empty() || |
| 190 | !peer_least_packet_awaiting_ack_.IsInitialized() || |
| 191 | ack_frame_.packets.Min() >= peer_least_packet_awaiting_ack_); |
| 192 | } |
| 193 | |
haoyuewang | e7415a5 | 2020-07-27 17:12:26 -0700 | [diff] [blame] | 194 | QuicTime::Delta QuicReceivedPacketManager::GetMaxAckDelay( |
| 195 | QuicPacketNumber last_received_packet_number, |
| 196 | const RttStats& rtt_stats) const { |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 197 | if (AckFrequencyFrameReceived() || |
| 198 | last_received_packet_number < PeerFirstSendingPacketNumber() + |
| 199 | min_received_before_ack_decimation_) { |
haoyuewang | e7415a5 | 2020-07-27 17:12:26 -0700 | [diff] [blame] | 200 | return local_max_ack_delay_; |
| 201 | } |
| 202 | |
| 203 | // Wait for the minimum of the ack decimation delay or the delayed ack time |
| 204 | // before sending an ack. |
| 205 | QuicTime::Delta ack_delay = std::min( |
| 206 | local_max_ack_delay_, rtt_stats.min_rtt() * ack_decimation_delay_); |
| 207 | if (GetQuicReloadableFlag(quic_ack_delay_alarm_granularity)) { |
| 208 | QUIC_RELOADABLE_FLAG_COUNT(quic_ack_delay_alarm_granularity); |
| 209 | ack_delay = std::max(ack_delay, kAlarmGranularity); |
| 210 | } |
| 211 | return ack_delay; |
| 212 | } |
| 213 | |
| 214 | void QuicReceivedPacketManager::MaybeUpdateAckFrequency( |
| 215 | QuicPacketNumber last_received_packet_number) { |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 216 | if (AckFrequencyFrameReceived()) { |
| 217 | // Skip Ack Decimation below after receiving an AckFrequencyFrame from the |
| 218 | // other end point. |
| 219 | return; |
| 220 | } |
haoyuewang | e7415a5 | 2020-07-27 17:12:26 -0700 | [diff] [blame] | 221 | if (last_received_packet_number < |
| 222 | PeerFirstSendingPacketNumber() + min_received_before_ack_decimation_) { |
| 223 | return; |
| 224 | } |
| 225 | ack_frequency_ = unlimited_ack_decimation_ |
| 226 | ? std::numeric_limits<size_t>::max() |
| 227 | : kMaxRetransmittablePacketsBeforeAck; |
| 228 | } |
| 229 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 230 | void QuicReceivedPacketManager::MaybeUpdateAckTimeout( |
| 231 | bool should_last_packet_instigate_acks, |
| 232 | QuicPacketNumber last_received_packet_number, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 233 | QuicTime now, |
ianswett | 309987e | 2019-08-02 13:16:26 -0700 | [diff] [blame] | 234 | const RttStats* rtt_stats) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 235 | if (!ack_frame_updated_) { |
| 236 | // ACK frame has not been updated, nothing to do. |
| 237 | return; |
| 238 | } |
| 239 | |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 240 | if (!ignore_order_ && was_last_packet_missing_ && |
| 241 | last_sent_largest_acked_.IsInitialized() && |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 242 | last_received_packet_number < last_sent_largest_acked_) { |
| 243 | // Only ack immediately if an ACK frame was sent with a larger largest acked |
| 244 | // than the newly received packet number. |
| 245 | ack_timeout_ = now; |
| 246 | return; |
| 247 | } |
| 248 | |
| 249 | if (!should_last_packet_instigate_acks) { |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | ++num_retransmittable_packets_received_since_last_ack_sent_; |
haoyuewang | e7415a5 | 2020-07-27 17:12:26 -0700 | [diff] [blame] | 254 | |
haoyuewang | 0cc998a | 2020-09-08 15:02:22 -0700 | [diff] [blame] | 255 | MaybeUpdateAckFrequency(last_received_packet_number); |
| 256 | if (num_retransmittable_packets_received_since_last_ack_sent_ >= |
| 257 | ack_frequency_) { |
| 258 | ack_timeout_ = now; |
haoyuewang | e7415a5 | 2020-07-27 17:12:26 -0700 | [diff] [blame] | 259 | return; |
| 260 | } |
| 261 | |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 262 | if (!ignore_order_ && HasNewMissingPackets()) { |
haoyuewang | 0cc998a | 2020-09-08 15:02:22 -0700 | [diff] [blame] | 263 | ack_timeout_ = now; |
| 264 | return; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 265 | } |
| 266 | |
haoyuewang | 0cc998a | 2020-09-08 15:02:22 -0700 | [diff] [blame] | 267 | MaybeUpdateAckTimeoutTo( |
| 268 | now + GetMaxAckDelay(last_received_packet_number, *rtt_stats)); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 269 | } |
| 270 | |
| 271 | void QuicReceivedPacketManager::ResetAckStates() { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 272 | ack_frame_updated_ = false; |
| 273 | ack_timeout_ = QuicTime::Zero(); |
| 274 | num_retransmittable_packets_received_since_last_ack_sent_ = 0; |
| 275 | last_sent_largest_acked_ = LargestAcked(ack_frame_); |
| 276 | } |
| 277 | |
| 278 | void QuicReceivedPacketManager::MaybeUpdateAckTimeoutTo(QuicTime time) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 279 | if (!ack_timeout_.IsInitialized() || ack_timeout_ > time) { |
| 280 | ack_timeout_ = time; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | bool QuicReceivedPacketManager::HasMissingPackets() const { |
| 285 | if (ack_frame_.packets.Empty()) { |
| 286 | return false; |
| 287 | } |
| 288 | if (ack_frame_.packets.NumIntervals() > 1) { |
| 289 | return true; |
| 290 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 291 | return peer_least_packet_awaiting_ack_.IsInitialized() && |
| 292 | ack_frame_.packets.Min() > peer_least_packet_awaiting_ack_; |
| 293 | } |
| 294 | |
| 295 | bool QuicReceivedPacketManager::HasNewMissingPackets() const { |
ianswett | 95cf383 | 2020-01-21 07:58:25 -0800 | [diff] [blame] | 296 | if (one_immediate_ack_) { |
| 297 | return HasMissingPackets() && ack_frame_.packets.LastIntervalLength() == 1; |
| 298 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 299 | return HasMissingPackets() && |
| 300 | ack_frame_.packets.LastIntervalLength() <= kMaxPacketsAfterNewMissing; |
| 301 | } |
| 302 | |
| 303 | bool QuicReceivedPacketManager::ack_frame_updated() const { |
| 304 | return ack_frame_updated_; |
| 305 | } |
| 306 | |
| 307 | QuicPacketNumber QuicReceivedPacketManager::GetLargestObserved() const { |
| 308 | return LargestAcked(ack_frame_); |
| 309 | } |
| 310 | |
| 311 | QuicPacketNumber QuicReceivedPacketManager::PeerFirstSendingPacketNumber() |
| 312 | const { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 313 | if (!least_received_packet_number_.IsInitialized()) { |
| 314 | QUIC_BUG << "No packets have been received yet"; |
| 315 | return QuicPacketNumber(1); |
| 316 | } |
| 317 | return least_received_packet_number_; |
| 318 | } |
| 319 | |
fayang | 5d92c41 | 2020-02-19 12:10:31 -0800 | [diff] [blame] | 320 | bool QuicReceivedPacketManager::IsAckFrameEmpty() const { |
| 321 | return ack_frame_.packets.Empty(); |
| 322 | } |
| 323 | |
haoyuewang | 2d2fdd1 | 2020-09-16 11:26:56 -0700 | [diff] [blame] | 324 | void QuicReceivedPacketManager::OnAckFrequencyFrame( |
| 325 | const QuicAckFrequencyFrame& frame) { |
| 326 | int64_t new_sequence_number = frame.sequence_number; |
| 327 | if (new_sequence_number <= last_ack_frequency_frame_sequence_number_) { |
| 328 | // Ignore old ACK_FREQUENCY frames. |
| 329 | return; |
| 330 | } |
| 331 | last_ack_frequency_frame_sequence_number_ = new_sequence_number; |
| 332 | ack_frequency_ = frame.packet_tolerance; |
| 333 | local_max_ack_delay_ = frame.max_ack_delay; |
| 334 | ignore_order_ = frame.ignore_order; |
| 335 | } |
| 336 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 337 | } // namespace quic |