blob: d8beb4359672a295ad426c12f9d36f39262d1694 [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),
fayang4c908f02019-11-01 07:26:17 -070031 packets_in_flight_(0),
ianswett479fea32019-09-04 02:51:01 -070032 last_inflight_packet_sent_time_(QuicTime::Zero()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050033 last_crypto_packet_sent_time_(QuicTime::Zero()),
34 session_notifier_(nullptr),
ianswette3567522019-10-28 07:20:10 -070035 supports_multiple_packet_number_spaces_(false) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050036
37QuicUnackedPacketMap::~QuicUnackedPacketMap() {
38 for (QuicTransmissionInfo& transmission_info : unacked_packets_) {
39 DeleteFrames(&(transmission_info.retransmittable_frames));
40 }
41}
42
43void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet,
QUICHE teama6ef0a62019-03-07 20:34:33 -050044 TransmissionType transmission_type,
45 QuicTime sent_time,
46 bool set_in_flight) {
47 QuicPacketNumber packet_number = packet->packet_number;
48 QuicPacketLength bytes_sent = packet->encrypted_length;
49 QUIC_BUG_IF(largest_sent_packet_.IsInitialized() &&
50 largest_sent_packet_ >= packet_number)
51 << "largest_sent_packet_: " << largest_sent_packet_
52 << ", packet_number: " << packet_number;
53 DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
54 while (least_unacked_ + unacked_packets_.size() < packet_number) {
55 unacked_packets_.push_back(QuicTransmissionInfo());
56 unacked_packets_.back().state = NEVER_SENT;
57 }
58
59 const bool has_crypto_handshake =
60 packet->has_crypto_handshake == IS_HANDSHAKE;
fayangcff885a2019-10-22 07:39:04 -070061 QuicTransmissionInfo info(packet->encryption_level, transmission_type,
62 sent_time, bytes_sent, has_crypto_handshake,
63 packet->num_padding_bytes);
QUICHE teama6ef0a62019-03-07 20:34:33 -050064 info.largest_acked = packet->largest_acked;
QUICHE teamc264e362019-03-19 14:21:06 -070065 largest_sent_largest_acked_.UpdateMax(packet->largest_acked);
QUICHE teama6ef0a62019-03-07 20:34:33 -050066
67 largest_sent_packet_ = packet_number;
QUICHE teamc279cec2019-03-22 06:51:48 -070068 if (supports_multiple_packet_number_spaces_) {
69 largest_sent_packets_[GetPacketNumberSpace(packet->encryption_level)] =
70 packet_number;
71 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050072 if (set_in_flight) {
73 bytes_in_flight_ += bytes_sent;
fayang4c908f02019-11-01 07:26:17 -070074 ++packets_in_flight_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 info.in_flight = true;
fayangbf3d2862019-06-20 14:13:44 -070076 largest_sent_retransmittable_packets_[GetPacketNumberSpace(
77 info.encryption_level)] = packet_number;
ianswett479fea32019-09-04 02:51:01 -070078 // TODO(ianswett): Should this field be per packet number space or should
79 // GetInFlightPacketSentTime() use largest_sent_retransmittable_packets_?
80 last_inflight_packet_sent_time_ = sent_time;
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 }
82 unacked_packets_.push_back(info);
83 // Swap the retransmittable frames to avoid allocations.
84 // TODO(ianswett): Could use emplace_back when Chromium can.
fayangcff885a2019-10-22 07:39:04 -070085 if (has_crypto_handshake) {
86 last_crypto_packet_sent_time_ = sent_time;
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 }
fayangcff885a2019-10-22 07:39:04 -070088
89 packet->retransmittable_frames.swap(
90 unacked_packets_.back().retransmittable_frames);
QUICHE teama6ef0a62019-03-07 20:34:33 -050091}
92
93void QuicUnackedPacketMap::RemoveObsoletePackets() {
94 while (!unacked_packets_.empty()) {
95 if (!IsPacketUseless(least_unacked_, unacked_packets_.front())) {
96 break;
97 }
fayangcff885a2019-10-22 07:39:04 -070098 DeleteFrames(&unacked_packets_.front().retransmittable_frames);
QUICHE teama6ef0a62019-03-07 20:34:33 -050099 unacked_packets_.pop_front();
100 ++least_unacked_;
101 }
102}
103
QUICHE teama6ef0a62019-03-07 20:34:33 -0500104bool QuicUnackedPacketMap::HasRetransmittableFrames(
105 QuicPacketNumber packet_number) const {
106 DCHECK_GE(packet_number, least_unacked_);
107 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
108 return HasRetransmittableFrames(
109 unacked_packets_[packet_number - least_unacked_]);
110}
111
112bool QuicUnackedPacketMap::HasRetransmittableFrames(
113 const QuicTransmissionInfo& info) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 if (!QuicUtils::IsAckable(info.state)) {
115 return false;
116 }
117
118 for (const auto& frame : info.retransmittable_frames) {
119 if (session_notifier_->IsFrameOutstanding(frame)) {
120 return true;
121 }
122 }
123 return false;
124}
125
126void QuicUnackedPacketMap::RemoveRetransmittability(
127 QuicTransmissionInfo* info) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 DeleteFrames(&info->retransmittable_frames);
fayangcff885a2019-10-22 07:39:04 -0700129 info->retransmission.Clear();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500130}
131
132void QuicUnackedPacketMap::RemoveRetransmittability(
133 QuicPacketNumber packet_number) {
134 DCHECK_GE(packet_number, least_unacked_);
135 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
136 QuicTransmissionInfo* info =
137 &unacked_packets_[packet_number - least_unacked_];
138 RemoveRetransmittability(info);
139}
140
141void QuicUnackedPacketMap::IncreaseLargestAcked(
142 QuicPacketNumber largest_acked) {
143 DCHECK(!largest_acked_.IsInitialized() || largest_acked_ <= largest_acked);
144 largest_acked_ = largest_acked;
145}
146
147void QuicUnackedPacketMap::MaybeUpdateLargestAckedOfPacketNumberSpace(
fayang3eb82212019-04-16 12:05:46 -0700148 PacketNumberSpace packet_number_space,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149 QuicPacketNumber packet_number) {
QUICHE teamc264e362019-03-19 14:21:06 -0700150 largest_acked_packets_[packet_number_space].UpdateMax(packet_number);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500151}
152
153bool QuicUnackedPacketMap::IsPacketUsefulForMeasuringRtt(
154 QuicPacketNumber packet_number,
155 const QuicTransmissionInfo& info) const {
156 // Packet can be used for RTT measurement if it may yet be acked as the
157 // largest observed packet by the receiver.
158 return QuicUtils::IsAckable(info.state) &&
159 (!largest_acked_.IsInitialized() || packet_number > largest_acked_);
160}
161
162bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
163 const QuicTransmissionInfo& info) const {
164 // Packet contributes to congestion control if it is considered inflight.
165 return info.in_flight;
166}
167
168bool QuicUnackedPacketMap::IsPacketUsefulForRetransmittableData(
169 const QuicTransmissionInfo& info) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 // Wait for 1 RTT before giving up on the lost packet.
171 return info.retransmission.IsInitialized() &&
172 (!largest_acked_.IsInitialized() ||
173 info.retransmission > largest_acked_);
174}
175
176bool QuicUnackedPacketMap::IsPacketUseless(
177 QuicPacketNumber packet_number,
178 const QuicTransmissionInfo& info) const {
179 return !IsPacketUsefulForMeasuringRtt(packet_number, info) &&
180 !IsPacketUsefulForCongestionControl(info) &&
181 !IsPacketUsefulForRetransmittableData(info);
182}
183
184bool QuicUnackedPacketMap::IsUnacked(QuicPacketNumber packet_number) const {
185 if (packet_number < least_unacked_ ||
186 packet_number >= least_unacked_ + unacked_packets_.size()) {
187 return false;
188 }
189 return !IsPacketUseless(packet_number,
190 unacked_packets_[packet_number - least_unacked_]);
191}
192
193void QuicUnackedPacketMap::RemoveFromInFlight(QuicTransmissionInfo* info) {
194 if (info->in_flight) {
195 QUIC_BUG_IF(bytes_in_flight_ < info->bytes_sent);
fayang4c908f02019-11-01 07:26:17 -0700196 QUIC_BUG_IF(packets_in_flight_ == 0);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500197 bytes_in_flight_ -= info->bytes_sent;
fayang4c908f02019-11-01 07:26:17 -0700198 --packets_in_flight_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 info->in_flight = false;
200 }
201}
202
203void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
204 DCHECK_GE(packet_number, least_unacked_);
205 DCHECK_LT(packet_number, least_unacked_ + unacked_packets_.size());
206 QuicTransmissionInfo* info =
207 &unacked_packets_[packet_number - least_unacked_];
208 RemoveFromInFlight(info);
209}
210
QUICHE teama6ef0a62019-03-07 20:34:33 -0500211bool QuicUnackedPacketMap::HasInFlightPackets() const {
212 return bytes_in_flight_ > 0;
213}
214
215const QuicTransmissionInfo& QuicUnackedPacketMap::GetTransmissionInfo(
216 QuicPacketNumber packet_number) const {
217 return unacked_packets_[packet_number - least_unacked_];
218}
219
220QuicTransmissionInfo* QuicUnackedPacketMap::GetMutableTransmissionInfo(
221 QuicPacketNumber packet_number) {
222 return &unacked_packets_[packet_number - least_unacked_];
223}
224
ianswett479fea32019-09-04 02:51:01 -0700225QuicTime QuicUnackedPacketMap::GetLastInFlightPacketSentTime() const {
ianswette3567522019-10-28 07:20:10 -0700226 return last_inflight_packet_sent_time_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500227}
228
229QuicTime QuicUnackedPacketMap::GetLastCryptoPacketSentTime() const {
230 return last_crypto_packet_sent_time_;
231}
232
233size_t QuicUnackedPacketMap::GetNumUnackedPacketsDebugOnly() const {
234 size_t unacked_packet_count = 0;
235 QuicPacketNumber packet_number = least_unacked_;
236 for (auto it = unacked_packets_.begin(); it != unacked_packets_.end();
237 ++it, ++packet_number) {
238 if (!IsPacketUseless(packet_number, *it)) {
239 ++unacked_packet_count;
240 }
241 }
242 return unacked_packet_count;
243}
244
245bool QuicUnackedPacketMap::HasMultipleInFlightPackets() const {
246 if (bytes_in_flight_ > kDefaultTCPMSS) {
247 return true;
248 }
249 size_t num_in_flight = 0;
250 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
251 ++it) {
252 if (it->in_flight) {
253 ++num_in_flight;
254 }
255 if (num_in_flight > 1) {
256 return true;
257 }
258 }
259 return false;
260}
261
262bool QuicUnackedPacketMap::HasPendingCryptoPackets() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500263 return session_notifier_->HasUnackedCryptoData();
264}
265
266bool QuicUnackedPacketMap::HasUnackedRetransmittableFrames() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 for (auto it = unacked_packets_.rbegin(); it != unacked_packets_.rend();
268 ++it) {
269 if (it->in_flight && HasRetransmittableFrames(*it)) {
270 return true;
271 }
272 }
273 return false;
274}
275
276QuicPacketNumber QuicUnackedPacketMap::GetLeastUnacked() const {
277 return least_unacked_;
278}
279
280void QuicUnackedPacketMap::SetSessionNotifier(
281 SessionNotifierInterface* session_notifier) {
282 session_notifier_ = session_notifier;
283}
284
285bool QuicUnackedPacketMap::NotifyFramesAcked(const QuicTransmissionInfo& info,
QUICHE team9467db02019-05-30 09:38:45 -0700286 QuicTime::Delta ack_delay,
287 QuicTime receive_timestamp) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500288 if (session_notifier_ == nullptr) {
289 return false;
290 }
291 bool new_data_acked = false;
292 for (const QuicFrame& frame : info.retransmittable_frames) {
QUICHE team9467db02019-05-30 09:38:45 -0700293 if (session_notifier_->OnFrameAcked(frame, ack_delay, receive_timestamp)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 new_data_acked = true;
295 }
296 }
297 return new_data_acked;
298}
299
300void QuicUnackedPacketMap::NotifyFramesLost(const QuicTransmissionInfo& info,
dschinazi17d42422019-06-18 16:35:07 -0700301 TransmissionType /*type*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500302 for (const QuicFrame& frame : info.retransmittable_frames) {
303 session_notifier_->OnFrameLost(frame);
304 }
305}
306
307void QuicUnackedPacketMap::RetransmitFrames(const QuicTransmissionInfo& info,
308 TransmissionType type) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500309 session_notifier_->RetransmitFrames(info.retransmittable_frames, type);
310}
311
312void QuicUnackedPacketMap::MaybeAggregateAckedStreamFrame(
313 const QuicTransmissionInfo& info,
QUICHE team9467db02019-05-30 09:38:45 -0700314 QuicTime::Delta ack_delay,
315 QuicTime receive_timestamp) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316 if (session_notifier_ == nullptr) {
317 return;
318 }
319 for (const auto& frame : info.retransmittable_frames) {
320 // Determine whether acked stream frame can be aggregated.
321 const bool can_aggregate =
322 frame.type == STREAM_FRAME &&
323 frame.stream_frame.stream_id == aggregated_stream_frame_.stream_id &&
324 frame.stream_frame.offset == aggregated_stream_frame_.offset +
325 aggregated_stream_frame_.data_length &&
326 // We would like to increment aggregated_stream_frame_.data_length by
327 // frame.stream_frame.data_length, so we need to make sure their sum is
328 // representable by QuicPacketLength, which is the type of the former.
329 !WillStreamFrameLengthSumWrapAround(
330 aggregated_stream_frame_.data_length,
331 frame.stream_frame.data_length);
332
333 if (can_aggregate) {
334 // Aggregate stream frame.
335 aggregated_stream_frame_.data_length += frame.stream_frame.data_length;
336 aggregated_stream_frame_.fin = frame.stream_frame.fin;
337 if (aggregated_stream_frame_.fin) {
338 // Notify session notifier aggregated stream frame gets acked if fin is
339 // acked.
340 NotifyAggregatedStreamFrameAcked(ack_delay);
341 }
342 continue;
343 }
344
345 NotifyAggregatedStreamFrameAcked(ack_delay);
346 if (frame.type != STREAM_FRAME || frame.stream_frame.fin) {
QUICHE team9467db02019-05-30 09:38:45 -0700347 session_notifier_->OnFrameAcked(frame, ack_delay, receive_timestamp);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500348 continue;
349 }
350
351 // Delay notifying session notifier stream frame gets acked in case it can
352 // be aggregated with following acked ones.
353 aggregated_stream_frame_.stream_id = frame.stream_frame.stream_id;
354 aggregated_stream_frame_.offset = frame.stream_frame.offset;
355 aggregated_stream_frame_.data_length = frame.stream_frame.data_length;
356 aggregated_stream_frame_.fin = frame.stream_frame.fin;
357 }
358}
359
360void QuicUnackedPacketMap::NotifyAggregatedStreamFrameAcked(
361 QuicTime::Delta ack_delay) {
362 if (aggregated_stream_frame_.stream_id == static_cast<QuicStreamId>(-1) ||
363 session_notifier_ == nullptr) {
364 // Aggregated stream frame is empty.
365 return;
366 }
QUICHE team9467db02019-05-30 09:38:45 -0700367 // Note: there is no receive_timestamp for an aggregated stream frame. The
368 // frames that are aggregated may not have been received at the same time.
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369 session_notifier_->OnFrameAcked(QuicFrame(aggregated_stream_frame_),
QUICHE team9467db02019-05-30 09:38:45 -0700370 ack_delay,
371 /*receive_timestamp=*/QuicTime::Zero());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500372 // Clear aggregated stream frame.
373 aggregated_stream_frame_.stream_id = -1;
374}
375
376PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
377 QuicPacketNumber packet_number) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500378 return GetPacketNumberSpace(
379 GetTransmissionInfo(packet_number).encryption_level);
380}
381
382PacketNumberSpace QuicUnackedPacketMap::GetPacketNumberSpace(
383 EncryptionLevel encryption_level) const {
QUICHE teamc279cec2019-03-22 06:51:48 -0700384 if (supports_multiple_packet_number_spaces_) {
385 return QuicUtils::GetPacketNumberSpace(encryption_level);
386 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500387 if (perspective_ == Perspective::IS_CLIENT) {
QUICHE team6987b4a2019-03-15 16:23:04 -0700388 return encryption_level == ENCRYPTION_INITIAL ? HANDSHAKE_DATA
389 : APPLICATION_DATA;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500390 }
391 return encryption_level == ENCRYPTION_FORWARD_SECURE ? APPLICATION_DATA
392 : HANDSHAKE_DATA;
393}
394
395QuicPacketNumber QuicUnackedPacketMap::GetLargestAckedOfPacketNumberSpace(
396 PacketNumberSpace packet_number_space) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500397 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
398 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
399 return QuicPacketNumber();
400 }
401 return largest_acked_packets_[packet_number_space];
402}
403
404QuicPacketNumber
405QuicUnackedPacketMap::GetLargestSentRetransmittableOfPacketNumberSpace(
406 PacketNumberSpace packet_number_space) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500407 if (packet_number_space >= NUM_PACKET_NUMBER_SPACES) {
408 QUIC_BUG << "Invalid packet number space: " << packet_number_space;
409 return QuicPacketNumber();
410 }
411 return largest_sent_retransmittable_packets_[packet_number_space];
412}
413
QUICHE teamc279cec2019-03-22 06:51:48 -0700414void QuicUnackedPacketMap::EnableMultiplePacketNumberSpacesSupport() {
415 if (supports_multiple_packet_number_spaces_) {
416 QUIC_BUG << "Multiple packet number spaces has already been enabled";
417 return;
418 }
419 if (largest_sent_packet_.IsInitialized()) {
420 QUIC_BUG << "Try to enable multiple packet number spaces support after any "
421 "packet has been sent.";
422 return;
423 }
424
425 supports_multiple_packet_number_spaces_ = true;
426}
427
428QuicPacketNumber QuicUnackedPacketMap::GetLargestSentPacketOfPacketNumberSpace(
429 EncryptionLevel encryption_level) const {
430 DCHECK(supports_multiple_packet_number_spaces_);
431 return largest_sent_packets_[GetPacketNumberSpace(encryption_level)];
432}
433
QUICHE teama6ef0a62019-03-07 20:34:33 -0500434} // namespace quic