gfe-relnote: (n/a) In QUIC BBRv1, default enable connection options LRTT and BBQ2, and deprecate unused QUIC connection options BBS1 and BBRS. Protected by --gfe2_reloadable_flag_quic_bbr_default_exit_startup_on_loss.

PiperOrigin-RevId: 304406108
Change-Id: I2e89d9474a09e9d9fb5157f69577f55f7a4176b8
diff --git a/quic/core/congestion_control/bbr_sender.cc b/quic/core/congestion_control/bbr_sender.cc
index ee74d70..8331611 100644
--- a/quic/core/congestion_control/bbr_sender.cc
+++ b/quic/core/congestion_control/bbr_sender.cc
@@ -106,7 +106,8 @@
       congestion_window_gain_constant_(
           static_cast<float>(GetQuicFlag(FLAGS_quic_bbr_cwnd_gain))),
       num_startup_rtts_(kRoundTripsWithoutGrowthBeforeExitingStartup),
-      exit_startup_on_loss_(false),
+      exit_startup_on_loss_(
+          GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)),
       cycle_current_offset_(0),
       last_cycle_start_(QuicTime::Zero()),
       is_at_full_bandwidth_(false),
@@ -137,6 +138,10 @@
     stats_->slowstart_duration = QuicTimeAccumulator();
   }
   EnterStartupMode(now);
+  if (exit_startup_on_loss_) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_default_exit_startup_on_loss);
+    set_high_cwnd_gain(kDerivedHighCWNDGain);
+  }
 }
 
 BbrSender::~BbrSender() {}
@@ -198,8 +203,14 @@
     return ProbeRttCongestionWindow();
   }
 
-  if (InRecovery() && !(rate_based_startup_ && mode_ == STARTUP)) {
-    return std::min(congestion_window_, recovery_window_);
+  if (exit_startup_on_loss_) {
+    if (InRecovery()) {
+      return std::min(congestion_window_, recovery_window_);
+    }
+  } else {
+    if (InRecovery() && !(rate_based_startup_ && mode_ == STARTUP)) {
+      return std::min(congestion_window_, recovery_window_);
+    }
   }
 
   return congestion_window_;
@@ -257,13 +268,15 @@
   if (config.HasClientRequestedIndependentOption(k2RTT, perspective)) {
     num_startup_rtts_ = 2;
   }
-  if (config.HasClientRequestedIndependentOption(kBBRS, perspective)) {
+  if (!exit_startup_on_loss_ &&
+      config.HasClientRequestedIndependentOption(kBBRS, perspective)) {
     slower_startup_ = true;
   }
   if (config.HasClientRequestedIndependentOption(kBBR3, perspective)) {
     drain_to_target_ = true;
   }
-  if (config.HasClientRequestedIndependentOption(kBBS1, perspective)) {
+  if (!exit_startup_on_loss_ &&
+      config.HasClientRequestedIndependentOption(kBBS1, perspective)) {
     rate_based_startup_ = true;
   }
   if (GetQuicReloadableFlag(quic_bbr_mitigate_overly_large_bandwidth_sample)) {
@@ -290,7 +303,8 @@
     set_high_cwnd_gain(kDerivedHighGain);
     set_drain_gain(1.f / kDerivedHighGain);
   }
-  if (config.HasClientRequestedIndependentOption(kBBQ2, perspective)) {
+  if (!exit_startup_on_loss_ &&
+      config.HasClientRequestedIndependentOption(kBBQ2, perspective)) {
     set_high_cwnd_gain(kDerivedHighCWNDGain);
   }
   if (config.HasClientRequestedIndependentOption(kBBQ3, perspective)) {
@@ -824,12 +838,14 @@
     }
   }
 
-  // Slow the pacing rate in STARTUP once loss has ever been detected.
-  const bool has_ever_detected_loss = end_recovery_at_.IsInitialized();
-  if (slower_startup_ && has_ever_detected_loss &&
-      has_non_app_limited_sample_) {
-    pacing_rate_ = kStartupAfterLossGain * BandwidthEstimate();
-    return;
+  if (!exit_startup_on_loss_) {
+    // Slow the pacing rate in STARTUP once loss has ever been detected.
+    const bool has_ever_detected_loss = end_recovery_at_.IsInitialized();
+    if (slower_startup_ && has_ever_detected_loss &&
+        has_non_app_limited_sample_) {
+      pacing_rate_ = kStartupAfterLossGain * BandwidthEstimate();
+      return;
+    }
   }
 
   // Do not decrease the pacing rate during startup.
@@ -877,7 +893,7 @@
 
 void BbrSender::CalculateRecoveryWindow(QuicByteCount bytes_acked,
                                         QuicByteCount bytes_lost) {
-  if (rate_based_startup_ && mode_ == STARTUP) {
+  if (!exit_startup_on_loss_ && rate_based_startup_ && mode_ == STARTUP) {
     return;
   }
 
diff --git a/quic/core/congestion_control/bbr_sender.h b/quic/core/congestion_control/bbr_sender.h
index eb8282a..ab5d819 100644
--- a/quic/core/congestion_control/bbr_sender.h
+++ b/quic/core/congestion_control/bbr_sender.h
@@ -324,6 +324,8 @@
   const float congestion_window_gain_constant_;
   // The number of RTTs to stay in STARTUP mode.  Defaults to 3.
   QuicRoundTripCount num_startup_rtts_;
+
+  // Latched value of --quic_bbr_default_exit_startup_on_loss.
   // If true, exit startup if all of the following conditions are met:
   // - 1RTT has passed with no bandwidth increase,
   // - Some number of congestion events happened with loss, in the last round.
diff --git a/quic/core/congestion_control/bbr_sender_test.cc b/quic/core/congestion_control/bbr_sender_test.cc
index 6f91153..e07931b 100644
--- a/quic/core/congestion_control/bbr_sender_test.cc
+++ b/quic/core/congestion_control/bbr_sender_test.cc
@@ -340,45 +340,6 @@
   EXPECT_APPROX_EQ(kTestRtt, sender_->GetMinRtt(), 0.2f);
 }
 
-TEST_F(BbrSenderTest, SimpleTransferEarlyPacketLoss) {
-  SetQuicReloadableFlag(quic_bbr_no_bytes_acked_in_startup_recovery, true);
-  // Enable rate based startup so the recovery window doesn't hide the true
-  // congestion_window_ in GetCongestionWindow().
-  SetConnectionOption(kBBS1);
-  // Disable Ack Decimation on the receiver, because it can increase srtt.
-  QuicConnectionPeer::SetAckMode(receiver_.connection(), AckMode::TCP_ACKING);
-  CreateDefaultSetup();
-
-  // At startup make sure we are at the default.
-  EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
-  // Verify that Sender is in slow start.
-  EXPECT_TRUE(sender_->InSlowStart());
-  // At startup make sure we can send.
-  EXPECT_TRUE(sender_->CanSend(0));
-  // And that window is un-affected.
-  EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
-
-  // Transfer 12MB.
-  bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
-  // Drop the first packet.
-  receiver_.DropNextIncomingPacket();
-  bool simulator_result = simulator_.RunUntilOrTimeout(
-      [this]() {
-        if (sender_->InRecovery()) {
-          // Two packets are acked before the first is declared lost.
-          EXPECT_LE(sender_->GetCongestionWindow(),
-                    (kDefaultWindowTCP + 2 * kDefaultTCPMSS));
-        }
-        return bbr_sender_.bytes_to_transfer() == 0 || !sender_->InSlowStart();
-      },
-      QuicTime::Delta::FromSeconds(30));
-  EXPECT_TRUE(simulator_result) << "Simple transfer failed.  Bytes remaining: "
-                                << bbr_sender_.bytes_to_transfer();
-  EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
-  EXPECT_EQ(1u, bbr_sender_.connection()->GetStats().packets_lost);
-  EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
-}
-
 TEST_F(BbrSenderTest, RemoveBytesLostInRecovery) {
   SetQuicReloadableFlag(quic_bbr_one_mss_conservation, false);
   // Disable Ack Decimation on the receiver, because it can increase srtt.
@@ -706,10 +667,18 @@
   ASSERT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
   EXPECT_APPROX_EQ(sender_->BandwidthEstimate() * (1 / 2.885f),
                    sender_->PacingRate(0), 0.01f);
-  // BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
-  // with approximately 1.88 BDPs.  Here, we use 1.5 to give some margin for
-  // error.
-  EXPECT_GE(queue->bytes_queued(), 1.5 * kTestBdp);
+
+  if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+    // BBR uses CWND gain of 2.88 during STARTUP, hence it will fill the buffer
+    // with approximately 1.88 BDPs.  Here, we use 1.5 to give some margin for
+    // error.
+    EXPECT_GE(queue->bytes_queued(), 1.5 * kTestBdp);
+  } else {
+    // BBR uses CWND gain of 2 during STARTUP, hence it will fill the buffer
+    // with approximately 1 BDP.  Here, we use 0.8 to give some margin for
+    // error.
+    EXPECT_GE(queue->bytes_queued(), 0.8 * kTestBdp);
+  }
 
   // Observe increased RTT due to bufferbloat.
   const QuicTime::Delta queueing_delay =
@@ -843,12 +812,12 @@
   DriveOutOfStartup();
 
   const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
-  bool simulator_result;
-
-  // Start a few cycles prior to the high gain one.
-  simulator_result = simulator_.RunUntilOrTimeout(
-      [this]() { return sender_->ExportDebugState().gain_cycle_index == 6; },
-      timeout);
+  while (!(sender_->ExportDebugState().gain_cycle_index >= 4 &&
+           bbr_sender_.bytes_to_transfer() == 0)) {
+    bbr_sender_.AddBytesToTransfer(kTestLinkBandwidth.ToBytesPerSecond());
+    ASSERT_TRUE(simulator_.RunUntilOrTimeout(
+        [this]() { return bbr_sender_.bytes_to_transfer() == 0; }, timeout));
+  }
 
   // Send at 10% of available rate.  Run for 3 seconds, checking in the middle
   // and at the end.  The pacing gain should be high throughout.
@@ -867,10 +836,10 @@
   // PROBE_BW mode to enter low gain cycle, and exit it earlier than one min_rtt
   // due to running out of data to send.
   bbr_sender_.AddBytesToTransfer(1.3 * kTestBdp);
-  simulator_result = simulator_.RunUntilOrTimeout(
+  ASSERT_TRUE(simulator_.RunUntilOrTimeout(
       [this]() { return sender_->ExportDebugState().gain_cycle_index == 1; },
-      timeout);
-  ASSERT_TRUE(simulator_result);
+      timeout));
+
   simulator_.RunFor(0.75 * sender_->ExportDebugState().min_rtt);
   EXPECT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
   EXPECT_EQ(2, sender_->ExportDebugState().gain_cycle_index);
@@ -963,11 +932,13 @@
   EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
 }
 
-// Test exiting STARTUP earlier upon loss due to the LRTT connection option.
-TEST_F(BbrSenderTest, SimpleTransferLRTTStartup) {
+// Test exiting STARTUP earlier upon loss.
+TEST_F(BbrSenderTest, SimpleTransferExitStartupOnLoss) {
   CreateDefaultSetup();
 
-  SetConnectionOption(kLRTT);
+  if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+    SetConnectionOption(kLRTT);
+  }
   EXPECT_EQ(3u, sender_->num_startup_rtts());
 
   // Run until the full bandwidth is reached and check how many rounds it was.
@@ -991,11 +962,13 @@
   EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
 }
 
-// Test exiting STARTUP earlier upon loss due to the LRTT connection option.
-TEST_F(BbrSenderTest, SimpleTransferLRTTStartupSmallBuffer) {
+// Test exiting STARTUP earlier upon loss with a small buffer.
+TEST_F(BbrSenderTest, SimpleTransferExitStartupOnLossSmallBuffer) {
   CreateSmallBufferSetup();
 
-  SetConnectionOption(kLRTT);
+  if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+    SetConnectionOption(kLRTT);
+  }
   EXPECT_EQ(3u, sender_->num_startup_rtts());
 
   // Run until the full bandwidth is reached and check how many rounds it was.
@@ -1019,68 +992,6 @@
   EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
 }
 
-// Test slower pacing after loss in STARTUP due to the BBRS connection option.
-TEST_F(BbrSenderTest, SimpleTransferSlowerStartup) {
-  CreateSmallBufferSetup();
-
-  SetConnectionOption(kBBRS);
-  EXPECT_EQ(3u, sender_->num_startup_rtts());
-
-  // Run until the full bandwidth is reached and check how many rounds it was.
-  bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
-  QuicRoundTripCount max_bw_round = 0;
-  QuicBandwidth max_bw(QuicBandwidth::Zero());
-  bool simulator_result = simulator_.RunUntilOrTimeout(
-      [this, &max_bw, &max_bw_round]() {
-        if (max_bw < sender_->ExportDebugState().max_bandwidth) {
-          max_bw = sender_->ExportDebugState().max_bandwidth;
-          max_bw_round = sender_->ExportDebugState().round_trip_count;
-        }
-        // Expect the pacing rate in STARTUP to decrease once packet loss
-        // is observed, but the CWND does not.
-        if (bbr_sender_.connection()->GetStats().packets_lost > 0 &&
-            !sender_->ExportDebugState().is_at_full_bandwidth &&
-            sender_->has_non_app_limited_sample()) {
-          EXPECT_EQ(1.5f * max_bw, sender_->PacingRate(0));
-        }
-        return sender_->ExportDebugState().is_at_full_bandwidth;
-      },
-      QuicTime::Delta::FromSeconds(5));
-  ASSERT_TRUE(simulator_result);
-  EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
-  EXPECT_GE(3u, sender_->ExportDebugState().round_trip_count - max_bw_round);
-  EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
-  EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
-  EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
-}
-
-// Ensures no change in congestion window in STARTUP after loss.
-TEST_F(BbrSenderTest, SimpleTransferNoConservationInStartup) {
-  CreateSmallBufferSetup();
-
-  SetConnectionOption(kBBS1);
-
-  // Run until the full bandwidth is reached and check how many rounds it was.
-  bbr_sender_.AddBytesToTransfer(12 * 1024 * 1024);
-  bool used_conservation_cwnd = false;
-  bool simulator_result = simulator_.RunUntilOrTimeout(
-      [this, &used_conservation_cwnd]() {
-        if (!sender_->ExportDebugState().is_at_full_bandwidth &&
-            sender_->GetCongestionWindow() <
-                sender_->ExportDebugState().congestion_window) {
-          used_conservation_cwnd = true;
-        }
-        return sender_->ExportDebugState().is_at_full_bandwidth;
-      },
-      QuicTime::Delta::FromSeconds(5));
-  ASSERT_TRUE(simulator_result);
-  EXPECT_FALSE(used_conservation_cwnd);
-  EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
-  EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
-  EXPECT_NE(0u, bbr_sender_.connection()->GetStats().packets_lost);
-  EXPECT_FALSE(sender_->ExportDebugState().last_sample_is_app_limited);
-}
-
 TEST_F(BbrSenderTest, DerivedPacingGainStartup) {
   CreateDefaultSetup();
 
@@ -1111,7 +1022,9 @@
 TEST_F(BbrSenderTest, DerivedCWNDGainStartup) {
   CreateSmallBufferSetup();
 
-  SetConnectionOption(kBBQ2);
+  if (!GetQuicReloadableFlag(quic_bbr_default_exit_startup_on_loss)) {
+    SetConnectionOption(kBBQ2);
+  }
   EXPECT_EQ(3u, sender_->num_startup_rtts());
   // Verify that Sender is in slow start.
   EXPECT_TRUE(sender_->InSlowStart());
@@ -1128,7 +1041,9 @@
       QuicTime::Delta::FromSeconds(5));
   ASSERT_TRUE(simulator_result);
   EXPECT_EQ(BbrSender::DRAIN, sender_->ExportDebugState().mode);
-  EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
+  if (!bbr_sender_.connection()->GetStats().bbr_exit_startup_due_to_loss) {
+    EXPECT_EQ(3u, sender_->ExportDebugState().rounds_without_bandwidth_gain);
+  }
   EXPECT_APPROX_EQ(kTestLinkBandwidth,
                    sender_->ExportDebugState().max_bandwidth, 0.01f);
   float loss_rate =
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 8e03bb3..8af8a04 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -82,8 +82,7 @@
 const QuicTag k1RTT = TAG('1', 'R', 'T', 'T');   // STARTUP in BBR for 1 RTT
 const QuicTag k2RTT = TAG('2', 'R', 'T', 'T');   // STARTUP in BBR for 2 RTTs
 const QuicTag kLRTT = TAG('L', 'R', 'T', 'T');   // Exit STARTUP in BBR on loss
-const QuicTag kBBS1 = TAG('B', 'B', 'S', '1');   // Rate-based recovery in
-                                                 // BBR STARTUP
+const QuicTag kBBS1 = TAG('B', 'B', 'S', '1');   // DEPRECATED
 const QuicTag kBBS2 = TAG('B', 'B', 'S', '2');   // More aggressive packet
                                                  // conservation in BBR STARTUP
 const QuicTag kBBS3 = TAG('B', 'B', 'S', '3');   // Slowstart packet
@@ -99,8 +98,7 @@
 const QuicTag kBBR5 = TAG('B', 'B', 'R', '5');   // 40 RTT ack aggregation
 const QuicTag kBBR9 = TAG('B', 'B', 'R', '9');   // Ignore app-limited calls in
                                                  // BBR if enough inflight.
-const QuicTag kBBRS = TAG('B', 'B', 'R', 'S');   // Use 1.5x pacing in startup
-                                                 // after a loss has occurred.
+const QuicTag kBBRS = TAG('B', 'B', 'R', 'S');   // DEPRECATED
 const QuicTag kBBQ1 = TAG('B', 'B', 'Q', '1');   // BBR with lower 2.77 STARTUP
                                                  // pacing and CWND gain.
 const QuicTag kBBQ2 = TAG('B', 'B', 'Q', '2');   // BBR with lower 2.0 STARTUP