gfe-relnote: In QUIC BBRv2's PROBE_BW mode, make sure the cwnd upper bound is at least BDP + AckHeight. Protected by --gfe2_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd. Connection option 'B2CL' is introduced to hold back to the original behavior. PiperOrigin-RevId: 306901798 Change-Id: Idc47368fd380419fce1f92f36a5a2ad3e1c879f3
diff --git a/quic/core/congestion_control/bbr2_misc.h b/quic/core/congestion_control/bbr2_misc.h index 0c72131..2315e63 100644 --- a/quic/core/congestion_control/bbr2_misc.h +++ b/quic/core/congestion_control/bbr2_misc.h
@@ -177,6 +177,10 @@ // Can be disabled by connection option 'B2RP'. bool avoid_unnecessary_probe_rtt = true; + + // Can be disabled by connection option 'B2CL'. + bool avoid_too_low_probe_bw_cwnd = + GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd); }; class QUIC_EXPORT_PRIVATE RoundTripCounter {
diff --git a/quic/core/congestion_control/bbr2_probe_bw.cc b/quic/core/congestion_control/bbr2_probe_bw.cc index 1a7a719..6fb7eee 100644 --- a/quic/core/congestion_control/bbr2_probe_bw.cc +++ b/quic/core/congestion_control/bbr2_probe_bw.cc
@@ -79,12 +79,36 @@ } Limits<QuicByteCount> Bbr2ProbeBwMode::GetCwndLimits() const { - if (cycle_.phase == CyclePhase::PROBE_CRUISE) { + if (!GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd)) { + if (cycle_.phase == CyclePhase::PROBE_CRUISE) { + return NoGreaterThan( + std::min(model_->inflight_lo(), model_->inflight_hi_with_headroom())); + } + return NoGreaterThan( - std::min(model_->inflight_lo(), model_->inflight_hi_with_headroom())); + std::min(model_->inflight_lo(), model_->inflight_hi())); } - return NoGreaterThan(std::min(model_->inflight_lo(), model_->inflight_hi())); + QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_avoid_too_low_probe_bw_cwnd); + + QuicByteCount upper_limit = + std::min(model_->inflight_lo(), cycle_.phase == CyclePhase::PROBE_CRUISE + ? model_->inflight_hi_with_headroom() + : model_->inflight_hi()); + + if (Params().avoid_too_low_probe_bw_cwnd) { + // Ensure upper_limit is at least BDP + AckHeight. + QuicByteCount bdp_with_ack_height = + model_->BDP(model_->MaxBandwidth()) + model_->MaxAckHeight(); + if (upper_limit < bdp_with_ack_height) { + QUIC_DVLOG(3) << sender_ << " Rasing upper_limit from " << upper_limit + << " to " << bdp_with_ack_height; + QUIC_CODE_COUNT(quic_bbr2_avoid_too_low_probe_bw_cwnd_in_effect); + upper_limit = bdp_with_ack_height; + } + } + + return NoGreaterThan(upper_limit); } bool Bbr2ProbeBwMode::IsProbingForBandwidth() const {
diff --git a/quic/core/congestion_control/bbr2_sender.cc b/quic/core/congestion_control/bbr2_sender.cc index ff5f74f..a367a56 100644 --- a/quic/core/congestion_control/bbr2_sender.cc +++ b/quic/core/congestion_control/bbr2_sender.cc
@@ -115,6 +115,10 @@ params_.startup_cwnd_gain = 2; params_.drain_cwnd_gain = 2; } + if (GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd) && + config.HasClientRequestedIndependentOption(kB2CL, perspective)) { + params_.avoid_too_low_probe_bw_cwnd = false; + } } Limits<QuicByteCount> Bbr2Sender::GetCwndLimitsByMode() const {
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h index aaa2d6f..9a5eaf2 100644 --- a/quic/core/crypto/crypto_protocol.h +++ b/quic/core/crypto/crypto_protocol.h
@@ -121,6 +121,9 @@ // height to queueing threshold const QuicTag kB2RP = TAG('B', '2', 'R', 'P'); // For BBRv2, run PROBE_RTT on // the regular schedule +const QuicTag kB2CL = TAG('B', '2', 'C', 'L'); // For BBRv2, allow PROBE_BW + // cwnd to be below BDP + ack + // height. const QuicTag kBSAO = TAG('B', 'S', 'A', 'O'); // Avoid Overestimation in // Bandwidth Sampler with ack // aggregation