In QUIC BBRv2, support NetworkParams.max_initial_congestion_window when bootstrapping cwnd.
This makes BBRv2 behave the same w.r.t NetworkParams.max_initial_congestion_window.
Protected by FLAGS_quic_reloadable_flag_quic_bbr2_support_max_bootstrap_cwnd.
PiperOrigin-RevId: 336959204
Change-Id: I888f067c6c0dcb3eaaa1b9191a83dd7ec16344c0
diff --git a/quic/core/congestion_control/bbr2_sender.cc b/quic/core/congestion_control/bbr2_sender.cc
index 6de304a..3185cc0 100644
--- a/quic/core/congestion_control/bbr2_sender.cc
+++ b/quic/core/congestion_control/bbr2_sender.cc
@@ -135,6 +135,11 @@
QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_use_tcp_inflight_hi_headroom);
params_.inflight_hi_headroom = 0.15;
}
+ if (GetQuicReloadableFlag(quic_bbr2_support_max_bootstrap_cwnd) &&
+ config.HasClientRequestedIndependentOption(kICW1, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_support_max_bootstrap_cwnd, 1, 4);
+ max_cwnd_when_network_parameters_adjusted_ = 100 * kDefaultTCPMSS;
+ }
ApplyConnectionOptions(config.ClientRequestedIndependentOptions(perspective));
}
@@ -184,7 +189,22 @@
QuicBandwidth effective_bandwidth =
std::max(params.bandwidth, model_.BandwidthEstimate());
- cwnd_ = cwnd_limits().ApplyLimits(model_.BDP(effective_bandwidth));
+ if (GetQuicReloadableFlag(quic_bbr2_support_max_bootstrap_cwnd)) {
+ if (params.max_initial_congestion_window > 0) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_support_max_bootstrap_cwnd, 2,
+ 4);
+ max_cwnd_when_network_parameters_adjusted_ =
+ params.max_initial_congestion_window * kDefaultTCPMSS;
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_support_max_bootstrap_cwnd, 3,
+ 4);
+ }
+ cwnd_ = cwnd_limits().ApplyLimits(
+ std::min(max_cwnd_when_network_parameters_adjusted_,
+ model_.BDP(effective_bandwidth)));
+ } else {
+ cwnd_ = cwnd_limits().ApplyLimits(model_.BDP(effective_bandwidth));
+ }
if (!params.allow_cwnd_to_decrease) {
cwnd_ = std::max(cwnd_, prior_cwnd);
diff --git a/quic/core/congestion_control/bbr2_sender.h b/quic/core/congestion_control/bbr2_sender.h
index 39964a0..1b328fe 100644
--- a/quic/core/congestion_control/bbr2_sender.h
+++ b/quic/core/congestion_control/bbr2_sender.h
@@ -183,6 +183,10 @@
// Instead, use params() to get read-only access.
Bbr2Params params_;
+ // Max congestion window when adjusting network parameters.
+ QuicByteCount max_cwnd_when_network_parameters_adjusted_ =
+ kMaxInitialCongestionWindow * kDefaultTCPMSS;
+
Bbr2NetworkModel model_;
const QuicByteCount initial_cwnd_;
diff --git a/quic/core/congestion_control/bbr2_simulator_test.cc b/quic/core/congestion_control/bbr2_simulator_test.cc
index 43a4fd7..4273667 100644
--- a/quic/core/congestion_control/bbr2_simulator_test.cc
+++ b/quic/core/congestion_control/bbr2_simulator_test.cc
@@ -1025,6 +1025,87 @@
DriveOutOfStartup(params);
}
+TEST_F(Bbr2DefaultTopologyTest,
+ 200InitialCongestionWindowWithNetworkParameterAdjusted) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ sender_endpoint_.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);
+
+ // Bootstrap cwnd by a overly large bandwidth sample.
+ sender_connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(1024 * params.BottleneckBandwidth(),
+ QuicTime::Delta::Zero(), false));
+
+ if (GetQuicReloadableFlag(quic_bbr2_support_max_bootstrap_cwnd)) {
+ // Verify cwnd is capped at 200.
+ EXPECT_EQ(200 * kDefaultTCPMSS,
+ sender_->ExportDebugState().congestion_window);
+ EXPECT_GT(1024 * params.BottleneckBandwidth(), sender_->PacingRate(0));
+ }
+}
+
+TEST_F(Bbr2DefaultTopologyTest,
+ 100InitialCongestionWindowFromNetworkParameter) {
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ sender_endpoint_.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);
+
+ // Bootstrap cwnd by a overly large bandwidth sample.
+ SendAlgorithmInterface::NetworkParams network_params(
+ 1024 * params.BottleneckBandwidth(), QuicTime::Delta::Zero(), false);
+ network_params.max_initial_congestion_window = 100;
+ sender_connection()->AdjustNetworkParameters(network_params);
+
+ if (GetQuicReloadableFlag(quic_bbr2_support_max_bootstrap_cwnd)) {
+ // Verify cwnd is capped at 100.
+ EXPECT_EQ(100 * kDefaultTCPMSS,
+ sender_->ExportDebugState().congestion_window);
+ EXPECT_GT(1024 * params.BottleneckBandwidth(), sender_->PacingRate(0));
+ }
+}
+
+TEST_F(Bbr2DefaultTopologyTest,
+ 100InitialCongestionWindowWithNetworkParameterAdjusted) {
+ SetConnectionOption(kICW1);
+ DefaultTopologyParams params;
+ CreateNetwork(params);
+
+ sender_endpoint_.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);
+
+ // Bootstrap cwnd by a overly large bandwidth sample.
+ sender_connection()->AdjustNetworkParameters(
+ SendAlgorithmInterface::NetworkParams(1024 * params.BottleneckBandwidth(),
+ QuicTime::Delta::Zero(), false));
+
+ if (GetQuicReloadableFlag(quic_bbr2_support_max_bootstrap_cwnd)) {
+ // Verify cwnd is capped at 100.
+ EXPECT_EQ(100 * kDefaultTCPMSS,
+ sender_->ExportDebugState().congestion_window);
+ EXPECT_GT(1024 * params.BottleneckBandwidth(), sender_->PacingRate(0));
+ }
+}
+
// All Bbr2MultiSenderTests uses the following network topology:
//
// Sender 0 (A Bbr2Sender)