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) {