gfe-relnote: In QUIC, re-calculate pacing rate when cwnd gets bootstrapped. Protected by gfe2_reloadable_flag_quic_bbr_fix_pacing_rate.

PiperOrigin-RevId: 277502654
Change-Id: I2c76d7a6ddb7e6097ed294d08b51678e455fa2b1
diff --git a/quic/core/congestion_control/bbr_sender.cc b/quic/core/congestion_control/bbr_sender.cc
index b0fd50d..1ba6b42 100644
--- a/quic/core/congestion_control/bbr_sender.cc
+++ b/quic/core/congestion_control/bbr_sender.cc
@@ -372,6 +372,13 @@
       set_high_cwnd_gain(kDerivedHighCWNDGain);
     }
     congestion_window_ = new_cwnd;
+    if (GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {
+      QUIC_RELOADABLE_FLAG_COUNT(quic_bbr_fix_pacing_rate);
+      // Pace at the rate of new_cwnd / RTT.
+      QuicBandwidth new_pacing_rate =
+          QuicBandwidth::FromBytesAndTimeDelta(congestion_window_, GetMinRtt());
+      pacing_rate_ = std::max(pacing_rate_, new_pacing_rate);
+    }
   }
 }
 
diff --git a/quic/core/congestion_control/bbr_sender_test.cc b/quic/core/congestion_control/bbr_sender_test.cc
index 8ecab87..290cf4c 100644
--- a/quic/core/congestion_control/bbr_sender_test.cc
+++ b/quic/core/congestion_control/bbr_sender_test.cc
@@ -1308,5 +1308,73 @@
                 ->GetSlowStartDuration());
 }
 
+// Regression test for b/143540157.
+TEST_F(BbrSenderTest, RecalculatePacingRateOnCwndChange1RTT) {
+  CreateDefaultSetup();
+
+  bbr_sender_.AddBytesToTransfer(1 * 1024 * 1024);
+  // Wait until an ACK comes back.
+  const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(5);
+  bool simulator_result = simulator_.RunUntilOrTimeout(
+      [this]() { return !sender_->ExportDebugState().min_rtt.IsZero(); },
+      timeout);
+  ASSERT_TRUE(simulator_result);
+  const QuicByteCount previous_cwnd =
+      sender_->ExportDebugState().congestion_window;
+
+  // Bootstrap cwnd.
+  bbr_sender_.connection()->AdjustNetworkParameters(
+      kTestLinkBandwidth, QuicTime::Delta::Zero(), false);
+  EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
+  EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
+  EXPECT_LT(previous_cwnd, sender_->ExportDebugState().congestion_window);
+
+  if (GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {
+    // Verify pacing rate is re-calculated based on the new cwnd and min_rtt.
+    EXPECT_APPROX_EQ(QuicBandwidth::FromBytesAndTimeDelta(
+                         sender_->ExportDebugState().congestion_window,
+                         sender_->ExportDebugState().min_rtt),
+                     sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+  } else {
+    // Pacing rate is still based on initial cwnd.
+    EXPECT_APPROX_EQ(QuicBandwidth::FromBytesAndTimeDelta(
+                         kInitialCongestionWindowPackets * kDefaultTCPMSS,
+                         sender_->ExportDebugState().min_rtt),
+                     sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+  }
+}
+
+TEST_F(BbrSenderTest, RecalculatePacingRateOnCwndChange0RTT) {
+  CreateDefaultSetup();
+  // Initial RTT is available.
+  const_cast<RttStats*>(rtt_stats_)->set_initial_rtt(kTestRtt);
+
+  // Bootstrap cwnd.
+  bbr_sender_.connection()->AdjustNetworkParameters(
+      kTestLinkBandwidth, QuicTime::Delta::Zero(), false);
+  EXPECT_EQ(kTestLinkBandwidth, sender_->ExportDebugState().max_bandwidth);
+  EXPECT_EQ(kTestLinkBandwidth, sender_->BandwidthEstimate());
+  EXPECT_LT(kInitialCongestionWindowPackets * kDefaultTCPMSS,
+            sender_->ExportDebugState().congestion_window);
+  // No Rtt sample is available.
+  EXPECT_TRUE(sender_->ExportDebugState().min_rtt.IsZero());
+
+  if (GetQuicReloadableFlag(quic_bbr_fix_pacing_rate)) {
+    // Verify pacing rate is re-calculated based on the new cwnd and initial
+    // RTT.
+    EXPECT_APPROX_EQ(QuicBandwidth::FromBytesAndTimeDelta(
+                         sender_->ExportDebugState().congestion_window,
+                         rtt_stats_->initial_rtt()),
+                     sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+  } else {
+    // Pacing rate is still based on initial cwnd.
+    EXPECT_APPROX_EQ(
+        2.885f * QuicBandwidth::FromBytesAndTimeDelta(
+                     kInitialCongestionWindowPackets * kDefaultTCPMSS,
+                     rtt_stats_->initial_rtt()),
+        sender_->PacingRate(/*bytes_in_flight=*/0), 0.01f);
+  }
+}
+
 }  // namespace test
 }  // namespace quic