gfe-relnote: Add B2LO connection option to ignore inflight_lo in BBRv2.  Protected by gfe2_reloadable_flag_quic_bbr2_ignore_inflight_lo.

This may not be the ideal long term option, but given bandwidth_lo is an existing shorter_term adjustment to loss, I fear inflight_lo is causing excess harm and complexity.  This could overlap with quic_bbr2_avoid_too_low_probe_bw_cwnd, but may be a preferable alternative.

BBRv2 tests pass with this default enabled as well.

PiperOrigin-RevId: 308673519
Change-Id: I6ce8b13dda3ca427919820dab04d135e3e4c8867
diff --git a/quic/core/congestion_control/bbr2_misc.cc b/quic/core/congestion_control/bbr2_misc.cc
index 97d645c..42978c3 100644
--- a/quic/core/congestion_control/bbr2_misc.cc
+++ b/quic/core/congestion_control/bbr2_misc.cc
@@ -186,15 +186,17 @@
     if (bandwidth_lo_.IsInfinite()) {
       bandwidth_lo_ = MaxBandwidth();
     }
-    if (inflight_lo_ == inflight_lo_default()) {
-      inflight_lo_ = congestion_event.prior_cwnd;
-    }
-
     bandwidth_lo_ =
         std::max(bandwidth_latest_, bandwidth_lo_ * (1.0 - Params().beta));
     QUIC_DVLOG(3) << "bandwidth_lo_ updated to " << bandwidth_lo_
                   << ", bandwidth_latest_ is " << bandwidth_latest_;
 
+    if (Params().ignore_inflight_lo) {
+      return;
+    }
+    if (inflight_lo_ == inflight_lo_default()) {
+      inflight_lo_ = congestion_event.prior_cwnd;
+    }
     inflight_lo_ = std::max<QuicByteCount>(
         inflight_latest_, inflight_lo_ * (1.0 - Params().beta));
   }
@@ -282,6 +284,15 @@
   round_trip_counter_.RestartRound();
 }
 
+void Bbr2NetworkModel::cap_inflight_lo(QuicByteCount cap) {
+  if (Params().ignore_inflight_lo) {
+    return;
+  }
+  if (inflight_lo_ != inflight_lo_default() && inflight_lo_ > cap) {
+    inflight_lo_ = cap;
+  }
+}
+
 QuicByteCount Bbr2NetworkModel::inflight_hi_with_headroom() const {
   QuicByteCount headroom = inflight_hi_ * Params().inflight_hi_headroom;
 
diff --git a/quic/core/congestion_control/bbr2_misc.h b/quic/core/congestion_control/bbr2_misc.h
index a71f517..e110a4c 100644
--- a/quic/core/congestion_control/bbr2_misc.h
+++ b/quic/core/congestion_control/bbr2_misc.h
@@ -181,6 +181,9 @@
   // Can be disabled by connection option 'B2CL'.
   bool avoid_too_low_probe_bw_cwnd =
       GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd);
+
+  // Can be enabled by connection option 'B2LO'.
+  bool ignore_inflight_lo = false;
 };
 
 class QUIC_EXPORT_PRIVATE RoundTripCounter {
@@ -424,11 +427,7 @@
     return std::numeric_limits<QuicByteCount>::max();
   }
   void clear_inflight_lo() { inflight_lo_ = inflight_lo_default(); }
-  void cap_inflight_lo(QuicByteCount cap) {
-    if (inflight_lo_ != inflight_lo_default() && inflight_lo_ > cap) {
-      inflight_lo_ = cap;
-    }
-  }
+  void cap_inflight_lo(QuicByteCount cap);
 
   QuicByteCount inflight_hi_with_headroom() const;
   QuicByteCount inflight_hi() const { return inflight_hi_; }
diff --git a/quic/core/congestion_control/bbr2_sender.cc b/quic/core/congestion_control/bbr2_sender.cc
index 8428bb5..65c4f16 100644
--- a/quic/core/congestion_control/bbr2_sender.cc
+++ b/quic/core/congestion_control/bbr2_sender.cc
@@ -129,6 +129,11 @@
     QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fewer_startup_round_trips, 2, 2);
     params_.startup_full_bw_rounds = 2;
   }
+  if (GetQuicReloadableFlag(quic_bbr2_ignore_inflight_lo) &&
+      config.HasClientRequestedIndependentOption(kB2LO, perspective)) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_ignore_inflight_lo);
+    params_.ignore_inflight_lo = true;
+  }
 }
 
 Limits<QuicByteCount> Bbr2Sender::GetCwndLimitsByMode() const {
diff --git a/quic/core/congestion_control/bbr2_startup.h b/quic/core/congestion_control/bbr2_startup.h
index e8f37ff..378a4fd 100644
--- a/quic/core/congestion_control/bbr2_startup.h
+++ b/quic/core/congestion_control/bbr2_startup.h
@@ -33,6 +33,8 @@
       const Bbr2CongestionEvent& congestion_event) override;
 
   Limits<QuicByteCount> GetCwndLimits() const override {
+    // Inflight_lo is never set in STARTUP.
+    DCHECK_EQ(Bbr2NetworkModel::inflight_lo_default(), model_->inflight_lo());
     return NoGreaterThan(model_->inflight_lo());
   }
 
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 9a5eaf2..97da818 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -124,6 +124,7 @@
 const QuicTag kB2CL = TAG('B', '2', 'C', 'L');   // For BBRv2, allow PROBE_BW
                                                  // cwnd to be below BDP + ack
                                                  // height.
+const QuicTag kB2LO = TAG('B', '2', 'L', 'O');   // Ignore inflight_lo in BBR2
 const QuicTag kBSAO = TAG('B', 'S', 'A', 'O');   // Avoid Overestimation in
                                                  // Bandwidth Sampler with ack
                                                  // aggregation