1 // Copyright 2016 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 "quiche/quic/core/congestion_control/bandwidth_sampler.h"
6
7 #include <algorithm>
8
9 #include "quiche/quic/core/quic_types.h"
10 #include "quiche/quic/platform/api/quic_bug_tracker.h"
11 #include "quiche/quic/platform/api/quic_flag_utils.h"
12 #include "quiche/quic/platform/api/quic_flags.h"
13 #include "quiche/quic/platform/api/quic_logging.h"
14
15 namespace quic {
16
operator <<(std::ostream & os,const SendTimeState & s)17 std::ostream& operator<<(std::ostream& os, const SendTimeState& s) {
18 os << "{valid:" << s.is_valid << ", app_limited:" << s.is_app_limited
19 << ", total_sent:" << s.total_bytes_sent
20 << ", total_acked:" << s.total_bytes_acked
21 << ", total_lost:" << s.total_bytes_lost
22 << ", inflight:" << s.bytes_in_flight << "}";
23 return os;
24 }
25
Update(QuicBandwidth bandwidth_estimate,bool is_new_max_bandwidth,QuicRoundTripCount round_trip_count,QuicPacketNumber last_sent_packet_number,QuicPacketNumber last_acked_packet_number,QuicTime ack_time,QuicByteCount bytes_acked)26 QuicByteCount MaxAckHeightTracker::Update(
27 QuicBandwidth bandwidth_estimate, bool is_new_max_bandwidth,
28 QuicRoundTripCount round_trip_count,
29 QuicPacketNumber last_sent_packet_number,
30 QuicPacketNumber last_acked_packet_number, QuicTime ack_time,
31 QuicByteCount bytes_acked) {
32 bool force_new_epoch = false;
33
34 if (reduce_extra_acked_on_bandwidth_increase_ && is_new_max_bandwidth) {
35 // Save and clear existing entries.
36 ExtraAckedEvent best = max_ack_height_filter_.GetBest();
37 ExtraAckedEvent second_best = max_ack_height_filter_.GetSecondBest();
38 ExtraAckedEvent third_best = max_ack_height_filter_.GetThirdBest();
39 max_ack_height_filter_.Clear();
40
41 // Reinsert the heights into the filter after recalculating.
42 QuicByteCount expected_bytes_acked = bandwidth_estimate * best.time_delta;
43 if (expected_bytes_acked < best.bytes_acked) {
44 best.extra_acked = best.bytes_acked - expected_bytes_acked;
45 max_ack_height_filter_.Update(best, best.round);
46 }
47 expected_bytes_acked = bandwidth_estimate * second_best.time_delta;
48 if (expected_bytes_acked < second_best.bytes_acked) {
49 QUICHE_DCHECK_LE(best.round, second_best.round);
50 second_best.extra_acked = second_best.bytes_acked - expected_bytes_acked;
51 max_ack_height_filter_.Update(second_best, second_best.round);
52 }
53 expected_bytes_acked = bandwidth_estimate * third_best.time_delta;
54 if (expected_bytes_acked < third_best.bytes_acked) {
55 QUICHE_DCHECK_LE(second_best.round, third_best.round);
56 third_best.extra_acked = third_best.bytes_acked - expected_bytes_acked;
57 max_ack_height_filter_.Update(third_best, third_best.round);
58 }
59 }
60
61 // If any packet sent after the start of the epoch has been acked, start a new
62 // epoch.
63 if (start_new_aggregation_epoch_after_full_round_ &&
64 last_sent_packet_number_before_epoch_.IsInitialized() &&
65 last_acked_packet_number.IsInitialized() &&
66 last_acked_packet_number > last_sent_packet_number_before_epoch_) {
67 QUIC_DVLOG(3) << "Force starting a new aggregation epoch. "
68 "last_sent_packet_number_before_epoch_:"
69 << last_sent_packet_number_before_epoch_
70 << ", last_acked_packet_number:" << last_acked_packet_number;
71 if (reduce_extra_acked_on_bandwidth_increase_) {
72 QUIC_BUG(quic_bwsampler_46)
73 << "A full round of aggregation should never "
74 << "pass with startup_include_extra_acked(B204) enabled.";
75 }
76 force_new_epoch = true;
77 }
78 if (aggregation_epoch_start_time_ == QuicTime::Zero() || force_new_epoch) {
79 aggregation_epoch_bytes_ = bytes_acked;
80 aggregation_epoch_start_time_ = ack_time;
81 last_sent_packet_number_before_epoch_ = last_sent_packet_number;
82 ++num_ack_aggregation_epochs_;
83 return 0;
84 }
85
86 // Compute how many bytes are expected to be delivered, assuming max bandwidth
87 // is correct.
88 QuicTime::Delta aggregation_delta = ack_time - aggregation_epoch_start_time_;
89 QuicByteCount expected_bytes_acked = bandwidth_estimate * aggregation_delta;
90 // Reset the current aggregation epoch as soon as the ack arrival rate is less
91 // than or equal to the max bandwidth.
92 if (aggregation_epoch_bytes_ <=
93 ack_aggregation_bandwidth_threshold_ * expected_bytes_acked) {
94 QUIC_DVLOG(3) << "Starting a new aggregation epoch because "
95 "aggregation_epoch_bytes_ "
96 << aggregation_epoch_bytes_
97 << " is smaller than expected. "
98 "ack_aggregation_bandwidth_threshold_:"
99 << ack_aggregation_bandwidth_threshold_
100 << ", expected_bytes_acked:" << expected_bytes_acked
101 << ", bandwidth_estimate:" << bandwidth_estimate
102 << ", aggregation_duration:" << aggregation_delta
103 << ", new_aggregation_epoch:" << ack_time
104 << ", new_aggregation_bytes_acked:" << bytes_acked;
105 // Reset to start measuring a new aggregation epoch.
106 aggregation_epoch_bytes_ = bytes_acked;
107 aggregation_epoch_start_time_ = ack_time;
108 last_sent_packet_number_before_epoch_ = last_sent_packet_number;
109 ++num_ack_aggregation_epochs_;
110 return 0;
111 }
112
113 aggregation_epoch_bytes_ += bytes_acked;
114
115 // Compute how many extra bytes were delivered vs max bandwidth.
116 QuicByteCount extra_bytes_acked =
117 aggregation_epoch_bytes_ - expected_bytes_acked;
118 QUIC_DVLOG(3) << "Updating MaxAckHeight. ack_time:" << ack_time
119 << ", last sent packet:" << last_sent_packet_number
120 << ", bandwidth_estimate:" << bandwidth_estimate
121 << ", bytes_acked:" << bytes_acked
122 << ", expected_bytes_acked:" << expected_bytes_acked
123 << ", aggregation_epoch_bytes_:" << aggregation_epoch_bytes_
124 << ", extra_bytes_acked:" << extra_bytes_acked;
125 ExtraAckedEvent new_event;
126 new_event.extra_acked = extra_bytes_acked;
127 new_event.bytes_acked = aggregation_epoch_bytes_;
128 new_event.time_delta = aggregation_delta;
129 max_ack_height_filter_.Update(new_event, round_trip_count);
130 return extra_bytes_acked;
131 }
132
BandwidthSampler(const QuicUnackedPacketMap * unacked_packet_map,QuicRoundTripCount max_height_tracker_window_length)133 BandwidthSampler::BandwidthSampler(
134 const QuicUnackedPacketMap* unacked_packet_map,
135 QuicRoundTripCount max_height_tracker_window_length)
136 : total_bytes_sent_(0),
137 total_bytes_acked_(0),
138 total_bytes_lost_(0),
139 total_bytes_neutered_(0),
140 total_bytes_sent_at_last_acked_packet_(0),
141 last_acked_packet_sent_time_(QuicTime::Zero()),
142 last_acked_packet_ack_time_(QuicTime::Zero()),
143 is_app_limited_(true),
144 connection_state_map_(),
145 max_tracked_packets_(GetQuicFlag(quic_max_tracked_packet_count)),
146 unacked_packet_map_(unacked_packet_map),
147 max_ack_height_tracker_(max_height_tracker_window_length),
148 total_bytes_acked_after_last_ack_event_(0),
149 overestimate_avoidance_(false),
150 limit_max_ack_height_tracker_by_send_rate_(false) {}
151
BandwidthSampler(const BandwidthSampler & other)152 BandwidthSampler::BandwidthSampler(const BandwidthSampler& other)
153 : total_bytes_sent_(other.total_bytes_sent_),
154 total_bytes_acked_(other.total_bytes_acked_),
155 total_bytes_lost_(other.total_bytes_lost_),
156 total_bytes_neutered_(other.total_bytes_neutered_),
157 total_bytes_sent_at_last_acked_packet_(
158 other.total_bytes_sent_at_last_acked_packet_),
159 last_acked_packet_sent_time_(other.last_acked_packet_sent_time_),
160 last_acked_packet_ack_time_(other.last_acked_packet_ack_time_),
161 last_sent_packet_(other.last_sent_packet_),
162 last_acked_packet_(other.last_acked_packet_),
163 is_app_limited_(other.is_app_limited_),
164 end_of_app_limited_phase_(other.end_of_app_limited_phase_),
165 connection_state_map_(other.connection_state_map_),
166 recent_ack_points_(other.recent_ack_points_),
167 a0_candidates_(other.a0_candidates_),
168 max_tracked_packets_(other.max_tracked_packets_),
169 unacked_packet_map_(other.unacked_packet_map_),
170 max_ack_height_tracker_(other.max_ack_height_tracker_),
171 total_bytes_acked_after_last_ack_event_(
172 other.total_bytes_acked_after_last_ack_event_),
173 overestimate_avoidance_(other.overestimate_avoidance_),
174 limit_max_ack_height_tracker_by_send_rate_(
175 other.limit_max_ack_height_tracker_by_send_rate_) {}
176
EnableOverestimateAvoidance()177 void BandwidthSampler::EnableOverestimateAvoidance() {
178 if (overestimate_avoidance_) {
179 return;
180 }
181
182 overestimate_avoidance_ = true;
183 // TODO(wub): Change the default value of
184 // --quic_ack_aggregation_bandwidth_threshold to 2.0.
185 max_ack_height_tracker_.SetAckAggregationBandwidthThreshold(2.0);
186 }
187
~BandwidthSampler()188 BandwidthSampler::~BandwidthSampler() {}
189
OnPacketSent(QuicTime sent_time,QuicPacketNumber packet_number,QuicByteCount bytes,QuicByteCount bytes_in_flight,HasRetransmittableData has_retransmittable_data)190 void BandwidthSampler::OnPacketSent(
191 QuicTime sent_time, QuicPacketNumber packet_number, QuicByteCount bytes,
192 QuicByteCount bytes_in_flight,
193 HasRetransmittableData has_retransmittable_data) {
194 last_sent_packet_ = packet_number;
195
196 if (has_retransmittable_data != HAS_RETRANSMITTABLE_DATA) {
197 return;
198 }
199
200 total_bytes_sent_ += bytes;
201
202 // If there are no packets in flight, the time at which the new transmission
203 // opens can be treated as the A_0 point for the purpose of bandwidth
204 // sampling. This underestimates bandwidth to some extent, and produces some
205 // artificially low samples for most packets in flight, but it provides with
206 // samples at important points where we would not have them otherwise, most
207 // importantly at the beginning of the connection.
208 if (bytes_in_flight == 0) {
209 last_acked_packet_ack_time_ = sent_time;
210 if (overestimate_avoidance_) {
211 recent_ack_points_.Clear();
212 recent_ack_points_.Update(sent_time, total_bytes_acked_);
213 a0_candidates_.clear();
214 a0_candidates_.push_back(recent_ack_points_.MostRecentPoint());
215 }
216 total_bytes_sent_at_last_acked_packet_ = total_bytes_sent_;
217
218 // In this situation ack compression is not a concern, set send rate to
219 // effectively infinite.
220 last_acked_packet_sent_time_ = sent_time;
221 }
222
223 if (!connection_state_map_.IsEmpty() &&
224 packet_number >
225 connection_state_map_.last_packet() + max_tracked_packets_) {
226 if (unacked_packet_map_ != nullptr && !unacked_packet_map_->empty()) {
227 QuicPacketNumber maybe_least_unacked =
228 unacked_packet_map_->GetLeastUnacked();
229 QUIC_BUG(quic_bug_10437_1)
230 << "BandwidthSampler in-flight packet map has exceeded maximum "
231 "number of tracked packets("
232 << max_tracked_packets_
233 << "). First tracked: " << connection_state_map_.first_packet()
234 << "; last tracked: " << connection_state_map_.last_packet()
235 << "; entry_slots_used: " << connection_state_map_.entry_slots_used()
236 << "; number_of_present_entries: "
237 << connection_state_map_.number_of_present_entries()
238 << "; packet number: " << packet_number
239 << "; unacked_map: " << unacked_packet_map_->DebugString()
240 << "; total_bytes_sent: " << total_bytes_sent_
241 << "; total_bytes_acked: " << total_bytes_acked_
242 << "; total_bytes_lost: " << total_bytes_lost_
243 << "; total_bytes_neutered: " << total_bytes_neutered_
244 << "; last_acked_packet_sent_time: " << last_acked_packet_sent_time_
245 << "; total_bytes_sent_at_last_acked_packet: "
246 << total_bytes_sent_at_last_acked_packet_
247 << "; least_unacked_packet_info: "
248 << (unacked_packet_map_->IsUnacked(maybe_least_unacked)
249 ? unacked_packet_map_
250 ->GetTransmissionInfo(maybe_least_unacked)
251 .DebugString()
252 : "n/a");
253 } else {
254 QUIC_BUG(quic_bug_10437_2)
255 << "BandwidthSampler in-flight packet map has exceeded maximum "
256 "number of tracked packets.";
257 }
258 }
259
260 bool success = connection_state_map_.Emplace(packet_number, sent_time, bytes,
261 bytes_in_flight + bytes, *this);
262 QUIC_BUG_IF(quic_bug_10437_3, !success)
263 << "BandwidthSampler failed to insert the packet "
264 "into the map, most likely because it's already "
265 "in it.";
266 }
267
OnPacketNeutered(QuicPacketNumber packet_number)268 void BandwidthSampler::OnPacketNeutered(QuicPacketNumber packet_number) {
269 connection_state_map_.Remove(
270 packet_number, [&](const ConnectionStateOnSentPacket& sent_packet) {
271 QUIC_CODE_COUNT(quic_bandwidth_sampler_packet_neutered);
272 total_bytes_neutered_ += sent_packet.size;
273 });
274 }
275
276 BandwidthSamplerInterface::CongestionEventSample
OnCongestionEvent(QuicTime ack_time,const AckedPacketVector & acked_packets,const LostPacketVector & lost_packets,QuicBandwidth max_bandwidth,QuicBandwidth est_bandwidth_upper_bound,QuicRoundTripCount round_trip_count)277 BandwidthSampler::OnCongestionEvent(QuicTime ack_time,
278 const AckedPacketVector& acked_packets,
279 const LostPacketVector& lost_packets,
280 QuicBandwidth max_bandwidth,
281 QuicBandwidth est_bandwidth_upper_bound,
282 QuicRoundTripCount round_trip_count) {
283 CongestionEventSample event_sample;
284
285 SendTimeState last_lost_packet_send_state;
286
287 for (const LostPacket& packet : lost_packets) {
288 SendTimeState send_state =
289 OnPacketLost(packet.packet_number, packet.bytes_lost);
290 if (send_state.is_valid) {
291 last_lost_packet_send_state = send_state;
292 }
293 }
294
295 if (acked_packets.empty()) {
296 // Only populate send state for a loss-only event.
297 event_sample.last_packet_send_state = last_lost_packet_send_state;
298 return event_sample;
299 }
300
301 SendTimeState last_acked_packet_send_state;
302 QuicBandwidth max_send_rate = QuicBandwidth::Zero();
303 for (const auto& packet : acked_packets) {
304 BandwidthSample sample =
305 OnPacketAcknowledged(ack_time, packet.packet_number);
306 if (!sample.state_at_send.is_valid) {
307 continue;
308 }
309
310 last_acked_packet_send_state = sample.state_at_send;
311
312 if (!sample.rtt.IsZero()) {
313 event_sample.sample_rtt = std::min(event_sample.sample_rtt, sample.rtt);
314 }
315 if (sample.bandwidth > event_sample.sample_max_bandwidth) {
316 event_sample.sample_max_bandwidth = sample.bandwidth;
317 event_sample.sample_is_app_limited = sample.state_at_send.is_app_limited;
318 }
319 if (!sample.send_rate.IsInfinite()) {
320 max_send_rate = std::max(max_send_rate, sample.send_rate);
321 }
322 const QuicByteCount inflight_sample =
323 total_bytes_acked() - last_acked_packet_send_state.total_bytes_acked;
324 if (inflight_sample > event_sample.sample_max_inflight) {
325 event_sample.sample_max_inflight = inflight_sample;
326 }
327 }
328
329 if (!last_lost_packet_send_state.is_valid) {
330 event_sample.last_packet_send_state = last_acked_packet_send_state;
331 } else if (!last_acked_packet_send_state.is_valid) {
332 event_sample.last_packet_send_state = last_lost_packet_send_state;
333 } else {
334 // If two packets are inflight and an alarm is armed to lose a packet and it
335 // wakes up late, then the first of two in flight packets could have been
336 // acknowledged before the wakeup, which re-evaluates loss detection, and
337 // could declare the later of the two lost.
338 event_sample.last_packet_send_state =
339 lost_packets.back().packet_number > acked_packets.back().packet_number
340 ? last_lost_packet_send_state
341 : last_acked_packet_send_state;
342 }
343
344 bool is_new_max_bandwidth = event_sample.sample_max_bandwidth > max_bandwidth;
345 max_bandwidth = std::max(max_bandwidth, event_sample.sample_max_bandwidth);
346 if (limit_max_ack_height_tracker_by_send_rate_) {
347 max_bandwidth = std::max(max_bandwidth, max_send_rate);
348 }
349 // TODO(ianswett): Why is the min being passed in here?
350 event_sample.extra_acked =
351 OnAckEventEnd(std::min(est_bandwidth_upper_bound, max_bandwidth),
352 is_new_max_bandwidth, round_trip_count);
353
354 return event_sample;
355 }
356
OnAckEventEnd(QuicBandwidth bandwidth_estimate,bool is_new_max_bandwidth,QuicRoundTripCount round_trip_count)357 QuicByteCount BandwidthSampler::OnAckEventEnd(
358 QuicBandwidth bandwidth_estimate, bool is_new_max_bandwidth,
359 QuicRoundTripCount round_trip_count) {
360 const QuicByteCount newly_acked_bytes =
361 total_bytes_acked_ - total_bytes_acked_after_last_ack_event_;
362
363 if (newly_acked_bytes == 0) {
364 return 0;
365 }
366 total_bytes_acked_after_last_ack_event_ = total_bytes_acked_;
367 QuicByteCount extra_acked = max_ack_height_tracker_.Update(
368 bandwidth_estimate, is_new_max_bandwidth, round_trip_count,
369 last_sent_packet_, last_acked_packet_, last_acked_packet_ack_time_,
370 newly_acked_bytes);
371 // If |extra_acked| is zero, i.e. this ack event marks the start of a new ack
372 // aggregation epoch, save LessRecentPoint, which is the last ack point of the
373 // previous epoch, as a A0 candidate.
374 if (overestimate_avoidance_ && extra_acked == 0) {
375 a0_candidates_.push_back(recent_ack_points_.LessRecentPoint());
376 QUIC_DVLOG(1) << "New a0_candidate:" << a0_candidates_.back();
377 }
378 return extra_acked;
379 }
380
OnPacketAcknowledged(QuicTime ack_time,QuicPacketNumber packet_number)381 BandwidthSample BandwidthSampler::OnPacketAcknowledged(
382 QuicTime ack_time, QuicPacketNumber packet_number) {
383 last_acked_packet_ = packet_number;
384 ConnectionStateOnSentPacket* sent_packet_pointer =
385 connection_state_map_.GetEntry(packet_number);
386 if (sent_packet_pointer == nullptr) {
387 // See the TODO below.
388 return BandwidthSample();
389 }
390 BandwidthSample sample =
391 OnPacketAcknowledgedInner(ack_time, packet_number, *sent_packet_pointer);
392 return sample;
393 }
394
OnPacketAcknowledgedInner(QuicTime ack_time,QuicPacketNumber packet_number,const ConnectionStateOnSentPacket & sent_packet)395 BandwidthSample BandwidthSampler::OnPacketAcknowledgedInner(
396 QuicTime ack_time, QuicPacketNumber packet_number,
397 const ConnectionStateOnSentPacket& sent_packet) {
398 total_bytes_acked_ += sent_packet.size;
399 total_bytes_sent_at_last_acked_packet_ =
400 sent_packet.send_time_state.total_bytes_sent;
401 last_acked_packet_sent_time_ = sent_packet.sent_time;
402 last_acked_packet_ack_time_ = ack_time;
403 if (overestimate_avoidance_) {
404 recent_ack_points_.Update(ack_time, total_bytes_acked_);
405 }
406
407 if (is_app_limited_) {
408 // Exit app-limited phase in two cases:
409 // (1) end_of_app_limited_phase_ is not initialized, i.e., so far all
410 // packets are sent while there are buffered packets or pending data.
411 // (2) The current acked packet is after the sent packet marked as the end
412 // of the app limit phase.
413 if (!end_of_app_limited_phase_.IsInitialized() ||
414 packet_number > end_of_app_limited_phase_) {
415 is_app_limited_ = false;
416 }
417 }
418
419 // There might have been no packets acknowledged at the moment when the
420 // current packet was sent. In that case, there is no bandwidth sample to
421 // make.
422 if (sent_packet.last_acked_packet_sent_time == QuicTime::Zero()) {
423 QUIC_BUG(quic_bug_10437_4)
424 << "sent_packet.last_acked_packet_sent_time is zero";
425 return BandwidthSample();
426 }
427
428 // Infinite rate indicates that the sampler is supposed to discard the
429 // current send rate sample and use only the ack rate.
430 QuicBandwidth send_rate = QuicBandwidth::Infinite();
431 if (sent_packet.sent_time > sent_packet.last_acked_packet_sent_time) {
432 send_rate = QuicBandwidth::FromBytesAndTimeDelta(
433 sent_packet.send_time_state.total_bytes_sent -
434 sent_packet.total_bytes_sent_at_last_acked_packet,
435 sent_packet.sent_time - sent_packet.last_acked_packet_sent_time);
436 }
437
438 AckPoint a0;
439 if (overestimate_avoidance_ &&
440 ChooseA0Point(sent_packet.send_time_state.total_bytes_acked, &a0)) {
441 QUIC_DVLOG(2) << "Using a0 point: " << a0;
442 } else {
443 a0.ack_time = sent_packet.last_acked_packet_ack_time,
444 a0.total_bytes_acked = sent_packet.send_time_state.total_bytes_acked;
445 }
446
447 // During the slope calculation, ensure that ack time of the current packet is
448 // always larger than the time of the previous packet, otherwise division by
449 // zero or integer underflow can occur.
450 if (ack_time <= a0.ack_time) {
451 // TODO(wub): Compare this code count before and after fixing clock jitter
452 // issue.
453 if (a0.ack_time == sent_packet.sent_time) {
454 // This is the 1st packet after quiescense.
455 QUIC_CODE_COUNT_N(quic_prev_ack_time_larger_than_current_ack_time, 1, 2);
456 } else {
457 QUIC_CODE_COUNT_N(quic_prev_ack_time_larger_than_current_ack_time, 2, 2);
458 }
459 QUIC_LOG_EVERY_N_SEC(ERROR, 60)
460 << "Time of the previously acked packet:"
461 << a0.ack_time.ToDebuggingValue()
462 << " is larger than the ack time of the current packet:"
463 << ack_time.ToDebuggingValue()
464 << ". acked packet number:" << packet_number
465 << ", total_bytes_acked_:" << total_bytes_acked_
466 << ", overestimate_avoidance_:" << overestimate_avoidance_
467 << ", sent_packet:" << sent_packet;
468 return BandwidthSample();
469 }
470 QuicBandwidth ack_rate = QuicBandwidth::FromBytesAndTimeDelta(
471 total_bytes_acked_ - a0.total_bytes_acked, ack_time - a0.ack_time);
472
473 BandwidthSample sample;
474 sample.bandwidth = std::min(send_rate, ack_rate);
475 // Note: this sample does not account for delayed acknowledgement time. This
476 // means that the RTT measurements here can be artificially high, especially
477 // on low bandwidth connections.
478 sample.rtt = ack_time - sent_packet.sent_time;
479 sample.send_rate = send_rate;
480 SentPacketToSendTimeState(sent_packet, &sample.state_at_send);
481
482 if (sample.bandwidth.IsZero()) {
483 QUIC_LOG_EVERY_N_SEC(ERROR, 60)
484 << "ack_rate: " << ack_rate << ", send_rate: " << send_rate
485 << ". acked packet number:" << packet_number
486 << ", overestimate_avoidance_:" << overestimate_avoidance_ << "a1:{"
487 << total_bytes_acked_ << "@" << ack_time << "}, a0:{"
488 << a0.total_bytes_acked << "@" << a0.ack_time
489 << "}, sent_packet:" << sent_packet;
490 }
491 return sample;
492 }
493
ChooseA0Point(QuicByteCount total_bytes_acked,AckPoint * a0)494 bool BandwidthSampler::ChooseA0Point(QuicByteCount total_bytes_acked,
495 AckPoint* a0) {
496 if (a0_candidates_.empty()) {
497 QUIC_BUG(quic_bug_10437_5)
498 << "No A0 point candicates. total_bytes_acked:" << total_bytes_acked;
499 return false;
500 }
501
502 if (a0_candidates_.size() == 1) {
503 *a0 = a0_candidates_.front();
504 return true;
505 }
506
507 for (size_t i = 1; i < a0_candidates_.size(); ++i) {
508 if (a0_candidates_[i].total_bytes_acked > total_bytes_acked) {
509 *a0 = a0_candidates_[i - 1];
510 if (i > 1) {
511 a0_candidates_.pop_front_n(i - 1);
512 }
513 return true;
514 }
515 }
516
517 // All candidates' total_bytes_acked is <= |total_bytes_acked|.
518 *a0 = a0_candidates_.back();
519 a0_candidates_.pop_front_n(a0_candidates_.size() - 1);
520 return true;
521 }
522
OnPacketLost(QuicPacketNumber packet_number,QuicPacketLength bytes_lost)523 SendTimeState BandwidthSampler::OnPacketLost(QuicPacketNumber packet_number,
524 QuicPacketLength bytes_lost) {
525 // TODO(vasilvv): see the comment for the case of missing packets in
526 // BandwidthSampler::OnPacketAcknowledged on why this does not raise a
527 // QUIC_BUG when removal fails.
528 SendTimeState send_time_state;
529
530 total_bytes_lost_ += bytes_lost;
531 ConnectionStateOnSentPacket* sent_packet_pointer =
532 connection_state_map_.GetEntry(packet_number);
533 if (sent_packet_pointer != nullptr) {
534 SentPacketToSendTimeState(*sent_packet_pointer, &send_time_state);
535 }
536
537 return send_time_state;
538 }
539
SentPacketToSendTimeState(const ConnectionStateOnSentPacket & sent_packet,SendTimeState * send_time_state) const540 void BandwidthSampler::SentPacketToSendTimeState(
541 const ConnectionStateOnSentPacket& sent_packet,
542 SendTimeState* send_time_state) const {
543 *send_time_state = sent_packet.send_time_state;
544 send_time_state->is_valid = true;
545 }
546
OnAppLimited()547 void BandwidthSampler::OnAppLimited() {
548 is_app_limited_ = true;
549 end_of_app_limited_phase_ = last_sent_packet_;
550 }
551
RemoveObsoletePackets(QuicPacketNumber least_unacked)552 void BandwidthSampler::RemoveObsoletePackets(QuicPacketNumber least_unacked) {
553 // A packet can become obsolete when it is removed from QuicUnackedPacketMap's
554 // view of inflight before it is acked or marked as lost. For example, when
555 // QuicSentPacketManager::RetransmitCryptoPackets retransmits a crypto packet,
556 // the packet is removed from QuicUnackedPacketMap's inflight, but is not
557 // marked as acked or lost in the BandwidthSampler.
558 connection_state_map_.RemoveUpTo(least_unacked);
559 }
560
total_bytes_sent() const561 QuicByteCount BandwidthSampler::total_bytes_sent() const {
562 return total_bytes_sent_;
563 }
564
total_bytes_acked() const565 QuicByteCount BandwidthSampler::total_bytes_acked() const {
566 return total_bytes_acked_;
567 }
568
total_bytes_lost() const569 QuicByteCount BandwidthSampler::total_bytes_lost() const {
570 return total_bytes_lost_;
571 }
572
total_bytes_neutered() const573 QuicByteCount BandwidthSampler::total_bytes_neutered() const {
574 return total_bytes_neutered_;
575 }
576
is_app_limited() const577 bool BandwidthSampler::is_app_limited() const { return is_app_limited_; }
578
end_of_app_limited_phase() const579 QuicPacketNumber BandwidthSampler::end_of_app_limited_phase() const {
580 return end_of_app_limited_phase_;
581 }
582
583 } // namespace quic
584