xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/congestion_control/bbr2_sender.cc (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 #include "quiche/quic/core/congestion_control/bbr2_sender.h"
6 
7 #include <cstddef>
8 
9 #include "quiche/quic/core/congestion_control/bandwidth_sampler.h"
10 #include "quiche/quic/core/congestion_control/bbr2_drain.h"
11 #include "quiche/quic/core/congestion_control/bbr2_misc.h"
12 #include "quiche/quic/core/crypto/crypto_protocol.h"
13 #include "quiche/quic/core/quic_bandwidth.h"
14 #include "quiche/quic/core/quic_tag.h"
15 #include "quiche/quic/core/quic_types.h"
16 #include "quiche/quic/platform/api/quic_flag_utils.h"
17 #include "quiche/quic/platform/api/quic_flags.h"
18 #include "quiche/quic/platform/api/quic_logging.h"
19 #include "quiche/common/platform/api/quiche_logging.h"
20 #include "quiche/common/print_elements.h"
21 
22 namespace quic {
23 
24 namespace {
25 // Constants based on TCP defaults.
26 // The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
27 // Does not inflate the pacing rate.
28 const QuicByteCount kDefaultMinimumCongestionWindow = 4 * kMaxSegmentSize;
29 
30 const float kInitialPacingGain = 2.885f;
31 
32 const int kMaxModeChangesPerCongestionEvent = 4;
33 }  // namespace
34 
35 // Call |member_function_call| based on the current Bbr2Mode we are in. e.g.
36 //
37 //   auto result = BBR2_MODE_DISPATCH(Foo());
38 //
39 // is equivalent to:
40 //
41 //   Bbr2ModeBase& Bbr2Sender::GetCurrentMode() {
42 //     if (mode_ == Bbr2Mode::STARTUP) { return startup_; }
43 //     if (mode_ == Bbr2Mode::DRAIN) { return drain_; }
44 //     ...
45 //   }
46 //   auto result = GetCurrentMode().Foo();
47 //
48 // Except that BBR2_MODE_DISPATCH guarantees the call to Foo() is non-virtual.
49 //
50 #define BBR2_MODE_DISPATCH(member_function_call)     \
51   (mode_ == Bbr2Mode::STARTUP                        \
52        ? (startup_.member_function_call)             \
53        : (mode_ == Bbr2Mode::PROBE_BW                \
54               ? (probe_bw_.member_function_call)     \
55               : (mode_ == Bbr2Mode::DRAIN            \
56                      ? (drain_.member_function_call) \
57                      : (probe_rtt_or_die().member_function_call))))
58 
Bbr2Sender(QuicTime now,const RttStats * rtt_stats,const QuicUnackedPacketMap * unacked_packets,QuicPacketCount initial_cwnd_in_packets,QuicPacketCount max_cwnd_in_packets,QuicRandom * random,QuicConnectionStats * stats,BbrSender * old_sender)59 Bbr2Sender::Bbr2Sender(QuicTime now, const RttStats* rtt_stats,
60                        const QuicUnackedPacketMap* unacked_packets,
61                        QuicPacketCount initial_cwnd_in_packets,
62                        QuicPacketCount max_cwnd_in_packets, QuicRandom* random,
63                        QuicConnectionStats* stats, BbrSender* old_sender)
64     : mode_(Bbr2Mode::STARTUP),
65       rtt_stats_(rtt_stats),
66       unacked_packets_(unacked_packets),
67       random_(random),
68       connection_stats_(stats),
69       params_(kDefaultMinimumCongestionWindow,
70               max_cwnd_in_packets * kDefaultTCPMSS),
71       model_(&params_, rtt_stats->SmoothedOrInitialRtt(),
72              rtt_stats->last_update_time(),
73              /*cwnd_gain=*/1.0,
74              /*pacing_gain=*/kInitialPacingGain,
75              old_sender ? &old_sender->sampler_ : nullptr),
76       initial_cwnd_(cwnd_limits().ApplyLimits(
77           (old_sender) ? old_sender->GetCongestionWindow()
78                        : (initial_cwnd_in_packets * kDefaultTCPMSS))),
79       cwnd_(initial_cwnd_),
80       pacing_rate_(kInitialPacingGain *
81                    QuicBandwidth::FromBytesAndTimeDelta(
82                        cwnd_, rtt_stats->SmoothedOrInitialRtt())),
83       startup_(this, &model_, now),
84       drain_(this, &model_),
85       probe_bw_(this, &model_),
86       probe_rtt_(this, &model_),
87       last_sample_is_app_limited_(false) {
88   QUIC_DVLOG(2) << this << " Initializing Bbr2Sender. mode:" << mode_
89                 << ", PacingRate:" << pacing_rate_ << ", Cwnd:" << cwnd_
90                 << ", CwndLimits:" << cwnd_limits() << "  @ " << now;
91   QUICHE_DCHECK_EQ(mode_, Bbr2Mode::STARTUP);
92 }
93 
SetFromConfig(const QuicConfig & config,Perspective perspective)94 void Bbr2Sender::SetFromConfig(const QuicConfig& config,
95                                Perspective perspective) {
96   if (config.HasClientRequestedIndependentOption(kB2NA, perspective)) {
97     params_.add_ack_height_to_queueing_threshold = false;
98   }
99   if (config.HasClientRequestedIndependentOption(kB2RP, perspective)) {
100     params_.avoid_unnecessary_probe_rtt = false;
101   }
102   if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) {
103     params_.startup_full_bw_rounds = 1;
104   }
105   if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) {
106     params_.startup_full_bw_rounds = 2;
107   }
108   if (config.HasClientRequestedIndependentOption(kB2HR, perspective)) {
109     params_.inflight_hi_headroom = 0.15;
110   }
111   if (config.HasClientRequestedIndependentOption(kICW1, perspective)) {
112     max_cwnd_when_network_parameters_adjusted_ = 100 * kDefaultTCPMSS;
113   }
114 
115   ApplyConnectionOptions(config.ClientRequestedIndependentOptions(perspective));
116 }
117 
ApplyConnectionOptions(const QuicTagVector & connection_options)118 void Bbr2Sender::ApplyConnectionOptions(
119     const QuicTagVector& connection_options) {
120   if (GetQuicReloadableFlag(quic_bbr2_extra_acked_window) &&
121       ContainsQuicTag(connection_options, kBBR4)) {
122     QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_extra_acked_window, 1, 2);
123     model_.SetMaxAckHeightTrackerWindowLength(20);
124   }
125   if (GetQuicReloadableFlag(quic_bbr2_extra_acked_window) &&
126       ContainsQuicTag(connection_options, kBBR5)) {
127     QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_extra_acked_window, 2, 2);
128     model_.SetMaxAckHeightTrackerWindowLength(40);
129   }
130   if (ContainsQuicTag(connection_options, kBBQ1)) {
131     params_.startup_pacing_gain = 2.773;
132     params_.drain_pacing_gain = 1.0 / params_.drain_cwnd_gain;
133   }
134   if (ContainsQuicTag(connection_options, kBBQ2)) {
135     params_.startup_cwnd_gain = 2.885;
136     params_.drain_cwnd_gain = 2.885;
137     model_.set_cwnd_gain(params_.startup_cwnd_gain);
138   }
139   if (ContainsQuicTag(connection_options, kB2LO)) {
140     params_.ignore_inflight_lo = true;
141   }
142   if (ContainsQuicTag(connection_options, kB2NE)) {
143     params_.always_exit_startup_on_excess_loss = true;
144   }
145   if (ContainsQuicTag(connection_options, kB2SL)) {
146     params_.startup_loss_exit_use_max_delivered_for_inflight_hi = false;
147   }
148   if (ContainsQuicTag(connection_options, kB2H2)) {
149     params_.limit_inflight_hi_by_max_delivered = true;
150   }
151   if (ContainsQuicTag(connection_options, kB2DL)) {
152     params_.use_bytes_delivered_for_inflight_hi = true;
153   }
154   if (ContainsQuicTag(connection_options, kB2RC)) {
155     params_.enable_reno_coexistence = false;
156   }
157   if (ContainsQuicTag(connection_options, kBSAO)) {
158     model_.EnableOverestimateAvoidance();
159   }
160   if (ContainsQuicTag(connection_options, kBBQ6)) {
161     params_.decrease_startup_pacing_at_end_of_round = true;
162   }
163   if (ContainsQuicTag(connection_options, kBBQ7)) {
164     params_.bw_lo_mode_ = Bbr2Params::QuicBandwidthLoMode::MIN_RTT_REDUCTION;
165   }
166   if (ContainsQuicTag(connection_options, kBBQ8)) {
167     params_.bw_lo_mode_ = Bbr2Params::QuicBandwidthLoMode::INFLIGHT_REDUCTION;
168   }
169   if (ContainsQuicTag(connection_options, kBBQ9)) {
170     params_.bw_lo_mode_ = Bbr2Params::QuicBandwidthLoMode::CWND_REDUCTION;
171   }
172   if (ContainsQuicTag(connection_options, kB202)) {
173     params_.max_probe_up_queue_rounds = 1;
174   }
175   if (ContainsQuicTag(connection_options, kB203)) {
176     params_.probe_up_ignore_inflight_hi = false;
177   }
178   if (ContainsQuicTag(connection_options, kB204)) {
179     model_.SetReduceExtraAckedOnBandwidthIncrease(true);
180   }
181   if (ContainsQuicTag(connection_options, kB205)) {
182     params_.startup_include_extra_acked = true;
183   }
184   if (ContainsQuicTag(connection_options, kB207)) {
185     params_.max_startup_queue_rounds = 1;
186   }
187   if (ContainsQuicTag(connection_options, kBBRA)) {
188     model_.SetStartNewAggregationEpochAfterFullRound(true);
189   }
190   if (ContainsQuicTag(connection_options, kBBRB)) {
191     model_.SetLimitMaxAckHeightTrackerBySendRate(true);
192   }
193   if (ContainsQuicTag(connection_options, kB206)) {
194     params_.startup_full_loss_count = params_.probe_bw_full_loss_count;
195   }
196   if (ContainsQuicTag(connection_options, kBBPD)) {
197     // Derived constant to ensure fairness.
198     params_.probe_bw_probe_down_pacing_gain = 0.91;
199   }
200   if (GetQuicReloadableFlag(quic_bbr2_simplify_inflight_hi) &&
201       ContainsQuicTag(connection_options, kBBHI)) {
202     QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_simplify_inflight_hi);
203     params_.probe_up_simplify_inflight_hi = true;
204     // Simplify inflight_hi is intended as an alternative to ignoring it,
205     // so ensure we're not ignoring it.
206     params_.probe_up_ignore_inflight_hi = false;
207   }
208   if (GetQuicReloadableFlag(quic_bbr2_probe_two_rounds) &&
209       ContainsQuicTag(connection_options, kBB2U)) {
210     QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_probe_two_rounds, 1, 3);
211     params_.max_probe_up_queue_rounds = 2;
212   }
213   if (GetQuicReloadableFlag(quic_bbr2_probe_two_rounds) &&
214       ContainsQuicTag(connection_options, kBB2S)) {
215     QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_probe_two_rounds, 2, 3);
216     params_.max_startup_queue_rounds = 2;
217   }
218 }
219 
GetCwndLimitsByMode() const220 Limits<QuicByteCount> Bbr2Sender::GetCwndLimitsByMode() const {
221   switch (mode_) {
222     case Bbr2Mode::STARTUP:
223       return startup_.GetCwndLimits();
224     case Bbr2Mode::PROBE_BW:
225       return probe_bw_.GetCwndLimits();
226     case Bbr2Mode::DRAIN:
227       return drain_.GetCwndLimits();
228     case Bbr2Mode::PROBE_RTT:
229       return probe_rtt_.GetCwndLimits();
230     default:
231       QUICHE_NOTREACHED();
232       return Unlimited<QuicByteCount>();
233   }
234 }
235 
cwnd_limits() const236 const Limits<QuicByteCount>& Bbr2Sender::cwnd_limits() const {
237   return params().cwnd_limits;
238 }
239 
AdjustNetworkParameters(const NetworkParams & params)240 void Bbr2Sender::AdjustNetworkParameters(const NetworkParams& params) {
241   model_.UpdateNetworkParameters(params.rtt);
242 
243   if (mode_ == Bbr2Mode::STARTUP) {
244     const QuicByteCount prior_cwnd = cwnd_;
245 
246     QuicBandwidth effective_bandwidth =
247         std::max(params.bandwidth, model_.BandwidthEstimate());
248     connection_stats_->cwnd_bootstrapping_rtt_us =
249         model_.MinRtt().ToMicroseconds();
250 
251     if (params.max_initial_congestion_window > 0) {
252       max_cwnd_when_network_parameters_adjusted_ =
253           params.max_initial_congestion_window * kDefaultTCPMSS;
254     }
255     cwnd_ = cwnd_limits().ApplyLimits(
256         std::min(max_cwnd_when_network_parameters_adjusted_,
257                  model_.BDP(effective_bandwidth)));
258 
259     if (!params.allow_cwnd_to_decrease) {
260       cwnd_ = std::max(cwnd_, prior_cwnd);
261     }
262 
263     pacing_rate_ = std::max(pacing_rate_, QuicBandwidth::FromBytesAndTimeDelta(
264                                               cwnd_, model_.MinRtt()));
265   }
266 }
267 
SetInitialCongestionWindowInPackets(QuicPacketCount congestion_window)268 void Bbr2Sender::SetInitialCongestionWindowInPackets(
269     QuicPacketCount congestion_window) {
270   if (mode_ == Bbr2Mode::STARTUP) {
271     // The cwnd limits is unchanged and still applies to the new cwnd.
272     cwnd_ = cwnd_limits().ApplyLimits(congestion_window * kDefaultTCPMSS);
273   }
274 }
275 
OnCongestionEvent(bool,QuicByteCount prior_in_flight,QuicTime event_time,const AckedPacketVector & acked_packets,const LostPacketVector & lost_packets,QuicPacketCount,QuicPacketCount)276 void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
277                                    QuicByteCount prior_in_flight,
278                                    QuicTime event_time,
279                                    const AckedPacketVector& acked_packets,
280                                    const LostPacketVector& lost_packets,
281                                    QuicPacketCount /*num_ect*/,
282                                    QuicPacketCount /*num_ce*/) {
283   QUIC_DVLOG(3) << this
284                 << " OnCongestionEvent. prior_in_flight:" << prior_in_flight
285                 << " prior_cwnd:" << cwnd_ << "  @ " << event_time;
286   Bbr2CongestionEvent congestion_event;
287   congestion_event.prior_cwnd = cwnd_;
288   congestion_event.prior_bytes_in_flight = prior_in_flight;
289   congestion_event.is_probing_for_bandwidth =
290       BBR2_MODE_DISPATCH(IsProbingForBandwidth());
291 
292   model_.OnCongestionEventStart(event_time, acked_packets, lost_packets,
293                                 &congestion_event);
294 
295   if (InSlowStart()) {
296     if (!lost_packets.empty()) {
297       connection_stats_->slowstart_packets_lost += lost_packets.size();
298       connection_stats_->slowstart_bytes_lost += congestion_event.bytes_lost;
299     }
300     if (congestion_event.end_of_round_trip) {
301       ++connection_stats_->slowstart_num_rtts;
302     }
303   }
304 
305   // Number of mode changes allowed for this congestion event.
306   int mode_changes_allowed = kMaxModeChangesPerCongestionEvent;
307   while (true) {
308     Bbr2Mode next_mode = BBR2_MODE_DISPATCH(
309         OnCongestionEvent(prior_in_flight, event_time, acked_packets,
310                           lost_packets, congestion_event));
311 
312     if (next_mode == mode_) {
313       break;
314     }
315 
316     QUIC_DVLOG(2) << this << " Mode change:  " << mode_ << " ==> " << next_mode
317                   << "  @ " << event_time;
318     BBR2_MODE_DISPATCH(Leave(event_time, &congestion_event));
319     mode_ = next_mode;
320     BBR2_MODE_DISPATCH(Enter(event_time, &congestion_event));
321     --mode_changes_allowed;
322     if (mode_changes_allowed < 0) {
323       QUIC_BUG(quic_bug_10443_1)
324           << "Exceeded max number of mode changes per congestion event.";
325       break;
326     }
327   }
328 
329   UpdatePacingRate(congestion_event.bytes_acked);
330   QUIC_BUG_IF(quic_bug_10443_2, pacing_rate_.IsZero())
331       << "Pacing rate must not be zero!";
332 
333   UpdateCongestionWindow(congestion_event.bytes_acked);
334   QUIC_BUG_IF(quic_bug_10443_3, cwnd_ == 0u)
335       << "Congestion window must not be zero!";
336 
337   model_.OnCongestionEventFinish(unacked_packets_->GetLeastUnacked(),
338                                  congestion_event);
339   last_sample_is_app_limited_ =
340       congestion_event.last_packet_send_state.is_app_limited;
341   if (!last_sample_is_app_limited_) {
342     has_non_app_limited_sample_ = true;
343   }
344   if (congestion_event.bytes_in_flight == 0 &&
345       params().avoid_unnecessary_probe_rtt) {
346     OnEnterQuiescence(event_time);
347   }
348 
349   QUIC_DVLOG(3)
350       << this
351       << " END CongestionEvent(acked:" << quiche::PrintElements(acked_packets)
352       << ", lost:" << lost_packets.size() << ") "
353       << ", Mode:" << mode_ << ", RttCount:" << model_.RoundTripCount()
354       << ", BytesInFlight:" << congestion_event.bytes_in_flight
355       << ", PacingRate:" << PacingRate(0) << ", CWND:" << GetCongestionWindow()
356       << ", PacingGain:" << model_.pacing_gain()
357       << ", CwndGain:" << model_.cwnd_gain()
358       << ", BandwidthEstimate(kbps):" << BandwidthEstimate().ToKBitsPerSecond()
359       << ", MinRTT(us):" << model_.MinRtt().ToMicroseconds()
360       << ", BDP:" << model_.BDP(BandwidthEstimate())
361       << ", BandwidthLatest(kbps):"
362       << model_.bandwidth_latest().ToKBitsPerSecond()
363       << ", BandwidthLow(kbps):" << model_.bandwidth_lo().ToKBitsPerSecond()
364       << ", BandwidthHigh(kbps):" << model_.MaxBandwidth().ToKBitsPerSecond()
365       << ", InflightLatest:" << model_.inflight_latest()
366       << ", InflightLow:" << model_.inflight_lo()
367       << ", InflightHigh:" << model_.inflight_hi()
368       << ", TotalAcked:" << model_.total_bytes_acked()
369       << ", TotalLost:" << model_.total_bytes_lost()
370       << ", TotalSent:" << model_.total_bytes_sent() << "  @ " << event_time;
371 }
372 
UpdatePacingRate(QuicByteCount bytes_acked)373 void Bbr2Sender::UpdatePacingRate(QuicByteCount bytes_acked) {
374   if (BandwidthEstimate().IsZero()) {
375     return;
376   }
377 
378   if (model_.total_bytes_acked() == bytes_acked) {
379     // After the first ACK, cwnd_ is still the initial congestion window.
380     pacing_rate_ = QuicBandwidth::FromBytesAndTimeDelta(cwnd_, model_.MinRtt());
381     return;
382   }
383 
384   QuicBandwidth target_rate = model_.pacing_gain() * model_.BandwidthEstimate();
385   if (model_.full_bandwidth_reached()) {
386     pacing_rate_ = target_rate;
387     return;
388   }
389   if (params_.decrease_startup_pacing_at_end_of_round &&
390       model_.pacing_gain() < Params().startup_pacing_gain) {
391     pacing_rate_ = target_rate;
392     return;
393   }
394   if (params_.bw_lo_mode_ != Bbr2Params::DEFAULT &&
395       model_.loss_events_in_round() > 0) {
396     pacing_rate_ = target_rate;
397     return;
398   }
399 
400   // By default, the pacing rate never decreases in STARTUP.
401   if (target_rate > pacing_rate_) {
402     pacing_rate_ = target_rate;
403   }
404 }
405 
UpdateCongestionWindow(QuicByteCount bytes_acked)406 void Bbr2Sender::UpdateCongestionWindow(QuicByteCount bytes_acked) {
407   QuicByteCount target_cwnd = GetTargetCongestionWindow(model_.cwnd_gain());
408 
409   const QuicByteCount prior_cwnd = cwnd_;
410   if (model_.full_bandwidth_reached() || Params().startup_include_extra_acked) {
411     target_cwnd += model_.MaxAckHeight();
412     cwnd_ = std::min(prior_cwnd + bytes_acked, target_cwnd);
413   } else if (prior_cwnd < target_cwnd || prior_cwnd < 2 * initial_cwnd_) {
414     cwnd_ = prior_cwnd + bytes_acked;
415   }
416   const QuicByteCount desired_cwnd = cwnd_;
417 
418   cwnd_ = GetCwndLimitsByMode().ApplyLimits(cwnd_);
419   const QuicByteCount model_limited_cwnd = cwnd_;
420 
421   cwnd_ = cwnd_limits().ApplyLimits(cwnd_);
422 
423   QUIC_DVLOG(3) << this << " Updating CWND. target_cwnd:" << target_cwnd
424                 << ", max_ack_height:" << model_.MaxAckHeight()
425                 << ", full_bw:" << model_.full_bandwidth_reached()
426                 << ", bytes_acked:" << bytes_acked
427                 << ", inflight_lo:" << model_.inflight_lo()
428                 << ", inflight_hi:" << model_.inflight_hi() << ". (prior_cwnd) "
429                 << prior_cwnd << " => (desired_cwnd) " << desired_cwnd
430                 << " => (model_limited_cwnd) " << model_limited_cwnd
431                 << " => (final_cwnd) " << cwnd_;
432 }
433 
GetTargetCongestionWindow(float gain) const434 QuicByteCount Bbr2Sender::GetTargetCongestionWindow(float gain) const {
435   return std::max(model_.BDP(model_.BandwidthEstimate(), gain),
436                   cwnd_limits().Min());
437 }
438 
OnPacketSent(QuicTime sent_time,QuicByteCount bytes_in_flight,QuicPacketNumber packet_number,QuicByteCount bytes,HasRetransmittableData is_retransmittable)439 void Bbr2Sender::OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight,
440                               QuicPacketNumber packet_number,
441                               QuicByteCount bytes,
442                               HasRetransmittableData is_retransmittable) {
443   QUIC_DVLOG(3) << this << " OnPacketSent: pkn:" << packet_number
444                 << ", bytes:" << bytes << ", cwnd:" << cwnd_
445                 << ", inflight:" << bytes_in_flight + bytes
446                 << ", total_sent:" << model_.total_bytes_sent() + bytes
447                 << ", total_acked:" << model_.total_bytes_acked()
448                 << ", total_lost:" << model_.total_bytes_lost() << "  @ "
449                 << sent_time;
450   if (InSlowStart()) {
451     ++connection_stats_->slowstart_packets_sent;
452     connection_stats_->slowstart_bytes_sent += bytes;
453   }
454   if (bytes_in_flight == 0 && params().avoid_unnecessary_probe_rtt) {
455     OnExitQuiescence(sent_time);
456   }
457   model_.OnPacketSent(sent_time, bytes_in_flight, packet_number, bytes,
458                       is_retransmittable);
459 }
460 
OnPacketNeutered(QuicPacketNumber packet_number)461 void Bbr2Sender::OnPacketNeutered(QuicPacketNumber packet_number) {
462   model_.OnPacketNeutered(packet_number);
463 }
464 
CanSend(QuicByteCount bytes_in_flight)465 bool Bbr2Sender::CanSend(QuicByteCount bytes_in_flight) {
466   const bool result = bytes_in_flight < GetCongestionWindow();
467   return result;
468 }
469 
GetCongestionWindow() const470 QuicByteCount Bbr2Sender::GetCongestionWindow() const {
471   // TODO(wub): Implement Recovery?
472   return cwnd_;
473 }
474 
PacingRate(QuicByteCount) const475 QuicBandwidth Bbr2Sender::PacingRate(QuicByteCount /*bytes_in_flight*/) const {
476   return pacing_rate_;
477 }
478 
OnApplicationLimited(QuicByteCount bytes_in_flight)479 void Bbr2Sender::OnApplicationLimited(QuicByteCount bytes_in_flight) {
480   if (bytes_in_flight >= GetCongestionWindow()) {
481     return;
482   }
483 
484   model_.OnApplicationLimited();
485   QUIC_DVLOG(2) << this << " Becoming application limited. Last sent packet: "
486                 << model_.last_sent_packet()
487                 << ", CWND: " << GetCongestionWindow();
488 }
489 
GetTargetBytesInflight() const490 QuicByteCount Bbr2Sender::GetTargetBytesInflight() const {
491   QuicByteCount bdp = model_.BDP(model_.BandwidthEstimate());
492   return std::min(bdp, GetCongestionWindow());
493 }
494 
PopulateConnectionStats(QuicConnectionStats * stats) const495 void Bbr2Sender::PopulateConnectionStats(QuicConnectionStats* stats) const {
496   stats->num_ack_aggregation_epochs = model_.num_ack_aggregation_epochs();
497 }
498 
OnEnterQuiescence(QuicTime now)499 void Bbr2Sender::OnEnterQuiescence(QuicTime now) {
500   last_quiescence_start_ = now;
501 }
502 
OnExitQuiescence(QuicTime now)503 void Bbr2Sender::OnExitQuiescence(QuicTime now) {
504   if (last_quiescence_start_ != QuicTime::Zero()) {
505     Bbr2Mode next_mode = BBR2_MODE_DISPATCH(
506         OnExitQuiescence(now, std::min(now, last_quiescence_start_)));
507     if (next_mode != mode_) {
508       BBR2_MODE_DISPATCH(Leave(now, nullptr));
509       mode_ = next_mode;
510       BBR2_MODE_DISPATCH(Enter(now, nullptr));
511     }
512     last_quiescence_start_ = QuicTime::Zero();
513   }
514 }
515 
GetDebugState() const516 std::string Bbr2Sender::GetDebugState() const {
517   std::ostringstream stream;
518   stream << ExportDebugState();
519   return stream.str();
520 }
521 
ExportDebugState() const522 Bbr2Sender::DebugState Bbr2Sender::ExportDebugState() const {
523   DebugState s;
524   s.mode = mode_;
525   s.round_trip_count = model_.RoundTripCount();
526   s.bandwidth_hi = model_.MaxBandwidth();
527   s.bandwidth_lo = model_.bandwidth_lo();
528   s.bandwidth_est = BandwidthEstimate();
529   s.inflight_hi = model_.inflight_hi();
530   s.inflight_lo = model_.inflight_lo();
531   s.max_ack_height = model_.MaxAckHeight();
532   s.min_rtt = model_.MinRtt();
533   s.min_rtt_timestamp = model_.MinRttTimestamp();
534   s.congestion_window = cwnd_;
535   s.pacing_rate = pacing_rate_;
536   s.last_sample_is_app_limited = last_sample_is_app_limited_;
537   s.end_of_app_limited_phase = model_.end_of_app_limited_phase();
538 
539   s.startup = startup_.ExportDebugState();
540   s.drain = drain_.ExportDebugState();
541   s.probe_bw = probe_bw_.ExportDebugState();
542   s.probe_rtt = probe_rtt_.ExportDebugState();
543 
544   return s;
545 }
546 
operator <<(std::ostream & os,const Bbr2Sender::DebugState & s)547 std::ostream& operator<<(std::ostream& os, const Bbr2Sender::DebugState& s) {
548   os << "mode: " << s.mode << "\n";
549   os << "round_trip_count: " << s.round_trip_count << "\n";
550   os << "bandwidth_hi ~ lo ~ est: " << s.bandwidth_hi << " ~ " << s.bandwidth_lo
551      << " ~ " << s.bandwidth_est << "\n";
552   os << "min_rtt: " << s.min_rtt << "\n";
553   os << "min_rtt_timestamp: " << s.min_rtt_timestamp << "\n";
554   os << "congestion_window: " << s.congestion_window << "\n";
555   os << "pacing_rate: " << s.pacing_rate << "\n";
556   os << "last_sample_is_app_limited: " << s.last_sample_is_app_limited << "\n";
557 
558   if (s.mode == Bbr2Mode::STARTUP) {
559     os << s.startup;
560   }
561 
562   if (s.mode == Bbr2Mode::DRAIN) {
563     os << s.drain;
564   }
565 
566   if (s.mode == Bbr2Mode::PROBE_BW) {
567     os << s.probe_bw;
568   }
569 
570   if (s.mode == Bbr2Mode::PROBE_RTT) {
571     os << s.probe_rtt;
572   }
573 
574   return os;
575 }
576 
577 }  // namespace quic
578