Fix a bug in BBRv2 bw_lo experimental modes where the second ACK would cause the pacing rate to suddenly drop. Also limits reduction of bandwidth_lo to 30% in a single round at the end of a round.
Protected by quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode.
PiperOrigin-RevId: 366875020
Change-Id: If1ae0d5fbdbd0770c2b4d1a219de2fd64e83e0b0
diff --git a/quic/core/congestion_control/bbr2_misc.cc b/quic/core/congestion_control/bbr2_misc.cc
index a12cd5d..d24e50e 100644
--- a/quic/core/congestion_control/bbr2_misc.cc
+++ b/quic/core/congestion_control/bbr2_misc.cc
@@ -9,6 +9,7 @@
#include "quic/core/quic_time.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_flag_utils.h"
+#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
namespace quic {
@@ -201,6 +202,10 @@
if (bandwidth_lo_.IsInfinite()) {
bandwidth_lo_ = MaxBandwidth();
}
+ // Save bandwidth_lo_ if it hasn't already been saved.
+ if (prior_bandwidth_lo_.IsZero()) {
+ prior_bandwidth_lo_ = bandwidth_lo_;
+ }
switch (Params().bw_lo_mode_) {
case Bbr2Params::MIN_RTT_REDUCTION:
bandwidth_lo_ =
@@ -229,9 +234,10 @@
QUIC_BUG(quic_bug_10466_1) << "Unreachable case DEFAULT.";
}
if (pacing_gain_ > Params().startup_full_bw_threshold) {
- // In STARTUP, pacing_gain_ is applied to bandwidth_lo_, so this backs
- // that multiplication out to allow the pacing rate to decrease,
- // but not below bandwidth_latest_ * startup_full_bw_threshold.
+ // In STARTUP, pacing_gain_ is applied to bandwidth_lo_ in
+ // UpdatePacingRate, so this backs that multiplication out to allow the
+ // pacing rate to decrease, but not below
+ // bandwidth_latest_ * startup_full_bw_threshold.
bandwidth_lo_ =
std::max(bandwidth_lo_,
bandwidth_latest_ *
@@ -240,6 +246,15 @@
// Ensure bandwidth_lo isn't lower than bandwidth_latest_.
bandwidth_lo_ = std::max(bandwidth_lo_, bandwidth_latest_);
}
+ // If it's the end of the round, ensure bandwidth_lo doesn't decrease more
+ // than beta.
+ if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode) &&
+ congestion_event.end_of_round_trip) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode, 2, 2);
+ bandwidth_lo_ =
+ std::max(bandwidth_lo_, prior_bandwidth_lo_ * (1.0 - Params().beta));
+ prior_bandwidth_lo_ = QuicBandwidth::Zero();
+ }
// This early return ignores inflight_lo as well.
return;
}
diff --git a/quic/core/congestion_control/bbr2_misc.h b/quic/core/congestion_control/bbr2_misc.h
index 21ceaaf..8f5d418 100644
--- a/quic/core/congestion_control/bbr2_misc.h
+++ b/quic/core/congestion_control/bbr2_misc.h
@@ -535,6 +535,9 @@
QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
// Max bandwidth of recent rounds. Updated once per round.
QuicBandwidth bandwidth_lo_ = bandwidth_lo_default();
+ // bandwidth_lo_ at the beginning of a round with loss. Only used when the
+ // bw_lo_mode is non-default.
+ QuicBandwidth prior_bandwidth_lo_ = QuicBandwidth::Zero();
// Max inflight in the current round. Updated once per congestion event.
QuicByteCount inflight_latest_ = 0;
diff --git a/quic/core/congestion_control/bbr2_sender.cc b/quic/core/congestion_control/bbr2_sender.cc
index 1589ebd..d0f6127 100644
--- a/quic/core/congestion_control/bbr2_sender.cc
+++ b/quic/core/congestion_control/bbr2_sender.cc
@@ -321,9 +321,17 @@
}
QuicBandwidth target_rate = model_.pacing_gain() * model_.BandwidthEstimate();
- if (model_.full_bandwidth_reached() ||
- params_.decrease_startup_pacing_at_end_of_round ||
- params_.bw_lo_mode_ != Bbr2Params::DEFAULT) {
+ if (model_.full_bandwidth_reached()) {
+ pacing_rate_ = target_rate;
+ return;
+ }
+ if (params_.decrease_startup_pacing_at_end_of_round &&
+ model_.pacing_gain() < Params().startup_pacing_gain) {
+ pacing_rate_ = target_rate;
+ return;
+ }
+ if (params_.bw_lo_mode_ != Bbr2Params::DEFAULT &&
+ model_.loss_events_in_round() > 0) {
pacing_rate_ = target_rate;
return;
}
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 7ef70ec..cc42f32 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -13,6 +13,7 @@
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_alps_include_scheme_in_origin, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_and_tls_allow_sni_without_dots, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_with_too_many_outstanding_packets, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_support_multiple_cids_v2, false)