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