blob: 1a0b1af24c4e4f657b195356b137410291954ca5 [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_(
QUICHE teamc279cec2019-03-22 06:51:48 -070036 GetQuicReloadableFlag(quic_use_uber_loss_algorithm)),
37 supports_multiple_packet_number_spaces_(false) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050038 if (use_uber_loss_algorithm_) {
39 QUIC_RELOADABLE_FLAG_COUNT(quic_use_uber_loss_algorithm);
40 }
41}
42
43QuicUnackedPacketMap::~QuicUnackedPacketMap() {
44 for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
45 DeleteFrames(&(transmission_info.retransmittable_frames));
46 }
47}
48
49void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
50 QuicPacketNumber old_packet_number,
51 TransmissionType transmission_type,
52 QuicTime sent_time,
53 bool set_in_flight) {
54 QuicPacketNumber packet_number = packet->packet_number;
55 QuicPacketLength bytes_sent = packet->encrypted_length;
56 QUIC_BUG_IF(largest_sent_packet_.IsInitialized() &&
57 largest_sent_packet_ >= packet_number)
58 << "largest_sent_packet_: " << largest_sent_packet_
59 << ", packet_number: " << packet_number;
60 DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
61 while (least_unacked_ + unacked_packets_.size() < packet_number) {
62 unacked_packets_.push_back(QuicTransmissionInfo());
63 unacked_packets_.back().state = NEVER_SENT;
64 }
65
66 const bool has_crypto_handshake =
67 packet->has_crypto_handshake == IS_HANDSHAKE;
68 QuicTransmissionInfo info(
69 packet->encryption_level, packet->packet_number_length, transmission_type,
70 sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
71 info.largest_acked = packet->largest_acked;
QUICHE teamc264e362019-03-19 14:21:06 -070072 largest_sent_largest_acked_.UpdateMax(packet->largest_acked);
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 if (old_packet_number.IsInitialized()) {
74 TransferRetransmissionInfo(old_packet_number, packet_number,
75 transmission_type, &info);
76 }
77
78 largest_sent_packet_ = packet_number;
QUICHE teamc279cec2019-03-22 06:51:48 -070079 if (supports_multiple_packet_number_spaces_) {
80 largest_sent_packets_[GetPacketNumberSpace(packet->encryption_level)] =
81 packet_number;
82 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050083 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(
fayang3eb82212019-04-16 12:05:46 -0700232 PacketNumberSpace packet_number_space,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500233 QuicPacketNumber packet_number) {
234 DCHECK(use_uber_loss_algorithm_);
QUICHE teamc264e362019-03-19 14:21:06 -0700235 largest_acked_packets_[packet_number_space].UpdateMax(packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500236}
237
238bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
239 QuicPacketNumber packet_number,
240 const QuicTransmissionInfo& info) const {
241 // Packet can be used for RTT measurement if it may yet be acked as the
242 // largest observed packet by the receiver.
243 return QuicUtils::IsAckable(info.state) &&
244 (!largest_acked_.IsInitialized() || packet_number > largest_acked_);
245}
246
247bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
248 const QuicTransmissionInfo& info) const {
249 // Packet contributes to congestion control if it is considered inflight.
250 return info.in_flight;
251}
252
253bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
254 const QuicTransmissionInfo& info) const {
255 if (!session_decides_what_to_write_) {
256 // Packet may have retransmittable frames, or the data may have been
257 // retransmitted with a new packet number.
258 // Allow for an extra 1 RTT before stopping to track old packets.
259 return (info.retransmission.IsInitialized() &&
260 (!largest_acked_.IsInitialized() ||
261 info.retransmission > largest_acked_)) ||
262 HasRetransmittableFrames(info);
263 }
264
265 // Wait for 1 RTT before giving up on the lost packet.
266 return info.retransmission.IsInitialized() &&
267 (!largest_acked_.IsInitialized() ||
268 info.retransmission > largest_acked_);
269}
270
271bool QuicUnackedPacketMap::IsPacketUseless(
272 QuicPacketNumber packet_number,
273 const QuicTransmissionInfo& info) const {
274 return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
275 !IsPacketUsefulForCongestionControl(info) &&
276 !IsPacketUsefulForRetransmittableData(info);
277}
278
279bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
280 if (packet_number < least_unacked_ ||
281 packet_number >= least_unacked_ + unacked_packets_.size()) {
282 return false;
283 }
284 return !IsPacketUseless(packet_number,
285 unacked_packets_[packet_number - least_unacked_]);
286}
287
288void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
289 if (info->in_flight) {
290 QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
291 bytes_in_flight_ -= info->bytes_sent;
292 info->in_flight = false;
293 }
294}
295
296void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
297 DCHECK_GE(packet_number, least_unacked_);
298 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
299 QuicTransmissionInfo* info =
300 &unacked_packets_[packet_number - least_unacked_];
301 RemoveFromInFlight(info);
302}
303
304void QuicUnackedPacketMap::CancelRetransmissionsForStream(
305 QuicStreamId stream_id) {
306 DCHECK(!session_decides_what_to_write_);
307 QuicPacketNumber packet_number = least_unacked_;
308 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
309 ++it, ++packet_number) {
310 QuicFrames* frames = &it->retransmittable_frames;
311 if (frames->empty()) {
312 continue;
313 }
314 RemoveFramesForStream(frames, stream_id);
315 if (frames->empty()) {
316 RemoveRetransmittability(packet_number);
317 }
318 }
319}
320
321bool QuicUnackedPacketMap::HasInFlightPackets() const {
322 return bytes_in_flight_ > 0;
323}
324
325const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
326 QuicPacketNumber packet_number) const {
327 return unacked_packets_[packet_number - least_unacked_];
328}
329
330QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
331 QuicPacketNumber packet_number) {
332 return &unacked_packets_[packet_number - least_unacked_];
333}
334
335QuicTime QuicUnackedPacketMap::GetLastPacketSentTime() const {
336 auto it = unacked_packets_.rbegin();
337 while (it != unacked_packets_.rend()) {
338 if (it->in_flight) {
339 QUIC_BUG_IF(it->sent_time == QuicTime::Zero())
340 << "Sent time can never be zero for a packet in flight.";
341 return it->sent_time;
342 }
343 ++it;
344 }
345 QUIC_BUG << "GetLastPacketSentTime requires in flight packets.";
346 return QuicTime::Zero();
347}
348
349QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
350 return last_crypto_packet_sent_time_;
351}
352
353size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const {
354 size_t unacked_packet_count = 0;
355 QuicPacketNumber packet_number = least_unacked_;
356 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
357 ++it, ++packet_number) {
358 if (!IsPacketUseless(packet_number, *it)) {
359 ++unacked_packet_count;
360 }
361 }
362 return unacked_packet_count;
363}
364
365bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
366 if (bytes_in_flight_ > kDefaultTCPMSS) {
367 return true;
368 }
369 size_t num_in_flight = 0;
370 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
371 ++it) {
372 if (it->in_flight) {
373 ++num_in_flight;
374 }
375 if (num_in_flight > 1) {
376 return true;
377 }
378 }
379 return false;
380}
381
382bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
383 if (!session_decides_what_to_write_) {
384 return pending_crypto_packet_count_ > 0;
385 }
386 return session_notifier_->HasUnackedCryptoData();
387}
388
389bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
390 DCHECK(!GetQuicReloadableFlag(quic_optimize_inflight_check));
391 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
392 ++it) {
393 if (it->in_flight && HasRetransmittableFrames(*it)) {
394 return true;
395 }
396 }
397 return false;
398}
399
400QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const {
401 return least_unacked_;
402}
403
404void QuicUnackedPacketMap::SetSessionNotifier(
405 SessionNotifierInterface* session_notifier) {
406 session_notifier_ = session_notifier;
407}
408
409bool QuicUnackedPacketMap::NotifyFramesAcked(const QuicTransmissionInfo& info,
410 QuicTime::Delta ack_delay) {
411 if (session_notifier_ == nullptr) {
412 return false;
413 }
414 bool new_data_acked = false;
415 for (const QuicFrame& frame : info.retransmittable_frames) {
416 if (session_notifier_->OnFrameAcked(frame, ack_delay)) {
417 new_data_acked = true;
418 }
419 }
420 return new_data_acked;
421}
422
423void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
424 TransmissionType type) {
425 DCHECK(session_decides_what_to_write_);
426 for (const QuicFrame& frame : info.retransmittable_frames) {
427 session_notifier_->OnFrameLost(frame);
428 }
429}
430
431void QuicUnackedPacketMap::RetransmitFrames(const QuicTransmissionInfo& info,
432 TransmissionType type) {
433 DCHECK(session_decides_what_to_write_);
434 session_notifier_->RetransmitFrames(info.retransmittable_frames, type);
435}
436
437void QuicUnackedPacketMap::MaybeAggregateAckedStreamFrame(
438 const QuicTransmissionInfo& info,
439 QuicTime::Delta ack_delay) {
440 if (session_notifier_ == nullptr) {
441 return;
442 }
443 for (const auto& frame : info.retransmittable_frames) {
444 // Determine whether acked stream frame can be aggregated.
445 const bool can_aggregate =
446 frame.type == STREAM_FRAME &&
447 frame.stream_frame.stream_id == aggregated_stream_frame_.stream_id &&
448 frame.stream_frame.offset == aggregated_stream_frame_.offset +
449 aggregated_stream_frame_.data_length &&
450 // We would like to increment aggregated_stream_frame_.data_length by
451 // frame.stream_frame.data_length, so we need to make sure their sum is
452 // representable by QuicPacketLength, which is the type of the former.
453 !WillStreamFrameLengthSumWrapAround(
454 aggregated_stream_frame_.data_length,
455 frame.stream_frame.data_length);
456
457 if (can_aggregate) {
458 // Aggregate stream frame.
459 aggregated_stream_frame_.data_length += frame.stream_frame.data_length;
460 aggregated_stream_frame_.fin = frame.stream_frame.fin;
461 if (aggregated_stream_frame_.fin) {
462 // Notify session notifier aggregated stream frame gets acked if fin is
463 // acked.
464 NotifyAggregatedStreamFrameAcked(ack_delay);
465 }
466 continue;
467 }
468
469 NotifyAggregatedStreamFrameAcked(ack_delay);
470 if (frame.type != STREAM_FRAME || frame.stream_frame.fin) {
471 session_notifier_->OnFrameAcked(frame, ack_delay);
472 continue;
473 }
474
475 // Delay notifying session notifier stream frame gets acked in case it can
476 // be aggregated with following acked ones.
477 aggregated_stream_frame_.stream_id = frame.stream_frame.stream_id;
478 aggregated_stream_frame_.offset = frame.stream_frame.offset;
479 aggregated_stream_frame_.data_length = frame.stream_frame.data_length;
480 aggregated_stream_frame_.fin = frame.stream_frame.fin;
481 }
482}
483
484void QuicUnackedPacketMap::NotifyAggregatedStreamFrameAcked(
485 QuicTime::Delta ack_delay) {
486 if (aggregated_stream_frame_.stream_id == static_cast<QuicStreamId>(-1) ||
487 session_notifier_ == nullptr) {
488 // Aggregated stream frame is empty.
489 return;
490 }
491 session_notifier_->OnFrameAcked(QuicFrame(aggregated_stream_frame_),
492 ack_delay);
493 // Clear aggregated stream frame.
494 aggregated_stream_frame_.stream_id = -1;
495}
496
497PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
498 QuicPacketNumber packet_number) const {
499 DCHECK(use_uber_loss_algorithm_);
500 return GetPacketNumberSpace(
501 GetTransmissionInfo(packet_number).encryption_level);
502}
503
504PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
505 EncryptionLevel encryption_level) const {
506 DCHECK(use_uber_loss_algorithm_);
QUICHE teamc279cec2019-03-22 06:51:48 -0700507 if (supports_multiple_packet_number_spaces_) {
508 return QuicUtils::GetPacketNumberSpace(encryption_level);
509 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500510 if (perspective_ == Perspective::IS_CLIENT) {
QUICHE team6987b4a2019-03-15 16:23:04 -0700511 return encryption_level == ENCRYPTION_INITIAL ? HANDSHAKE_DATA
512 : APPLICATION_DATA;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500513 }
514 return encryption_level == ENCRYPTION_FORWARD_SECURE ? APPLICATION_DATA
515 : HANDSHAKE_DATA;
516}
517
518QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
519 PacketNumberSpace packet_number_space) const {
520 DCHECK(use_uber_loss_algorithm_);
521 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
522 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
523 return QuicPacketNumber();
524 }
525 return largest_acked_packets_[packet_number_space];
526}
527
528QuicPacketNumber
529QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
530 PacketNumberSpace packet_number_space) const {
531 DCHECK(use_uber_loss_algorithm_);
532 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
533 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
534 return QuicPacketNumber();
535 }
536 return largest_sent_retransmittable_packets_[packet_number_space];
537}
538
539void QuicUnackedPacketMap::SetSessionDecideWhatToWrite(
540 bool session_decides_what_to_write) {
541 if (largest_sent_packet_.IsInitialized()) {
542 QUIC_BUG << "Cannot change session_decide_what_to_write with packets sent.";
543 return;
544 }
545 session_decides_what_to_write_ = session_decides_what_to_write;
546}
547
QUICHE teamc279cec2019-03-22 06:51:48 -0700548void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
549 if (supports_multiple_packet_number_spaces_) {
550 QUIC_BUG << "Multiple packet number spaces has already been enabled";
551 return;
552 }
553 if (largest_sent_packet_.IsInitialized()) {
554 QUIC_BUG << "Try to enable multiple packet number spaces support after any "
555 "packet has been sent.";
556 return;
557 }
558
559 supports_multiple_packet_number_spaces_ = true;
560}
561
562QuicPacketNumber QuicUnackedPacketMap::GetLargestSentPacketOfPacketNumberSpace(
563 EncryptionLevel encryption_level) const {
564 DCHECK(supports_multiple_packet_number_spaces_);
565 return largest_sent_packets_[GetPacketNumberSpace(encryption_level)];
566}
567
QUICHE teama6ef0a62019-03-07 20:34:33 -0500568} // namespace quic