xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_misc.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 =
162       GetQuicFlag(quic_bbr2_default_probe_rtt_inflight_target_bdp_fraction);
163   QuicTime::Delta probe_rtt_period = QuicTime::Delta::FromMilliseconds(
164       GetQuicFlag(quic_bbr2_default_probe_rtt_period_ms));
165   QuicTime::Delta probe_rtt_duration = QuicTime::Delta::FromMilliseconds(
166       GetQuicFlag(quic_bbr2_default_probe_rtt_duration_ms));
167 
168   /*
169    * Parameters used by multiple modes.
170    */
171 
172   // The initial value of the max ack height filter's window length.
173   QuicRoundTripCount initial_max_ack_height_filter_window =
174       GetQuicFlag(quic_bbr2_default_initial_ack_height_filter_window);
175 
176   // Fraction of unutilized headroom to try to leave in path upon high loss.
177   float inflight_hi_headroom =
178       GetQuicFlag(quic_bbr2_default_inflight_hi_headroom);
179 
180   // Estimate startup/bw probing has gone too far if loss rate exceeds this.
181   float loss_threshold = GetQuicFlag(quic_bbr2_default_loss_threshold);
182 
183   // A common factor for multiplicative decreases. Used for adjusting
184   // bandwidth_lo, inflight_lo and inflight_hi upon losses.
185   float beta = 0.3;
186 
187   Limits<QuicByteCount> cwnd_limits;
188 
189   /*
190    * Experimental flags from QuicConfig.
191    */
192 
193   // Can be disabled by connection option 'B2NA'.
194   bool add_ack_height_to_queueing_threshold = true;
195 
196   // Can be disabled by connection option 'B2RP'.
197   bool avoid_unnecessary_probe_rtt = true;
198 
199   // Can be enabled by connection option 'B2LO'.
200   bool ignore_inflight_lo = false;
201 
202   // Can be enabled by connection option 'B2H2'.
203   bool limit_inflight_hi_by_max_delivered = false;
204 
205   // Can be disabled by connection option 'B2SL'.
206   bool startup_loss_exit_use_max_delivered_for_inflight_hi = true;
207 
208   // Can be enabled by connection option 'B2DL'.
209   bool use_bytes_delivered_for_inflight_hi = false;
210 
211   // Can be disabled by connection option 'B2RC'.
212   bool enable_reno_coexistence = true;
213 
214   // For experimentation to improve fast convergence upon loss.
215   enum QuicBandwidthLoMode : uint8_t {
216     DEFAULT = 0,
217     MIN_RTT_REDUCTION = 1,   // 'BBQ7'
218     INFLIGHT_REDUCTION = 2,  // 'BBQ8'
219     CWND_REDUCTION = 3,      // 'BBQ9'
220   };
221 
222   // Different modes change bandwidth_lo_ differently upon loss.
223   QuicBandwidthLoMode bw_lo_mode_ = QuicBandwidthLoMode::DEFAULT;
224 
225   // Set the pacing gain to 25% larger than the recent BW increase in STARTUP.
226   bool decrease_startup_pacing_at_end_of_round = false;
227 };
228 
229 class QUICHE_EXPORT RoundTripCounter {
230  public:
231   RoundTripCounter();
232 
Count()233   QuicRoundTripCount Count() const { return round_trip_count_; }
234 
last_sent_packet()235   QuicPacketNumber last_sent_packet() const { return last_sent_packet_; }
236 
237   // Must be called in ascending packet number order.
238   void OnPacketSent(QuicPacketNumber packet_number);
239 
240   // Return whether a round trip has just completed.
241   bool OnPacketsAcked(QuicPacketNumber last_acked_packet);
242 
243   void RestartRound();
244 
245  private:
246   QuicRoundTripCount round_trip_count_;
247   QuicPacketNumber last_sent_packet_;
248   // The last sent packet number of the current round trip.
249   QuicPacketNumber end_of_round_trip_;
250 };
251 
252 class QUICHE_EXPORT MinRttFilter {
253  public:
254   MinRttFilter(QuicTime::Delta initial_min_rtt,
255                QuicTime initial_min_rtt_timestamp);
256 
257   void Update(QuicTime::Delta sample_rtt, QuicTime now);
258 
259   void ForceUpdate(QuicTime::Delta sample_rtt, QuicTime now);
260 
Get()261   QuicTime::Delta Get() const { return min_rtt_; }
262 
GetTimestamp()263   QuicTime GetTimestamp() const { return min_rtt_timestamp_; }
264 
265  private:
266   QuicTime::Delta min_rtt_;
267   // Time when the current value of |min_rtt_| was assigned.
268   QuicTime min_rtt_timestamp_;
269 };
270 
271 class QUICHE_EXPORT Bbr2MaxBandwidthFilter {
272  public:
Update(QuicBandwidth sample)273   void Update(QuicBandwidth sample) {
274     max_bandwidth_[1] = std::max(sample, max_bandwidth_[1]);
275   }
276 
Advance()277   void Advance() {
278     if (max_bandwidth_[1].IsZero()) {
279       return;
280     }
281 
282     max_bandwidth_[0] = max_bandwidth_[1];
283     max_bandwidth_[1] = QuicBandwidth::Zero();
284   }
285 
Get()286   QuicBandwidth Get() const {
287     return std::max(max_bandwidth_[0], max_bandwidth_[1]);
288   }
289 
290  private:
291   QuicBandwidth max_bandwidth_[2] = {QuicBandwidth::Zero(),
292                                      QuicBandwidth::Zero()};
293 };
294 
295 // Information that are meaningful only when Bbr2Sender::OnCongestionEvent is
296 // running.
297 struct QUICHE_EXPORT Bbr2CongestionEvent {
298   QuicTime event_time = QuicTime::Zero();
299 
300   // The congestion window prior to the processing of the ack/loss events.
301   QuicByteCount prior_cwnd;
302 
303   // Total bytes inflight before the processing of the ack/loss events.
304   QuicByteCount prior_bytes_in_flight = 0;
305 
306   // Total bytes inflight after the processing of the ack/loss events.
307   QuicByteCount bytes_in_flight = 0;
308 
309   // Total bytes acked from acks in this event.
310   QuicByteCount bytes_acked = 0;
311 
312   // Total bytes lost from losses in this event.
313   QuicByteCount bytes_lost = 0;
314 
315   // Whether acked_packets indicates the end of a round trip.
316   bool end_of_round_trip = false;
317 
318   // When the event happened, whether the sender is probing for bandwidth.
319   bool is_probing_for_bandwidth = false;
320 
321   // Minimum rtt of all bandwidth samples from acked_packets.
322   // QuicTime::Delta::Infinite() if acked_packets is empty.
323   QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
324 
325   // Maximum bandwidth of all bandwidth samples from acked_packets.
326   // This sample may be app-limited, and will be Zero() if there are no newly
327   // acknowledged inflight packets.
328   QuicBandwidth sample_max_bandwidth = QuicBandwidth::Zero();
329 
330   // The send state of the largest packet in acked_packets, unless it is empty.
331   // If acked_packets is empty, it's the send state of the largest packet in
332   // lost_packets.
333   SendTimeState last_packet_send_state;
334 };
335 
336 // Bbr2NetworkModel takes low level congestion signals(packets sent/acked/lost)
337 // as input and produces BBRv2 model parameters like inflight_(hi|lo),
338 // bandwidth_(hi|lo), bandwidth and rtt estimates, etc.
339 class QUICHE_EXPORT Bbr2NetworkModel {
340  public:
341   Bbr2NetworkModel(const Bbr2Params* params, QuicTime::Delta initial_rtt,
342                    QuicTime initial_rtt_timestamp, float cwnd_gain,
343                    float pacing_gain, const BandwidthSampler* old_sampler);
344 
345   void OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight,
346                     QuicPacketNumber packet_number, QuicByteCount bytes,
347                     HasRetransmittableData is_retransmittable);
348 
349   void OnCongestionEventStart(QuicTime event_time,
350                               const AckedPacketVector& acked_packets,
351                               const LostPacketVector& lost_packets,
352                               Bbr2CongestionEvent* congestion_event);
353 
354   void OnCongestionEventFinish(QuicPacketNumber least_unacked_packet,
355                                const Bbr2CongestionEvent& congestion_event);
356 
357   // Update the model without a congestion event.
358   // Min rtt is updated if |rtt| is non-zero and smaller than existing min rtt.
359   void UpdateNetworkParameters(QuicTime::Delta rtt);
360 
361   // Update inflight/bandwidth short-term lower bounds.
362   void AdaptLowerBounds(const Bbr2CongestionEvent& congestion_event);
363 
364   // Restart the current round trip as if it is starting now.
365   void RestartRoundEarly();
366 
AdvanceMaxBandwidthFilter()367   void AdvanceMaxBandwidthFilter() { max_bandwidth_filter_.Advance(); }
368 
OnApplicationLimited()369   void OnApplicationLimited() { bandwidth_sampler_.OnAppLimited(); }
370 
371   // Calculates BDP using the current MaxBandwidth.
BDP()372   QuicByteCount BDP() const { return BDP(MaxBandwidth()); }
373 
BDP(QuicBandwidth bandwidth)374   QuicByteCount BDP(QuicBandwidth bandwidth) const {
375     return bandwidth * MinRtt();
376   }
377 
BDP(QuicBandwidth bandwidth,float gain)378   QuicByteCount BDP(QuicBandwidth bandwidth, float gain) const {
379     return bandwidth * MinRtt() * gain;
380   }
381 
MinRtt()382   QuicTime::Delta MinRtt() const { return min_rtt_filter_.Get(); }
383 
MinRttTimestamp()384   QuicTime MinRttTimestamp() const { return min_rtt_filter_.GetTimestamp(); }
385 
386   // TODO(wub): If we do this too frequently, we can potentailly postpone
387   // PROBE_RTT indefinitely. Observe how it works in production and improve it.
PostponeMinRttTimestamp(QuicTime::Delta duration)388   void PostponeMinRttTimestamp(QuicTime::Delta duration) {
389     min_rtt_filter_.ForceUpdate(MinRtt(), MinRttTimestamp() + duration);
390   }
391 
MaxBandwidth()392   QuicBandwidth MaxBandwidth() const { return max_bandwidth_filter_.Get(); }
393 
MaxAckHeight()394   QuicByteCount MaxAckHeight() const {
395     return bandwidth_sampler_.max_ack_height();
396   }
397 
398   // 2 packets.  Used to indicate the typical number of bytes ACKed at once.
QueueingThresholdExtraBytes()399   QuicByteCount QueueingThresholdExtraBytes() const {
400     return 2 * kDefaultTCPMSS;
401   }
402 
cwnd_limited_before_aggregation_epoch()403   bool cwnd_limited_before_aggregation_epoch() const {
404     return cwnd_limited_before_aggregation_epoch_;
405   }
406 
EnableOverestimateAvoidance()407   void EnableOverestimateAvoidance() {
408     bandwidth_sampler_.EnableOverestimateAvoidance();
409   }
410 
IsBandwidthOverestimateAvoidanceEnabled()411   bool IsBandwidthOverestimateAvoidanceEnabled() const {
412     return bandwidth_sampler_.IsOverestimateAvoidanceEnabled();
413   }
414 
OnPacketNeutered(QuicPacketNumber packet_number)415   void OnPacketNeutered(QuicPacketNumber packet_number) {
416     bandwidth_sampler_.OnPacketNeutered(packet_number);
417   }
418 
num_ack_aggregation_epochs()419   uint64_t num_ack_aggregation_epochs() const {
420     return bandwidth_sampler_.num_ack_aggregation_epochs();
421   }
422 
SetStartNewAggregationEpochAfterFullRound(bool value)423   void SetStartNewAggregationEpochAfterFullRound(bool value) {
424     bandwidth_sampler_.SetStartNewAggregationEpochAfterFullRound(value);
425   }
426 
SetLimitMaxAckHeightTrackerBySendRate(bool value)427   void SetLimitMaxAckHeightTrackerBySendRate(bool value) {
428     bandwidth_sampler_.SetLimitMaxAckHeightTrackerBySendRate(value);
429   }
430 
SetMaxAckHeightTrackerWindowLength(QuicRoundTripCount value)431   void SetMaxAckHeightTrackerWindowLength(QuicRoundTripCount value) {
432     bandwidth_sampler_.SetMaxAckHeightTrackerWindowLength(value);
433   }
434 
SetReduceExtraAckedOnBandwidthIncrease(bool value)435   void SetReduceExtraAckedOnBandwidthIncrease(bool value) {
436     bandwidth_sampler_.SetReduceExtraAckedOnBandwidthIncrease(value);
437   }
438 
439   bool MaybeExpireMinRtt(const Bbr2CongestionEvent& congestion_event);
440 
BandwidthEstimate()441   QuicBandwidth BandwidthEstimate() const {
442     return std::min(MaxBandwidth(), bandwidth_lo_);
443   }
444 
RoundTripCount()445   QuicRoundTripCount RoundTripCount() const {
446     return round_trip_counter_.Count();
447   }
448 
449   // Return true if the number of loss events exceeds max_loss_events and
450   // fraction of bytes lost exceed the loss threshold.
451   bool IsInflightTooHigh(const Bbr2CongestionEvent& congestion_event,
452                          int64_t max_loss_events) const;
453 
454   // Check bandwidth growth in the past round. Must be called at the end of a
455   // round. Returns true if there was sufficient bandwidth growth and false
456   // otherwise.  If it's been too many rounds without growth, also sets
457   // |full_bandwidth_reached_| to true.
458   bool HasBandwidthGrowth(const Bbr2CongestionEvent& congestion_event);
459 
460   // Increments rounds_with_queueing_ if the minimum bytes in flight during the
461   // round is greater than the BDP * |target_gain|.
462   void CheckPersistentQueue(const Bbr2CongestionEvent& congestion_event,
463                             float target_gain);
464 
last_sent_packet()465   QuicPacketNumber last_sent_packet() const {
466     return round_trip_counter_.last_sent_packet();
467   }
468 
total_bytes_acked()469   QuicByteCount total_bytes_acked() const {
470     return bandwidth_sampler_.total_bytes_acked();
471   }
472 
total_bytes_lost()473   QuicByteCount total_bytes_lost() const {
474     return bandwidth_sampler_.total_bytes_lost();
475   }
476 
total_bytes_sent()477   QuicByteCount total_bytes_sent() const {
478     return bandwidth_sampler_.total_bytes_sent();
479   }
480 
loss_events_in_round()481   int64_t loss_events_in_round() const { return loss_events_in_round_; }
482 
max_bytes_delivered_in_round()483   QuicByteCount max_bytes_delivered_in_round() const {
484     return max_bytes_delivered_in_round_;
485   }
486 
min_bytes_in_flight_in_round()487   QuicByteCount min_bytes_in_flight_in_round() const {
488     return min_bytes_in_flight_in_round_;
489   }
490 
inflight_hi_limited_in_round()491   bool inflight_hi_limited_in_round() const {
492     return inflight_hi_limited_in_round_;
493   }
494 
end_of_app_limited_phase()495   QuicPacketNumber end_of_app_limited_phase() const {
496     return bandwidth_sampler_.end_of_app_limited_phase();
497   }
498 
bandwidth_latest()499   QuicBandwidth bandwidth_latest() const { return bandwidth_latest_; }
bandwidth_lo()500   QuicBandwidth bandwidth_lo() const { return bandwidth_lo_; }
bandwidth_lo_default()501   static QuicBandwidth bandwidth_lo_default() {
502     return QuicBandwidth::Infinite();
503   }
clear_bandwidth_lo()504   void clear_bandwidth_lo() { bandwidth_lo_ = bandwidth_lo_default(); }
505 
inflight_latest()506   QuicByteCount inflight_latest() const { return inflight_latest_; }
inflight_lo()507   QuicByteCount inflight_lo() const { return inflight_lo_; }
inflight_lo_default()508   static QuicByteCount inflight_lo_default() {
509     return std::numeric_limits<QuicByteCount>::max();
510   }
clear_inflight_lo()511   void clear_inflight_lo() { inflight_lo_ = inflight_lo_default(); }
512   void cap_inflight_lo(QuicByteCount cap);
513 
514   QuicByteCount inflight_hi_with_headroom() const;
inflight_hi()515   QuicByteCount inflight_hi() const { return inflight_hi_; }
inflight_hi_default()516   static QuicByteCount inflight_hi_default() {
517     return std::numeric_limits<QuicByteCount>::max();
518   }
set_inflight_hi(QuicByteCount inflight_hi)519   void set_inflight_hi(QuicByteCount inflight_hi) {
520     inflight_hi_ = inflight_hi;
521   }
522 
cwnd_gain()523   float cwnd_gain() const { return cwnd_gain_; }
set_cwnd_gain(float cwnd_gain)524   void set_cwnd_gain(float cwnd_gain) { cwnd_gain_ = cwnd_gain; }
525 
pacing_gain()526   float pacing_gain() const { return pacing_gain_; }
set_pacing_gain(float pacing_gain)527   void set_pacing_gain(float pacing_gain) { pacing_gain_ = pacing_gain; }
528 
full_bandwidth_reached()529   bool full_bandwidth_reached() const { return full_bandwidth_reached_; }
set_full_bandwidth_reached()530   void set_full_bandwidth_reached() { full_bandwidth_reached_ = true; }
full_bandwidth_baseline()531   QuicBandwidth full_bandwidth_baseline() const {
532     return full_bandwidth_baseline_;
533   }
rounds_without_bandwidth_growth()534   QuicRoundTripCount rounds_without_bandwidth_growth() const {
535     return rounds_without_bandwidth_growth_;
536   }
rounds_with_queueing()537   QuicRoundTripCount rounds_with_queueing() const {
538     return rounds_with_queueing_;
539   }
540 
541  private:
542   // Called when a new round trip starts.
543   void OnNewRound();
544 
Params()545   const Bbr2Params& Params() const { return *params_; }
546   const Bbr2Params* const params_;
547   RoundTripCounter round_trip_counter_;
548 
549   // Bandwidth sampler provides BBR with the bandwidth measurements at
550   // individual points.
551   BandwidthSampler bandwidth_sampler_;
552   // The filter that tracks the maximum bandwidth over multiple recent round
553   // trips.
554   Bbr2MaxBandwidthFilter max_bandwidth_filter_;
555   MinRttFilter min_rtt_filter_;
556 
557   // Bytes lost in the current round. Updated once per congestion event.
558   QuicByteCount bytes_lost_in_round_ = 0;
559   // Number of loss marking events in the current round.
560   int64_t loss_events_in_round_ = 0;
561 
562   // A max of bytes delivered among all congestion events in the current round.
563   // A congestions event's bytes delivered is the total bytes acked between time
564   // Ts and Ta, which is the time when the largest acked packet(within the
565   // congestion event) was sent and acked, respectively.
566   QuicByteCount max_bytes_delivered_in_round_ = 0;
567 
568   // The minimum bytes in flight during this round.
569   QuicByteCount min_bytes_in_flight_in_round_ =
570       std::numeric_limits<uint64_t>::max();
571 
572   // True if sending was limited by inflight_hi anytime in the current round.
573   bool inflight_hi_limited_in_round_ = false;
574 
575   // Max bandwidth in the current round. Updated once per congestion event.
576   QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
577   // Max bandwidth of recent rounds. Updated once per round.
578   QuicBandwidth bandwidth_lo_ = bandwidth_lo_default();
579   // bandwidth_lo_ at the beginning of a round with loss. Only used when the
580   // bw_lo_mode is non-default.
581   QuicBandwidth prior_bandwidth_lo_ = QuicBandwidth::Zero();
582 
583   // Max inflight in the current round. Updated once per congestion event.
584   QuicByteCount inflight_latest_ = 0;
585   // Max inflight of recent rounds. Updated once per round.
586   QuicByteCount inflight_lo_ = inflight_lo_default();
587   QuicByteCount inflight_hi_ = inflight_hi_default();
588 
589   float cwnd_gain_;
590   float pacing_gain_;
591 
592   // Whether we are cwnd limited prior to the start of the current aggregation
593   // epoch.
594   bool cwnd_limited_before_aggregation_epoch_ = false;
595 
596   // STARTUP-centric fields which experimentally used by PROBE_UP.
597   bool full_bandwidth_reached_ = false;
598   QuicBandwidth full_bandwidth_baseline_ = QuicBandwidth::Zero();
599   QuicRoundTripCount rounds_without_bandwidth_growth_ = 0;
600 
601   // Used by STARTUP and PROBE_UP to decide when to exit.
602   QuicRoundTripCount rounds_with_queueing_ = 0;
603 };
604 
605 enum class Bbr2Mode : uint8_t {
606   // Startup phase of the connection.
607   STARTUP,
608   // After achieving the highest possible bandwidth during the startup, lower
609   // the pacing rate in order to drain the queue.
610   DRAIN,
611   // Cruising mode.
612   PROBE_BW,
613   // Temporarily slow down sending in order to empty the buffer and measure
614   // the real minimum RTT.
615   PROBE_RTT,
616 };
617 
618 QUICHE_EXPORT inline std::ostream& operator<<(std::ostream& os,
619                                               const Bbr2Mode& mode) {
620   switch (mode) {
621     case Bbr2Mode::STARTUP:
622       return os << "STARTUP";
623     case Bbr2Mode::DRAIN:
624       return os << "DRAIN";
625     case Bbr2Mode::PROBE_BW:
626       return os << "PROBE_BW";
627     case Bbr2Mode::PROBE_RTT:
628       return os << "PROBE_RTT";
629   }
630   return os << "<Invalid Mode>";
631 }
632 
633 // The base class for all BBRv2 modes. A Bbr2Sender is in one mode at a time,
634 // this interface is used to implement mode-specific behaviors.
635 class Bbr2Sender;
636 class QUICHE_EXPORT Bbr2ModeBase {
637  public:
Bbr2ModeBase(const Bbr2Sender * sender,Bbr2NetworkModel * model)638   Bbr2ModeBase(const Bbr2Sender* sender, Bbr2NetworkModel* model)
639       : sender_(sender), model_(model) {}
640 
641   virtual ~Bbr2ModeBase() = default;
642 
643   // Called when entering/leaving this mode.
644   // congestion_event != nullptr means BBRv2 is switching modes in the context
645   // of a ack and/or loss.
646   virtual void Enter(QuicTime now,
647                      const Bbr2CongestionEvent* congestion_event) = 0;
648   virtual void Leave(QuicTime now,
649                      const Bbr2CongestionEvent* congestion_event) = 0;
650 
651   virtual Bbr2Mode OnCongestionEvent(
652       QuicByteCount prior_in_flight, QuicTime event_time,
653       const AckedPacketVector& acked_packets,
654       const LostPacketVector& lost_packets,
655       const Bbr2CongestionEvent& congestion_event) = 0;
656 
657   virtual Limits<QuicByteCount> GetCwndLimits() const = 0;
658 
659   virtual bool IsProbingForBandwidth() const = 0;
660 
661   virtual Bbr2Mode OnExitQuiescence(QuicTime now,
662                                     QuicTime quiescence_start_time) = 0;
663 
664  protected:
665   const Bbr2Sender* const sender_;
666   Bbr2NetworkModel* model_;
667 };
668 
BytesInFlight(const SendTimeState & send_state)669 QUICHE_EXPORT inline QuicByteCount BytesInFlight(
670     const SendTimeState& send_state) {
671   QUICHE_DCHECK(send_state.is_valid);
672   if (send_state.bytes_in_flight != 0) {
673     return send_state.bytes_in_flight;
674   }
675   return send_state.total_bytes_sent - send_state.total_bytes_acked -
676          send_state.total_bytes_lost;
677 }
678 
679 }  // namespace quic
680 
681 #endif  // QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_
682