Double the initial congestion window in QuicSentPacketManager This new behavior is gated on the QuicTag IW2X and a new reloadable flag, quic_allow_client_enabled_2x_initial_cwnd. Protected by FLAGS_quic_reloadable_flag_quic_allow_client_enabled_2x_initial_cwnd. PiperOrigin-RevId: 773849231
diff --git a/quiche/common/quiche_feature_flags_list.h b/quiche/common/quiche_feature_flags_list.h index 12ffbdd..1e52ff0 100755 --- a/quiche/common/quiche_feature_flags_list.h +++ b/quiche/common/quiche_feature_flags_list.h
@@ -12,6 +12,7 @@ QUICHE_FLAG(bool, quiche_reloadable_flag_enable_tls_trust_anchor_ids, true, true, "When true, QUIC client and server will support TLS Trust Anchor IDs.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_act_upon_invalid_header, true, true, "If true, reject or send error response code upon receiving invalid request or response headers.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_add_stream_info_to_idle_close_detail, false, true, "If true, include stream information in idle timeout connection close detail.") +QUICHE_FLAG(bool, quiche_reloadable_flag_quic_allow_client_enabled_2x_initial_cwnd, false, false, "Doubles the initial congestion window for QUIC connections when initiated by the client") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_allow_client_enabled_bbr_v2, true, true, "If true, allow client to enable BBRv2 on server via connection option 'B2ON'.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_extra_acked_window, false, true, "When true, the BBR4 copt sets the extra_acked window to 20 RTTs and BBR5 sets it to 40 RTTs.") QUICHE_FLAG(bool, quiche_reloadable_flag_quic_bbr2_probe_two_rounds, true, true, "When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP.")
diff --git a/quiche/quic/core/crypto/crypto_protocol.h b/quiche/quic/core/crypto/crypto_protocol.h index 244321f..9056c47 100644 --- a/quiche/quic/core/crypto/crypto_protocol.h +++ b/quiche/quic/core/crypto/crypto_protocol.h
@@ -151,6 +151,7 @@ DEFINE_STATIC_QUIC_TAG(IW10); // Force ICWND to 10 DEFINE_STATIC_QUIC_TAG(IW20); // Force ICWND to 20 DEFINE_STATIC_QUIC_TAG(IW50); // Force ICWND to 50 +DEFINE_STATIC_QUIC_TAG(IW2X); // Force ICWND to 2x its default value. DEFINE_STATIC_QUIC_TAG(B2ON); // Enable BBRv2 DEFINE_STATIC_QUIC_TAG(B2NA); // For BBRv2, do not add ack // height to queueing threshold
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc index 7b4ae68..ec8d3a4 100644 --- a/quiche/quic/core/http/end_to_end_test.cc +++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -3890,6 +3890,30 @@ server_thread_->Resume(); } +TEST_P(EndToEndTest, NegotiatedDoubledInitialCongestionWindow) { + SetQuicReloadableFlag(quic_allow_client_enabled_2x_initial_cwnd, true); + client_extra_copts_.push_back(kIW2X); + + ASSERT_TRUE(Initialize()); + + // Values are exchanged during crypto handshake, so wait for that to finish. + EXPECT_TRUE(client_->client()->WaitForOneRttKeysAvailable()); + server_thread_->WaitForCryptoHandshakeConfirmed(); + server_thread_->Pause(); + QuicConnection* server_connection = GetServerConnection(); + ASSERT_NE(server_connection, nullptr); + EXPECT_EQ( + server_connection->sent_packet_manager().initial_congestion_window(), + kInitialCongestionWindow * 2); + server_thread_->Resume(); + + QuicConnection* client_connection = GetClientConnection(); + ASSERT_NE(client_connection, nullptr); + EXPECT_EQ( + client_connection->sent_packet_manager().initial_congestion_window(), + kInitialCongestionWindow); +} + TEST_P(EndToEndTest, DifferentFlowControlWindows) { // Client and server can set different initial flow control receive windows. // These are sent in CHLO/SHLO. Tests that these values are exchanged properly
diff --git a/quiche/quic/core/quic_sent_packet_manager.cc b/quiche/quic/core/quic_sent_packet_manager.cc index ae905a5..2c60d23 100644 --- a/quiche/quic/core/quic_sent_packet_manager.cc +++ b/quiche/quic/core/quic_sent_packet_manager.cc
@@ -187,6 +187,13 @@ initial_congestion_window_ = 50; send_algorithm_->SetInitialCongestionWindowInPackets(50); } + if (config.HasClientRequestedIndependentOption(kIW2X, perspective) && + GetQuicReloadableFlag(quic_allow_client_enabled_2x_initial_cwnd)) { + QUIC_RELOADABLE_FLAG_COUNT(quic_allow_client_enabled_2x_initial_cwnd); + initial_congestion_window_ *= 2; + send_algorithm_->SetInitialCongestionWindowInPackets( + initial_congestion_window_); + } if (config.HasClientRequestedIndependentOption(kBWS5, perspective)) { initial_congestion_window_ = 10; send_algorithm_->SetInitialCongestionWindowInPackets(10);
diff --git a/quiche/quic/core/quic_sent_packet_manager_test.cc b/quiche/quic/core/quic_sent_packet_manager_test.cc index 0427cfb..d7c051b 100644 --- a/quiche/quic/core/quic_sent_packet_manager_test.cc +++ b/quiche/quic/core/quic_sent_packet_manager_test.cc
@@ -2121,6 +2121,51 @@ EXPECT_EQ(10u, manager_.initial_congestion_window()); } +TEST_F(QuicSentPacketManagerTest, ServerCongestionWindowDoubledWithIW2X) { + SetQuicReloadableFlag(quic_allow_client_enabled_2x_initial_cwnd, true); + QuicConfig config; + QuicConfigPeer::SetReceivedConnectionOptions(&config, {kIW2X}); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, SetInitialCongestionWindowInPackets( + kInitialCongestionWindow * 2)); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + + EXPECT_EQ(manager_.initial_congestion_window(), kInitialCongestionWindow * 2); +} + +TEST_F(QuicSentPacketManagerTest, + ServerCongestionWindowIsDefaultWithIW2XAndNoFlag) { + SetQuicReloadableFlag(quic_allow_client_enabled_2x_initial_cwnd, false); + QuicConfig config; + QuicConfigPeer::SetReceivedConnectionOptions(&config, {kIW2X}); + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, SetInitialCongestionWindowInPackets(_)) + .Times(0); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + + EXPECT_EQ(manager_.initial_congestion_window(), kInitialCongestionWindow); +} + +TEST_F(QuicSentPacketManagerTest, + ClientCongestionWindowIsDefaultWithIW2XAndNoFlag) { + QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT); + SetQuicReloadableFlag(quic_allow_client_enabled_2x_initial_cwnd, false); + QuicConfig config; + config.SetConnectionOptionsToSend({kIW2X}); + config.SetClientConnectionOptions({}); + + EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); + EXPECT_CALL(*send_algorithm_, + SetInitialCongestionWindowInPackets(kInitialCongestionWindow * 2)) + .Times(0); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + + EXPECT_EQ(manager_.initial_congestion_window(), kInitialCongestionWindow); +} + TEST_F(QuicSentPacketManagerTest, ClientMultiplePacketNumberSpacePtoTimeout) { manager_.EnableMultiplePacketNumberSpacesSupport(); EXPECT_CALL(*send_algorithm_, PacingRate(_))