1 // Copyright 2019 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 #ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_
6 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_
7
8 #include <algorithm>
9 #include <limits>
10
11 #include "quiche/quic/core/congestion_control/bandwidth_sampler.h"
12 #include "quiche/quic/core/congestion_control/send_algorithm_interface.h"
13 #include "quiche/quic/core/congestion_control/windowed_filter.h"
14 #include "quiche/quic/core/quic_bandwidth.h"
15 #include "quiche/quic/core/quic_packet_number.h"
16 #include "quiche/quic/core/quic_time.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/platform/api/quic_export.h"
19 #include "quiche/quic/platform/api/quic_flags.h"
20
21 namespace quic {
22
23 template <typename T>
24 class QUICHE_EXPORT Limits {
25 public:
Limits(T min,T max)26 Limits(T min, T max) : min_(min), max_(max) {}
27
28 // If [min, max] is an empty range, i.e. min > max, this function returns max,
29 // because typically a value larger than max means "risky".
ApplyLimits(T raw_value)30 T ApplyLimits(T raw_value) const {
31 return std::min(max_, std::max(min_, raw_value));
32 }
33
Min()34 T Min() const { return min_; }
Max()35 T Max() const { return max_; }
36
37 private:
38 T min_;
39 T max_;
40 };
41
42 template <typename T>
MinMax(T min,T max)43 QUICHE_EXPORT inline Limits<T> MinMax(T min, T max) {
44 return Limits<T>(min, max);
45 }
46
47 template <typename T>
NoLessThan(T min)48 QUICHE_EXPORT inline Limits<T> NoLessThan(T min) {
49 return Limits<T>(min, std::numeric_limits<T>::max());
50 }
51
52 template <typename T>
NoGreaterThan(T max)53 QUICHE_EXPORT inline Limits<T> NoGreaterThan(T max) {
54 return Limits<T>(std::numeric_limits<T>::min(), max);
55 }
56
57 template <typename T>
Unlimited()58 QUICHE_EXPORT inline Limits<T> Unlimited() {
59 return Limits<T>(std::numeric_limits<T>::min(),
60 std::numeric_limits<T>::max());
61 }
62
63 template <typename T>
64 QUICHE_EXPORT inline std::ostream& operator<<(std::ostream& os,
65 const Limits<T>& limits) {
66 return os << "[" << limits.Min() << ", " << limits.Max() << "]";
67 }
68
69 // Bbr2Params contains all parameters of a Bbr2Sender.
70 struct QUICHE_EXPORT Bbr2Params {
Bbr2ParamsBbr2Params71 Bbr2Params(QuicByteCount cwnd_min, QuicByteCount cwnd_max)
72 : cwnd_limits(cwnd_min, cwnd_max) {}
73
74 /*
75 * STARTUP parameters.
76 */
77
78 // The gain for CWND in startup.
79 float startup_cwnd_gain = 2.0;
80 // TODO(wub): Maybe change to the newly derived value of 2.773 (4 * ln(2)).
81 float startup_pacing_gain = 2.885;
82
83 // STARTUP or PROBE_UP are exited if the total bandwidth growth is less than
84 // |full_bw_threshold| in the last |startup_full_bw_rounds| round trips.
85 float full_bw_threshold = 1.25;
86
87 QuicRoundTripCount startup_full_bw_rounds = 3;
88
89 // Number of rounds to stay in STARTUP when there's a sufficient queue that
90 // bytes_in_flight never drops below the target (1.75 * BDP). 0 indicates the
91 // feature is disabled and we never exit due to queueing.
92 QuicRoundTripCount max_startup_queue_rounds = 0;
93
94 // The minimum number of loss marking events to exit STARTUP.
95 int64_t startup_full_loss_count =
96 GetQuicFlag(quic_bbr2_default_startup_full_loss_count);
97
98 // If true, always exit STARTUP on loss, even if bandwidth exceeds threshold.
99 // If false, exit STARTUP on loss only if bandwidth is below threshold.
100 bool always_exit_startup_on_excess_loss = false;
101
102 // If true, include extra acked during STARTUP and proactively reduce extra
103 // acked when bandwidth increases.
104 bool startup_include_extra_acked = false;
105
106
107 /*
108 * DRAIN parameters.
109 */
110 float drain_cwnd_gain = 2.0;
111 float drain_pacing_gain = 1.0 / 2.885;
112
113 /*
114 * PROBE_BW parameters.
115 */
116 // Max amount of randomness to inject in round counting for Reno-coexistence.
117 QuicRoundTripCount probe_bw_max_probe_rand_rounds = 2;
118
119 // Max number of rounds before probing for Reno-coexistence.
120 uint32_t probe_bw_probe_max_rounds = 63;
121
122 // Multiplier to get Reno-style probe epoch duration as: k * BDP round trips.
123 // If zero, disables Reno-style BDP-scaled coexistence mechanism.
124 float probe_bw_probe_reno_gain = 1.0;
125
126 // Minimum duration for BBR-native probes.
127 QuicTime::Delta probe_bw_probe_base_duration =
128 QuicTime::Delta::FromMilliseconds(
129 GetQuicFlag(quic_bbr2_default_probe_bw_base_duration_ms));
130
131 // The upper bound of the random amount of BBR-native probes.
132 QuicTime::Delta probe_bw_probe_max_rand_duration =
133 QuicTime::Delta::FromMilliseconds(
134 GetQuicFlag(quic_bbr2_default_probe_bw_max_rand_duration_ms));
135
136 // The minimum number of loss marking events to exit the PROBE_UP phase.
137 int64_t probe_bw_full_loss_count =
138 GetQuicFlag(quic_bbr2_default_probe_bw_full_loss_count);
139
140 // Pacing gains.
141 float probe_bw_probe_up_pacing_gain = 1.25;
142 float probe_bw_probe_down_pacing_gain = 0.75;
143 float probe_bw_default_pacing_gain = 1.0;
144
145 float probe_bw_cwnd_gain = 2.0;
146
147 /*
148 * PROBE_UP parameters.
149 */
150 bool probe_up_ignore_inflight_hi = true;
151 bool probe_up_simplify_inflight_hi = false;
152
153 // Number of rounds to stay in PROBE_UP when there's a sufficient queue that
154 // bytes_in_flight never drops below the target. 0 indicates the feature is
155 // disabled and we never exit due to queueing.
156 QuicRoundTripCount max_probe_up_queue_rounds = 0;
157
158 /*
159 * PROBE_RTT parameters.
160 */
161 float probe_rtt_inflight_target_bdp_fraction = 0.5;
162 QuicTime::Delta probe_rtt_period = QuicTime::Delta::FromMilliseconds(
163 GetQuicFlag(quic_bbr2_default_probe_rtt_period_ms));
164 QuicTime::Delta probe_rtt_duration = QuicTime::Delta::FromMilliseconds(200);
165
166 /*
167 * Parameters used by multiple modes.
168 */
169
170 // The initial value of the max ack height filter's window length.
171 QuicRoundTripCount initial_max_ack_height_filter_window =
172 GetQuicFlag(quic_bbr2_default_initial_ack_height_filter_window);
173
174 // Fraction of unutilized headroom to try to leave in path upon high loss.
175 float inflight_hi_headroom =
176 GetQuicFlag(quic_bbr2_default_inflight_hi_headroom);
177
178 // Estimate startup/bw probing has gone too far if loss rate exceeds this.
179 float loss_threshold = GetQuicFlag(quic_bbr2_default_loss_threshold);
180
181 // A common factor for multiplicative decreases. Used for adjusting
182 // bandwidth_lo, inflight_lo and inflight_hi upon losses.
183 float beta = 0.3;
184
185 Limits<QuicByteCount> cwnd_limits;
186
187 /*
188 * Experimental flags from QuicConfig.
189 */
190
191 // Can be disabled by connection option 'B2NA'.
192 bool add_ack_height_to_queueing_threshold = true;
193
194 // Can be disabled by connection option 'B2RP'.
195 bool avoid_unnecessary_probe_rtt = true;
196
197 // Can be enabled by connection option 'B2LO'.
198 bool ignore_inflight_lo = false;
199
200 // Can be enabled by connection option 'B2H2'.
201 bool limit_inflight_hi_by_max_delivered = false;
202
203 // Can be disabled by connection option 'B2SL'.
204 bool startup_loss_exit_use_max_delivered_for_inflight_hi = true;
205
206 // Can be enabled by connection option 'B2DL'.
207 bool use_bytes_delivered_for_inflight_hi = false;
208
209 // Can be disabled by connection option 'B2RC'.
210 bool enable_reno_coexistence = true;
211
212 // For experimentation to improve fast convergence upon loss.
213 enum QuicBandwidthLoMode : uint8_t {
214 DEFAULT = 0,
215 MIN_RTT_REDUCTION = 1, // 'BBQ7'
216 INFLIGHT_REDUCTION = 2, // 'BBQ8'
217 CWND_REDUCTION = 3, // 'BBQ9'
218 };
219
220 // Different modes change bandwidth_lo_ differently upon loss.
221 QuicBandwidthLoMode bw_lo_mode_ = QuicBandwidthLoMode::DEFAULT;
222
223 // Set the pacing gain to 25% larger than the recent BW increase in STARTUP.
224 bool decrease_startup_pacing_at_end_of_round = false;
225 };
226
227 class QUICHE_EXPORT RoundTripCounter {
228 public:
229 RoundTripCounter();
230
Count()231 QuicRoundTripCount Count() const { return round_trip_count_; }
232
last_sent_packet()233 QuicPacketNumber last_sent_packet() const { return last_sent_packet_; }
234
235 // Must be called in ascending packet number order.
236 void OnPacketSent(QuicPacketNumber packet_number);
237
238 // Return whether a round trip has just completed.
239 bool OnPacketsAcked(QuicPacketNumber last_acked_packet);
240
241 void RestartRound();
242
243 private:
244 QuicRoundTripCount round_trip_count_;
245 QuicPacketNumber last_sent_packet_;
246 // The last sent packet number of the current round trip.
247 QuicPacketNumber end_of_round_trip_;
248 };
249
250 class QUICHE_EXPORT MinRttFilter {
251 public:
252 MinRttFilter(QuicTime::Delta initial_min_rtt,
253 QuicTime initial_min_rtt_timestamp);
254
255 void Update(QuicTime::Delta sample_rtt, QuicTime now);
256
257 void ForceUpdate(QuicTime::Delta sample_rtt, QuicTime now);
258
Get()259 QuicTime::Delta Get() const { return min_rtt_; }
260
GetTimestamp()261 QuicTime GetTimestamp() const { return min_rtt_timestamp_; }
262
263 private:
264 QuicTime::Delta min_rtt_;
265 // Time when the current value of |min_rtt_| was assigned.
266 QuicTime min_rtt_timestamp_;
267 };
268
269 class QUICHE_EXPORT Bbr2MaxBandwidthFilter {
270 public:
Update(QuicBandwidth sample)271 void Update(QuicBandwidth sample) {
272 max_bandwidth_[1] = std::max(sample, max_bandwidth_[1]);
273 }
274
Advance()275 void Advance() {
276 if (max_bandwidth_[1].IsZero()) {
277 return;
278 }
279
280 max_bandwidth_[0] = max_bandwidth_[1];
281 max_bandwidth_[1] = QuicBandwidth::Zero();
282 }
283
Get()284 QuicBandwidth Get() const {
285 return std::max(max_bandwidth_[0], max_bandwidth_[1]);
286 }
287
288 private:
289 QuicBandwidth max_bandwidth_[2] = {QuicBandwidth::Zero(),
290 QuicBandwidth::Zero()};
291 };
292
293 // Information that are meaningful only when Bbr2Sender::OnCongestionEvent is
294 // running.
295 struct QUICHE_EXPORT Bbr2CongestionEvent {
296 QuicTime event_time = QuicTime::Zero();
297
298 // The congestion window prior to the processing of the ack/loss events.
299 QuicByteCount prior_cwnd;
300
301 // Total bytes inflight before the processing of the ack/loss events.
302 QuicByteCount prior_bytes_in_flight = 0;
303
304 // Total bytes inflight after the processing of the ack/loss events.
305 QuicByteCount bytes_in_flight = 0;
306
307 // Total bytes acked from acks in this event.
308 QuicByteCount bytes_acked = 0;
309
310 // Total bytes lost from losses in this event.
311 QuicByteCount bytes_lost = 0;
312
313 // Whether acked_packets indicates the end of a round trip.
314 bool end_of_round_trip = false;
315
316 // When the event happened, whether the sender is probing for bandwidth.
317 bool is_probing_for_bandwidth = false;
318
319 // Minimum rtt of all bandwidth samples from acked_packets.
320 // QuicTime::Delta::Infinite() if acked_packets is empty.
321 QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
322
323 // Maximum bandwidth of all bandwidth samples from acked_packets.
324 // This sample may be app-limited, and will be Zero() if there are no newly
325 // acknowledged inflight packets.
326 QuicBandwidth sample_max_bandwidth = QuicBandwidth::Zero();
327
328 // The send state of the largest packet in acked_packets, unless it is empty.
329 // If acked_packets is empty, it's the send state of the largest packet in
330 // lost_packets.
331 SendTimeState last_packet_send_state;
332 };
333
334 // Bbr2NetworkModel takes low level congestion signals(packets sent/acked/lost)
335 // as input and produces BBRv2 model parameters like inflight_(hi|lo),
336 // bandwidth_(hi|lo), bandwidth and rtt estimates, etc.
337 class QUICHE_EXPORT Bbr2NetworkModel {
338 public:
339 Bbr2NetworkModel(const Bbr2Params* params, QuicTime::Delta initial_rtt,
340 QuicTime initial_rtt_timestamp, float cwnd_gain,
341 float pacing_gain, const BandwidthSampler* old_sampler);
342
343 void OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight,
344 QuicPacketNumber packet_number, QuicByteCount bytes,
345 HasRetransmittableData is_retransmittable);
346
347 void OnCongestionEventStart(QuicTime event_time,
348 const AckedPacketVector& acked_packets,
349 const LostPacketVector& lost_packets,
350 Bbr2CongestionEvent* congestion_event);
351
352 void OnCongestionEventFinish(QuicPacketNumber least_unacked_packet,
353 const Bbr2CongestionEvent& congestion_event);
354
355 // Update the model without a congestion event.
356 // Min rtt is updated if |rtt| is non-zero and smaller than existing min rtt.
357 void UpdateNetworkParameters(QuicTime::Delta rtt);
358
359 // Update inflight/bandwidth short-term lower bounds.
360 void AdaptLowerBounds(const Bbr2CongestionEvent& congestion_event);
361
362 // Restart the current round trip as if it is starting now.
363 void RestartRoundEarly();
364
AdvanceMaxBandwidthFilter()365 void AdvanceMaxBandwidthFilter() { max_bandwidth_filter_.Advance(); }
366
OnApplicationLimited()367 void OnApplicationLimited() { bandwidth_sampler_.OnAppLimited(); }
368
369 // Calculates BDP using the current MaxBandwidth.
BDP()370 QuicByteCount BDP() const { return BDP(MaxBandwidth()); }
371
BDP(QuicBandwidth bandwidth)372 QuicByteCount BDP(QuicBandwidth bandwidth) const {
373 return bandwidth * MinRtt();
374 }
375
BDP(QuicBandwidth bandwidth,float gain)376 QuicByteCount BDP(QuicBandwidth bandwidth, float gain) const {
377 return bandwidth * MinRtt() * gain;
378 }
379
MinRtt()380 QuicTime::Delta MinRtt() const { return min_rtt_filter_.Get(); }
381
MinRttTimestamp()382 QuicTime MinRttTimestamp() const { return min_rtt_filter_.GetTimestamp(); }
383
384 // TODO(wub): If we do this too frequently, we can potentailly postpone
385 // PROBE_RTT indefinitely. Observe how it works in production and improve it.
PostponeMinRttTimestamp(QuicTime::Delta duration)386 void PostponeMinRttTimestamp(QuicTime::Delta duration) {
387 min_rtt_filter_.ForceUpdate(MinRtt(), MinRttTimestamp() + duration);
388 }
389
MaxBandwidth()390 QuicBandwidth MaxBandwidth() const { return max_bandwidth_filter_.Get(); }
391
MaxAckHeight()392 QuicByteCount MaxAckHeight() const {
393 return bandwidth_sampler_.max_ack_height();
394 }
395
396 // 2 packets. Used to indicate the typical number of bytes ACKed at once.
QueueingThresholdExtraBytes()397 QuicByteCount QueueingThresholdExtraBytes() const {
398 return 2 * kDefaultTCPMSS;
399 }
400
cwnd_limited_before_aggregation_epoch()401 bool cwnd_limited_before_aggregation_epoch() const {
402 return cwnd_limited_before_aggregation_epoch_;
403 }
404
EnableOverestimateAvoidance()405 void EnableOverestimateAvoidance() {
406 bandwidth_sampler_.EnableOverestimateAvoidance();
407 }
408
IsBandwidthOverestimateAvoidanceEnabled()409 bool IsBandwidthOverestimateAvoidanceEnabled() const {
410 return bandwidth_sampler_.IsOverestimateAvoidanceEnabled();
411 }
412
OnPacketNeutered(QuicPacketNumber packet_number)413 void OnPacketNeutered(QuicPacketNumber packet_number) {
414 bandwidth_sampler_.OnPacketNeutered(packet_number);
415 }
416
num_ack_aggregation_epochs()417 uint64_t num_ack_aggregation_epochs() const {
418 return bandwidth_sampler_.num_ack_aggregation_epochs();
419 }
420
SetStartNewAggregationEpochAfterFullRound(bool value)421 void SetStartNewAggregationEpochAfterFullRound(bool value) {
422 bandwidth_sampler_.SetStartNewAggregationEpochAfterFullRound(value);
423 }
424
SetLimitMaxAckHeightTrackerBySendRate(bool value)425 void SetLimitMaxAckHeightTrackerBySendRate(bool value) {
426 bandwidth_sampler_.SetLimitMaxAckHeightTrackerBySendRate(value);
427 }
428
SetMaxAckHeightTrackerWindowLength(QuicRoundTripCount value)429 void SetMaxAckHeightTrackerWindowLength(QuicRoundTripCount value) {
430 bandwidth_sampler_.SetMaxAckHeightTrackerWindowLength(value);
431 }
432
SetReduceExtraAckedOnBandwidthIncrease(bool value)433 void SetReduceExtraAckedOnBandwidthIncrease(bool value) {
434 bandwidth_sampler_.SetReduceExtraAckedOnBandwidthIncrease(value);
435 }
436
437 bool MaybeExpireMinRtt(const Bbr2CongestionEvent& congestion_event);
438
BandwidthEstimate()439 QuicBandwidth BandwidthEstimate() const {
440 return std::min(MaxBandwidth(), bandwidth_lo_);
441 }
442
RoundTripCount()443 QuicRoundTripCount RoundTripCount() const {
444 return round_trip_counter_.Count();
445 }
446
447 // Return true if the number of loss events exceeds max_loss_events and
448 // fraction of bytes lost exceed the loss threshold.
449 bool IsInflightTooHigh(const Bbr2CongestionEvent& congestion_event,
450 int64_t max_loss_events) const;
451
452 // Check bandwidth growth in the past round. Must be called at the end of a
453 // round. Returns true if there was sufficient bandwidth growth and false
454 // otherwise. If it's been too many rounds without growth, also sets
455 // |full_bandwidth_reached_| to true.
456 bool HasBandwidthGrowth(const Bbr2CongestionEvent& congestion_event);
457
458 // Increments rounds_with_queueing_ if the minimum bytes in flight during the
459 // round is greater than the BDP * |target_gain|.
460 void CheckPersistentQueue(const Bbr2CongestionEvent& congestion_event,
461 float target_gain);
462
last_sent_packet()463 QuicPacketNumber last_sent_packet() const {
464 return round_trip_counter_.last_sent_packet();
465 }
466
total_bytes_acked()467 QuicByteCount total_bytes_acked() const {
468 return bandwidth_sampler_.total_bytes_acked();
469 }
470
total_bytes_lost()471 QuicByteCount total_bytes_lost() const {
472 return bandwidth_sampler_.total_bytes_lost();
473 }
474
total_bytes_sent()475 QuicByteCount total_bytes_sent() const {
476 return bandwidth_sampler_.total_bytes_sent();
477 }
478
loss_events_in_round()479 int64_t loss_events_in_round() const { return loss_events_in_round_; }
480
max_bytes_delivered_in_round()481 QuicByteCount max_bytes_delivered_in_round() const {
482 return max_bytes_delivered_in_round_;
483 }
484
min_bytes_in_flight_in_round()485 QuicByteCount min_bytes_in_flight_in_round() const {
486 return min_bytes_in_flight_in_round_;
487 }
488
inflight_hi_limited_in_round()489 bool inflight_hi_limited_in_round() const {
490 return inflight_hi_limited_in_round_;
491 }
492
end_of_app_limited_phase()493 QuicPacketNumber end_of_app_limited_phase() const {
494 return bandwidth_sampler_.end_of_app_limited_phase();
495 }
496
bandwidth_latest()497 QuicBandwidth bandwidth_latest() const { return bandwidth_latest_; }
bandwidth_lo()498 QuicBandwidth bandwidth_lo() const { return bandwidth_lo_; }
bandwidth_lo_default()499 static QuicBandwidth bandwidth_lo_default() {
500 return QuicBandwidth::Infinite();
501 }
clear_bandwidth_lo()502 void clear_bandwidth_lo() { bandwidth_lo_ = bandwidth_lo_default(); }
503
inflight_latest()504 QuicByteCount inflight_latest() const { return inflight_latest_; }
inflight_lo()505 QuicByteCount inflight_lo() const { return inflight_lo_; }
inflight_lo_default()506 static QuicByteCount inflight_lo_default() {
507 return std::numeric_limits<QuicByteCount>::max();
508 }
clear_inflight_lo()509 void clear_inflight_lo() { inflight_lo_ = inflight_lo_default(); }
510 void cap_inflight_lo(QuicByteCount cap);
511
512 QuicByteCount inflight_hi_with_headroom() const;
inflight_hi()513 QuicByteCount inflight_hi() const { return inflight_hi_; }
inflight_hi_default()514 static QuicByteCount inflight_hi_default() {
515 return std::numeric_limits<QuicByteCount>::max();
516 }
set_inflight_hi(QuicByteCount inflight_hi)517 void set_inflight_hi(QuicByteCount inflight_hi) {
518 inflight_hi_ = inflight_hi;
519 }
520
cwnd_gain()521 float cwnd_gain() const { return cwnd_gain_; }
set_cwnd_gain(float cwnd_gain)522 void set_cwnd_gain(float cwnd_gain) { cwnd_gain_ = cwnd_gain; }
523
pacing_gain()524 float pacing_gain() const { return pacing_gain_; }
set_pacing_gain(float pacing_gain)525 void set_pacing_gain(float pacing_gain) { pacing_gain_ = pacing_gain; }
526
full_bandwidth_reached()527 bool full_bandwidth_reached() const { return full_bandwidth_reached_; }
set_full_bandwidth_reached()528 void set_full_bandwidth_reached() { full_bandwidth_reached_ = true; }
full_bandwidth_baseline()529 QuicBandwidth full_bandwidth_baseline() const {
530 return full_bandwidth_baseline_;
531 }
rounds_without_bandwidth_growth()532 QuicRoundTripCount rounds_without_bandwidth_growth() const {
533 return rounds_without_bandwidth_growth_;
534 }
rounds_with_queueing()535 QuicRoundTripCount rounds_with_queueing() const {
536 return rounds_with_queueing_;
537 }
538
539 private:
540 // Called when a new round trip starts.
541 void OnNewRound();
542
Params()543 const Bbr2Params& Params() const { return *params_; }
544 const Bbr2Params* const params_;
545 RoundTripCounter round_trip_counter_;
546
547 // Bandwidth sampler provides BBR with the bandwidth measurements at
548 // individual points.
549 BandwidthSampler bandwidth_sampler_;
550 // The filter that tracks the maximum bandwidth over multiple recent round
551 // trips.
552 Bbr2MaxBandwidthFilter max_bandwidth_filter_;
553 MinRttFilter min_rtt_filter_;
554
555 // Bytes lost in the current round. Updated once per congestion event.
556 QuicByteCount bytes_lost_in_round_ = 0;
557 // Number of loss marking events in the current round.
558 int64_t loss_events_in_round_ = 0;
559
560 // A max of bytes delivered among all congestion events in the current round.
561 // A congestions event's bytes delivered is the total bytes acked between time
562 // Ts and Ta, which is the time when the largest acked packet(within the
563 // congestion event) was sent and acked, respectively.
564 QuicByteCount max_bytes_delivered_in_round_ = 0;
565
566 // The minimum bytes in flight during this round.
567 QuicByteCount min_bytes_in_flight_in_round_ =
568 std::numeric_limits<uint64_t>::max();
569
570 // True if sending was limited by inflight_hi anytime in the current round.
571 bool inflight_hi_limited_in_round_ = false;
572
573 // Max bandwidth in the current round. Updated once per congestion event.
574 QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
575 // Max bandwidth of recent rounds. Updated once per round.
576 QuicBandwidth bandwidth_lo_ = bandwidth_lo_default();
577 // bandwidth_lo_ at the beginning of a round with loss. Only used when the
578 // bw_lo_mode is non-default.
579 QuicBandwidth prior_bandwidth_lo_ = QuicBandwidth::Zero();
580
581 // Max inflight in the current round. Updated once per congestion event.
582 QuicByteCount inflight_latest_ = 0;
583 // Max inflight of recent rounds. Updated once per round.
584 QuicByteCount inflight_lo_ = inflight_lo_default();
585 QuicByteCount inflight_hi_ = inflight_hi_default();
586
587 float cwnd_gain_;
588 float pacing_gain_;
589
590 // Whether we are cwnd limited prior to the start of the current aggregation
591 // epoch.
592 bool cwnd_limited_before_aggregation_epoch_ = false;
593
594 // STARTUP-centric fields which experimentally used by PROBE_UP.
595 bool full_bandwidth_reached_ = false;
596 QuicBandwidth full_bandwidth_baseline_ = QuicBandwidth::Zero();
597 QuicRoundTripCount rounds_without_bandwidth_growth_ = 0;
598
599 // Used by STARTUP and PROBE_UP to decide when to exit.
600 QuicRoundTripCount rounds_with_queueing_ = 0;
601 };
602
603 enum class Bbr2Mode : uint8_t {
604 // Startup phase of the connection.
605 STARTUP,
606 // After achieving the highest possible bandwidth during the startup, lower
607 // the pacing rate in order to drain the queue.
608 DRAIN,
609 // Cruising mode.
610 PROBE_BW,
611 // Temporarily slow down sending in order to empty the buffer and measure
612 // the real minimum RTT.
613 PROBE_RTT,
614 };
615
616 QUICHE_EXPORT inline std::ostream& operator<<(std::ostream& os,
617 const Bbr2Mode& mode) {
618 switch (mode) {
619 case Bbr2Mode::STARTUP:
620 return os << "STARTUP";
621 case Bbr2Mode::DRAIN:
622 return os << "DRAIN";
623 case Bbr2Mode::PROBE_BW:
624 return os << "PROBE_BW";
625 case Bbr2Mode::PROBE_RTT:
626 return os << "PROBE_RTT";
627 }
628 return os << "<Invalid Mode>";
629 }
630
631 // The base class for all BBRv2 modes. A Bbr2Sender is in one mode at a time,
632 // this interface is used to implement mode-specific behaviors.
633 class Bbr2Sender;
634 class QUICHE_EXPORT Bbr2ModeBase {
635 public:
Bbr2ModeBase(const Bbr2Sender * sender,Bbr2NetworkModel * model)636 Bbr2ModeBase(const Bbr2Sender* sender, Bbr2NetworkModel* model)
637 : sender_(sender), model_(model) {}
638
639 virtual ~Bbr2ModeBase() = default;
640
641 // Called when entering/leaving this mode.
642 // congestion_event != nullptr means BBRv2 is switching modes in the context
643 // of a ack and/or loss.
644 virtual void Enter(QuicTime now,
645 const Bbr2CongestionEvent* congestion_event) = 0;
646 virtual void Leave(QuicTime now,
647 const Bbr2CongestionEvent* congestion_event) = 0;
648
649 virtual Bbr2Mode OnCongestionEvent(
650 QuicByteCount prior_in_flight, QuicTime event_time,
651 const AckedPacketVector& acked_packets,
652 const LostPacketVector& lost_packets,
653 const Bbr2CongestionEvent& congestion_event) = 0;
654
655 virtual Limits<QuicByteCount> GetCwndLimits() const = 0;
656
657 virtual bool IsProbingForBandwidth() const = 0;
658
659 virtual Bbr2Mode OnExitQuiescence(QuicTime now,
660 QuicTime quiescence_start_time) = 0;
661
662 protected:
663 const Bbr2Sender* const sender_;
664 Bbr2NetworkModel* model_;
665 };
666
BytesInFlight(const SendTimeState & send_state)667 QUICHE_EXPORT inline QuicByteCount BytesInFlight(
668 const SendTimeState& send_state) {
669 QUICHE_DCHECK(send_state.is_valid);
670 if (send_state.bytes_in_flight != 0) {
671 return send_state.bytes_in_flight;
672 }
673 return send_state.total_bytes_sent - send_state.total_bytes_acked -
674 send_state.total_bytes_lost;
675 }
676
677 } // namespace quic
678
679 #endif // QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_
680