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)