blob: 859bf3939bccddbb073d426873d72254a84ed885 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2014 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_unacked_packet_map.h"
6
7#include <limits>
8#include <type_traits>
9
10#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
11#include "net/third_party/quiche/src/quic/core/quic_utils.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
14
15namespace quic {
16
17namespace {
18bool WillStreamFrameLengthSumWrapAround(QuicPacketLength lhs,
19 QuicPacketLength rhs) {
20 static_assert(
21 std::is_unsigned<QuicPacketLength>::value,
22 "This function assumes QuicPacketLength is an unsigned integer type.");
23 return std::numeric_limits<QuicPacketLength>::max() - lhs < rhs;
24}
25} // namespace
26
27QuicUnackedPacketMap::QuicUnackedPacketMap(Perspective perspective)
28 : perspective_(perspective),
29 least_unacked_(FirstSendingPacketNumber()),
30 bytes_in_flight_(0),
31 pending_crypto_packet_count_(0),
32 last_crypto_packet_sent_time_(QuicTime::Zero()),
33 session_notifier_(nullptr),
34 session_decides_what_to_write_(false),
35 use_uber_loss_algorithm_(
36 GetQuicReloadableFlag(quic_use_uber_loss_algorithm)) {
37 if (use_uber_loss_algorithm_) {
38 QUIC_RELOADABLE_FLAG_COUNT(quic_use_uber_loss_algorithm);
39 }
40}
41
42QuicUnackedPacketMap::~QuicUnackedPacketMap() {
43 for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
44 DeleteFrames(&(transmission_info.retransmittable_frames));
45 }
46}
47
48void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
49 QuicPacketNumber old_packet_number,
50 TransmissionType transmission_type,
51 QuicTime sent_time,
52 bool set_in_flight) {
53 QuicPacketNumber packet_number = packet->packet_number;
54 QuicPacketLength bytes_sent = packet->encrypted_length;
55 QUIC_BUG_IF(largest_sent_packet_.IsInitialized() &&
56 largest_sent_packet_ >= packet_number)
57 << "largest_sent_packet_: " << largest_sent_packet_
58 << ", packet_number: " << packet_number;
59 DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
60 while (least_unacked_ + unacked_packets_.size() < packet_number) {
61 unacked_packets_.push_back(QuicTransmissionInfo());
62 unacked_packets_.back().state = NEVER_SENT;
63 }
64
65 const bool has_crypto_handshake =
66 packet->has_crypto_handshake == IS_HANDSHAKE;
67 QuicTransmissionInfo info(
68 packet->encryption_level, packet->packet_number_length, transmission_type,
69 sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
70 info.largest_acked = packet->largest_acked;
71 if (packet->largest_acked.IsInitialized()) {
72 largest_sent_largest_acked_ =
73 largest_sent_largest_acked_.IsInitialized()
74 ? std::max(largest_sent_largest_acked_, packet->largest_acked)
75 : packet->largest_acked;
76 }
77 if (old_packet_number.IsInitialized()) {
78 TransferRetransmissionInfo(old_packet_number, packet_number,
79 transmission_type, &info);
80 }
81
82 largest_sent_packet_ = packet_number;
83 if (set_in_flight) {
84 bytes_in_flight_ += bytes_sent;
85 info.in_flight = true;
86 if (use_uber_loss_algorithm_) {
87 largest_sent_retransmittable_packets_[GetPacketNumberSpace(
88 info.encryption_level)] = packet_number;
89 } else {
90 largest_sent_retransmittable_packet_ = packet_number;
91 }
92 }
93 unacked_packets_.push_back(info);
94 // Swap the retransmittable frames to avoid allocations.
95 // TODO(ianswett): Could use emplace_back when Chromium can.
96 if (!old_packet_number.IsInitialized()) {
97 if (has_crypto_handshake) {
98 ++pending_crypto_packet_count_;
99 last_crypto_packet_sent_time_ = sent_time;
100 }
101
102 packet->retransmittable_frames.swap(
103 unacked_packets_.back().retransmittable_frames);
104 }
105}
106
107void QuicUnackedPacketMap::RemoveObsoletePackets() {
108 while (!unacked_packets_.empty()) {
109 if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) {
110 break;
111 }
112 if (session_decides_what_to_write_) {
113 DeleteFrames(&unacked_packets_.front().retransmittable_frames);
114 }
115 unacked_packets_.pop_front();
116 ++least_unacked_;
117 }
118}
119
120void QuicUnackedPacketMap::TransferRetransmissionInfo(
121 QuicPacketNumber old_packet_number,
122 QuicPacketNumber new_packet_number,
123 TransmissionType transmission_type,
124 QuicTransmissionInfo* info) {
125 if (old_packet_number < least_unacked_) {
126 // This can happen when a retransmission packet is queued because of write
127 // blocked socket, and the original packet gets acked before the
128 // retransmission gets sent.
129 return;
130 }
131 if (old_packet_number > largest_sent_packet_) {
132 QUIC_BUG << "Old QuicTransmissionInfo never existed for :"
133 << old_packet_number << " largest_sent:" << largest_sent_packet_;
134 return;
135 }
136 DCHECK_GE(new_packet_number, least_unacked_ + unacked_packets_.size());
137 DCHECK_NE(NOT_RETRANSMISSION, transmission_type);
138
139 QuicTransmissionInfo* transmission_info =
140 &unacked_packets_.at(old_packet_number - least_unacked_);
141 QuicFrames* frames = &transmission_info->retransmittable_frames;
142 if (session_notifier_ != nullptr) {
143 for (const QuicFrame& frame : *frames) {
144 if (frame.type == STREAM_FRAME) {
145 session_notifier_->OnStreamFrameRetransmitted(frame.stream_frame);
146 }
147 }
148 }
149
150 // Swap the frames and preserve num_padding_bytes and has_crypto_handshake.
151 frames->swap(info->retransmittable_frames);
152 info->has_crypto_handshake = transmission_info->has_crypto_handshake;
153 transmission_info->has_crypto_handshake = false;
154 info->num_padding_bytes = transmission_info->num_padding_bytes;
155
156 // Don't link old transmissions to new ones when version or
157 // encryption changes.
158 if (transmission_type == ALL_INITIAL_RETRANSMISSION ||
159 transmission_type == ALL_UNACKED_RETRANSMISSION) {
160 transmission_info->state = UNACKABLE;
161 } else {
162 transmission_info->retransmission = new_packet_number;
163 }
164 // Proactively remove obsolete packets so the least unacked can be raised.
165 RemoveObsoletePackets();
166}
167
168bool QuicUnackedPacketMap::HasRetransmittableFrames(
169 QuicPacketNumber packet_number) const {
170 DCHECK_GE(packet_number, least_unacked_);
171 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
172 return HasRetransmittableFrames(
173 unacked_packets_[packet_number - least_unacked_]);
174}
175
176bool QuicUnackedPacketMap::HasRetransmittableFrames(
177 const QuicTransmissionInfo& info) const {
178 if (!session_decides_what_to_write_) {
179 return !info.retransmittable_frames.empty();
180 }
181
182 if (!QuicUtils::IsAckable(info.state)) {
183 return false;
184 }
185
186 for (const auto& frame : info.retransmittable_frames) {
187 if (session_notifier_->IsFrameOutstanding(frame)) {
188 return true;
189 }
190 }
191 return false;
192}
193
194void QuicUnackedPacketMap::RemoveRetransmittability(
195 QuicTransmissionInfo* info) {
196 if (session_decides_what_to_write_) {
197 DeleteFrames(&info->retransmittable_frames);
198 info->retransmission.Clear();
199 return;
200 }
201 while (info->retransmission.IsInitialized()) {
202 const QuicPacketNumber retransmission = info->retransmission;
203 info->retransmission.Clear();
204 info = &unacked_packets_[retransmission - least_unacked_];
205 }
206
207 if (info->has_crypto_handshake) {
208 DCHECK(HasRetransmittableFrames(*info));
209 DCHECK_LT(0u, pending_crypto_packet_count_);
210 --pending_crypto_packet_count_;
211 info->has_crypto_handshake = false;
212 }
213 DeleteFrames(&info->retransmittable_frames);
214}
215
216void QuicUnackedPacketMap::RemoveRetransmittability(
217 QuicPacketNumber packet_number) {
218 DCHECK_GE(packet_number, least_unacked_);
219 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
220 QuicTransmissionInfo* info =
221 &unacked_packets_[packet_number - least_unacked_];
222 RemoveRetransmittability(info);
223}
224
225void QuicUnackedPacketMap::IncreaseLargestAcked(
226 QuicPacketNumber largest_acked) {
227 DCHECK(!largest_acked_.IsInitialized() || largest_acked_ <= largest_acked);
228 largest_acked_ = largest_acked;
229}
230
231void QuicUnackedPacketMap::MaybeUpdateLargestAckedOfPacketNumberSpace(
232 EncryptionLevel encryption_level,
233 QuicPacketNumber packet_number) {
234 DCHECK(use_uber_loss_algorithm_);
235 const PacketNumberSpace packet_number_space =
236 GetPacketNumberSpace(encryption_level);
237 if (!largest_acked_packets_[packet_number_space].IsInitialized()) {
238 largest_acked_packets_[packet_number_space] = packet_number;
239 } else {
240 largest_acked_packets_[packet_number_space] =
241 std::max(largest_acked_packets_[packet_number_space], packet_number);
242 }
243}
244
245bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
246 QuicPacketNumber packet_number,
247 const QuicTransmissionInfo& info) const {
248 // Packet can be used for RTT measurement if it may yet be acked as the
249 // largest observed packet by the receiver.
250 return QuicUtils::IsAckable(info.state) &&
251 (!largest_acked_.IsInitialized() || packet_number > largest_acked_);
252}
253
254bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
255 const QuicTransmissionInfo& info) const {
256 // Packet contributes to congestion control if it is considered inflight.
257 return info.in_flight;
258}
259
260bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
261 const QuicTransmissionInfo& info) const {
262 if (!session_decides_what_to_write_) {
263 // Packet may have retransmittable frames, or the data may have been
264 // retransmitted with a new packet number.
265 // Allow for an extra 1 RTT before stopping to track old packets.
266 return (info.retransmission.IsInitialized() &&
267 (!largest_acked_.IsInitialized() ||
268 info.retransmission > largest_acked_)) ||
269 HasRetransmittableFrames(info);
270 }
271
272 // Wait for 1 RTT before giving up on the lost packet.
273 return info.retransmission.IsInitialized() &&
274 (!largest_acked_.IsInitialized() ||
275 info.retransmission > largest_acked_);
276}
277
278bool QuicUnackedPacketMap::IsPacketUseless(
279 QuicPacketNumber packet_number,
280 const QuicTransmissionInfo& info) const {
281 return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
282 !IsPacketUsefulForCongestionControl(info) &&
283 !IsPacketUsefulForRetransmittableData(info);
284}
285
286bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
287 if (packet_number < least_unacked_ ||
288 packet_number >= least_unacked_ + unacked_packets_.size()) {
289 return false;
290 }
291 return !IsPacketUseless(packet_number,
292 unacked_packets_[packet_number - least_unacked_]);
293}
294
295void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
296 if (info->in_flight) {
297 QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
298 bytes_in_flight_ -= info->bytes_sent;
299 info->in_flight = false;
300 }
301}
302
303void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
304 DCHECK_GE(packet_number, least_unacked_);
305 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
306 QuicTransmissionInfo* info =
307 &unacked_packets_[packet_number - least_unacked_];
308 RemoveFromInFlight(info);
309}
310
311void QuicUnackedPacketMap::CancelRetransmissionsForStream(
312 QuicStreamId stream_id) {
313 DCHECK(!session_decides_what_to_write_);
314 QuicPacketNumber packet_number = least_unacked_;
315 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
316 ++it, ++packet_number) {
317 QuicFrames* frames = &it->retransmittable_frames;
318 if (frames->empty()) {
319 continue;
320 }
321 RemoveFramesForStream(frames, stream_id);
322 if (frames->empty()) {
323 RemoveRetransmittability(packet_number);
324 }
325 }
326}
327
328bool QuicUnackedPacketMap::HasInFlightPackets() const {
329 return bytes_in_flight_ > 0;
330}
331
332const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
333 QuicPacketNumber packet_number) const {
334 return unacked_packets_[packet_number - least_unacked_];
335}
336
337QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
338 QuicPacketNumber packet_number) {
339 return &unacked_packets_[packet_number - least_unacked_];
340}
341
342QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const {
343 auto it = unacked_packets_.rbegin();
344 while (it != unacked_packets_.rend()) {
345 if (it->in_flight) {
346 QUIC_BUG_IF(it->sent_time == QuicTime::Zero())
347 << "Sent time can never be zero for a packet in flight.";
348 return it->sent_time;
349 }
350 ++it;
351 }
352 QUIC_BUG << "GetLastPacketSentTime requires in flight packets.";
353 return QuicTime::Zero();
354}
355
356QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
357 return last_crypto_packet_sent_time_;
358}
359
360size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const {
361 size_t unacked_packet_count = 0;
362 QuicPacketNumber packet_number = least_unacked_;
363 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
364 ++it, ++packet_number) {
365 if (!IsPacketUseless(packet_number, *it)) {
366 ++unacked_packet_count;
367 }
368 }
369 return unacked_packet_count;
370}
371
372bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
373 if (bytes_in_flight_ > kDefaultTCPMSS) {
374 return true;
375 }
376 size_t num_in_flight = 0;
377 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
378 ++it) {
379 if (it->in_flight) {
380 ++num_in_flight;
381 }
382 if (num_in_flight > 1) {
383 return true;
384 }
385 }
386 return false;
387}
388
389bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
390 if (!session_decides_what_to_write_) {
391 return pending_crypto_packet_count_ > 0;
392 }
393 return session_notifier_->HasUnackedCryptoData();
394}
395
396bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
397 DCHECK(!GetQuicReloadableFlag(quic_optimize_inflight_check));
398 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
399 ++it) {
400 if (it->in_flight && HasRetransmittableFrames(*it)) {
401 return true;
402 }
403 }
404 return false;
405}
406
407QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const {
408 return least_unacked_;
409}
410
411void QuicUnackedPacketMap::SetSessionNotifier(
412 SessionNotifierInterface* session_notifier) {
413 session_notifier_ = session_notifier;
414}
415
416bool QuicUnackedPacketMap::NotifyFramesAcked(const QuicTransmissionInfo& info,
417 QuicTime::Delta ack_delay) {
418 if (session_notifier_ == nullptr) {
419 return false;
420 }
421 bool new_data_acked = false;
422 for (const QuicFrame& frame : info.retransmittable_frames) {
423 if (session_notifier_->OnFrameAcked(frame, ack_delay)) {
424 new_data_acked = true;
425 }
426 }
427 return new_data_acked;
428}
429
430void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
431 TransmissionType type) {
432 DCHECK(session_decides_what_to_write_);
433 for (const QuicFrame& frame : info.retransmittable_frames) {
434 session_notifier_->OnFrameLost(frame);
435 }
436}
437
438void QuicUnackedPacketMap::RetransmitFrames(const QuicTransmissionInfo& info,
439 TransmissionType type) {
440 DCHECK(session_decides_what_to_write_);
441 session_notifier_->RetransmitFrames(info.retransmittable_frames, type);
442}
443
444void QuicUnackedPacketMap::MaybeAggregateAckedStreamFrame(
445 const QuicTransmissionInfo& info,
446 QuicTime::Delta ack_delay) {
447 if (session_notifier_ == nullptr) {
448 return;
449 }
450 for (const auto& frame : info.retransmittable_frames) {
451 // Determine whether acked stream frame can be aggregated.
452 const bool can_aggregate =
453 frame.type == STREAM_FRAME &&
454 frame.stream_frame.stream_id == aggregated_stream_frame_.stream_id &&
455 frame.stream_frame.offset == aggregated_stream_frame_.offset +
456 aggregated_stream_frame_.data_length &&
457 // We would like to increment aggregated_stream_frame_.data_length by
458 // frame.stream_frame.data_length, so we need to make sure their sum is
459 // representable by QuicPacketLength, which is the type of the former.
460 !WillStreamFrameLengthSumWrapAround(
461 aggregated_stream_frame_.data_length,
462 frame.stream_frame.data_length);
463
464 if (can_aggregate) {
465 // Aggregate stream frame.
466 aggregated_stream_frame_.data_length += frame.stream_frame.data_length;
467 aggregated_stream_frame_.fin = frame.stream_frame.fin;
468 if (aggregated_stream_frame_.fin) {
469 // Notify session notifier aggregated stream frame gets acked if fin is
470 // acked.
471 NotifyAggregatedStreamFrameAcked(ack_delay);
472 }
473 continue;
474 }
475
476 NotifyAggregatedStreamFrameAcked(ack_delay);
477 if (frame.type != STREAM_FRAME || frame.stream_frame.fin) {
478 session_notifier_->OnFrameAcked(frame, ack_delay);
479 continue;
480 }
481
482 // Delay notifying session notifier stream frame gets acked in case it can
483 // be aggregated with following acked ones.
484 aggregated_stream_frame_.stream_id = frame.stream_frame.stream_id;
485 aggregated_stream_frame_.offset = frame.stream_frame.offset;
486 aggregated_stream_frame_.data_length = frame.stream_frame.data_length;
487 aggregated_stream_frame_.fin = frame.stream_frame.fin;
488 }
489}
490
491void QuicUnackedPacketMap::NotifyAggregatedStreamFrameAcked(
492 QuicTime::Delta ack_delay) {
493 if (aggregated_stream_frame_.stream_id == static_cast<QuicStreamId>(-1) ||
494 session_notifier_ == nullptr) {
495 // Aggregated stream frame is empty.
496 return;
497 }
498 session_notifier_->OnFrameAcked(QuicFrame(aggregated_stream_frame_),
499 ack_delay);
500 // Clear aggregated stream frame.
501 aggregated_stream_frame_.stream_id = -1;
502}
503
504PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
505 QuicPacketNumber packet_number) const {
506 DCHECK(use_uber_loss_algorithm_);
507 return GetPacketNumberSpace(
508 GetTransmissionInfo(packet_number).encryption_level);
509}
510
511PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
512 EncryptionLevel encryption_level) const {
513 DCHECK(use_uber_loss_algorithm_);
514 if (perspective_ == Perspective::IS_CLIENT) {
515 return encryption_level == ENCRYPTION_NONE ? HANDSHAKE_DATA
516 : APPLICATION_DATA;
517 }
518 return encryption_level == ENCRYPTION_FORWARD_SECURE ? APPLICATION_DATA
519 : HANDSHAKE_DATA;
520}
521
522QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
523 PacketNumberSpace packet_number_space) const {
524 DCHECK(use_uber_loss_algorithm_);
525 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
526 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
527 return QuicPacketNumber();
528 }
529 return largest_acked_packets_[packet_number_space];
530}
531
532QuicPacketNumber
533QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
534 PacketNumberSpace packet_number_space) const {
535 DCHECK(use_uber_loss_algorithm_);
536 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
537 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
538 return QuicPacketNumber();
539 }
540 return largest_sent_retransmittable_packets_[packet_number_space];
541}
542
543void QuicUnackedPacketMap::SetSessionDecideWhatToWrite(
544 bool session_decides_what_to_write) {
545 if (largest_sent_packet_.IsInitialized()) {
546 QUIC_BUG << "Cannot change session_decide_what_to_write with packets sent.";
547 return;
548 }
549 session_decides_what_to_write_ = session_decides_what_to_write;
550}
551
552} // namespace quic