Allow client to activate PragueCubic congestion control via connection option for experiment purposes. At first, this option will be enabled on a local Chrome instance for basic lab experiments. This option has no effect on the server, so it could be stripped from the client hello. @ianswett recommended I send it to remain consistent with the framework, for now. see go/prague-cubic. PiperOrigin-RevId: 688685081
diff --git a/quiche/quic/core/crypto/crypto_protocol.h b/quiche/quic/core/crypto/crypto_protocol.h index 48e98d5..c9f697f 100644 --- a/quiche/quic/core/crypto/crypto_protocol.h +++ b/quiche/quic/core/crypto/crypto_protocol.h
@@ -287,6 +287,9 @@ const QuicTag kCRNT = TAG('C', 'R', 'N', 'T'); +const QuicTag kPRGC = TAG('P', 'R', 'G', 'C'); // Prague Cubic congestion + // control (client-only) + // Optional support of truncated Connection IDs. If sent by a peer, the value // is the minimum number of bytes allowed for the connection ID sent to the // peer.
diff --git a/quiche/quic/core/quic_config_test.cc b/quiche/quic/core/quic_config_test.cc index a157eaa..ea311e9 100644 --- a/quiche/quic/core/quic_config_test.cc +++ b/quiche/quic/core/quic_config_test.cc
@@ -14,6 +14,7 @@ #include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_time.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" #include "quiche/quic/platform/api/quic_expect_bug.h" #include "quiche/quic/platform/api/quic_flags.h" @@ -335,9 +336,12 @@ QuicConfig client_config; QuicTagVector copt; copt.push_back(kTBBR); + copt.push_back(kPRGC); client_config.SetConnectionOptionsToSend(copt); EXPECT_TRUE(client_config.HasClientSentConnectionOption( kTBBR, Perspective::IS_CLIENT)); + EXPECT_TRUE(client_config.HasClientSentConnectionOption( + kPRGC, Perspective::IS_CLIENT)); CryptoHandshakeMessage msg; client_config.ToHandshakeMessage(&msg, version_.transport_version); @@ -349,9 +353,11 @@ EXPECT_TRUE(config_.negotiated()); EXPECT_TRUE(config_.HasReceivedConnectionOptions()); - EXPECT_EQ(1u, config_.ReceivedConnectionOptions().size()); + EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size()); EXPECT_TRUE( config_.HasClientSentConnectionOption(kTBBR, Perspective::IS_SERVER)); + EXPECT_TRUE( + config_.HasClientSentConnectionOption(kPRGC, Perspective::IS_SERVER)); } TEST_P(QuicConfigTest, DontSendClientConnectionOptions) {
diff --git a/quiche/quic/core/quic_sent_packet_manager.cc b/quiche/quic/core/quic_sent_packet_manager.cc index e4f364c..94c228d 100644 --- a/quiche/quic/core/quic_sent_packet_manager.cc +++ b/quiche/quic/core/quic_sent_packet_manager.cc
@@ -21,6 +21,7 @@ #include "quiche/quic/core/quic_connection_stats.h" #include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_packet_number.h" +#include "quiche/quic/core/quic_tag.h" #include "quiche/quic/core/quic_transmission_info.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" @@ -136,6 +137,10 @@ } // Configure congestion control. + if (perspective == Perspective::IS_CLIENT && + config.HasClientRequestedIndependentOption(kPRGC, perspective)) { + SetSendAlgorithm(kPragueCubic); + } if (config.HasClientRequestedIndependentOption(kTBBR, perspective)) { SetSendAlgorithm(kBBR); } @@ -240,7 +245,9 @@ } else if (ContainsQuicTag(connection_options, kQBIC)) { cc_type = kCubicBytes; } - + // This function is only used in server experiments, so do not apply the + // client-only PRGC tag. + QUICHE_DCHECK(unacked_packets_.perspective() == Perspective::IS_SERVER); if (cc_type.has_value()) { SetSendAlgorithm(*cc_type); }
diff --git a/quiche/quic/core/quic_sent_packet_manager_test.cc b/quiche/quic/core/quic_sent_packet_manager_test.cc index 5e8c62b..d086c12 100644 --- a/quiche/quic/core/quic_sent_packet_manager_test.cc +++ b/quiche/quic/core/quic_sent_packet_manager_test.cc
@@ -1246,6 +1246,15 @@ manager_.SetFromConfig(config); EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) ->GetCongestionControlType()); + + options.clear(); + options.push_back(kPRGC); + QuicConfigPeer::SetReceivedConnectionOptions(&config, options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + // The server does nothing on kPRGC. + EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType()); } TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) { @@ -1293,6 +1302,24 @@ manager_.SetFromConfig(config); EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) ->GetCongestionControlType()); + + options.clear(); + options.push_back(kPRGC); + config.SetClientConnectionOptions(options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + EXPECT_EQ(kPragueCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType()); + + // Test that kPRGC is overriden by other options. + options.clear(); + options.push_back(kPRGC); + options.push_back(kTBBR); + config.SetClientConnectionOptions(options); + EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); + manager_.SetFromConfig(config); + EXPECT_EQ(kBBR, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_) + ->GetCongestionControlType()); } TEST_F(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {