Add a new QUIC Connection option to specify Cubic for the client side only.

Supports the experiment plan in go/prague-cubic.

PiperOrigin-RevId: 707928694
diff --git a/quiche/quic/core/crypto/crypto_protocol.h b/quiche/quic/core/crypto/crypto_protocol.h
index b5acba6..a925471 100644
--- a/quiche/quic/core/crypto/crypto_protocol.h
+++ b/quiche/quic/core/crypto/crypto_protocol.h
@@ -304,6 +304,8 @@
 
 DEFINE_STATIC_QUIC_TAG(PRGC);  // Prague Cubic congestion
                                // control (client-only)
+DEFINE_STATIC_QUIC_TAG(CQBC);  // Client-only Cubic congestion control. Used
+                               // for a control in the PRGC experiment.
 
 // 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
diff --git a/quiche/quic/core/quic_sent_packet_manager.cc b/quiche/quic/core/quic_sent_packet_manager.cc
index 7b270f2..5917ac8 100644
--- a/quiche/quic/core/quic_sent_packet_manager.cc
+++ b/quiche/quic/core/quic_sent_packet_manager.cc
@@ -137,10 +137,6 @@
   }
 
   // Configure congestion control.
-  if (perspective == Perspective::IS_CLIENT &&
-      config.HasClientRequestedIndependentOption(kPRGC, perspective)) {
-    SetSendAlgorithm(kPragueCubic);
-  }
   if (config.HasClientRequestedIndependentOption(kTBBR, perspective)) {
     SetSendAlgorithm(kBBR);
   }
@@ -157,6 +153,13 @@
               config.HasClientRequestedIndependentOption(kQBIC, perspective))) {
     SetSendAlgorithm(kCubicBytes);
   }
+  if (perspective == Perspective::IS_CLIENT) {
+    if (config.HasClientRequestedIndependentOption(kPRGC, perspective)) {
+      SetSendAlgorithm(kPragueCubic);
+    } else if (config.HasClientRequestedIndependentOption(kCQBC, perspective)) {
+      SetSendAlgorithm(kCubicBytes);
+    }
+  }
 
   // Initial window.
   if (config.HasClientRequestedIndependentOption(kIW03, perspective)) {
diff --git a/quiche/quic/core/quic_sent_packet_manager_test.cc b/quiche/quic/core/quic_sent_packet_manager_test.cc
index cbe8861..4576014 100644
--- a/quiche/quic/core/quic_sent_packet_manager_test.cc
+++ b/quiche/quic/core/quic_sent_packet_manager_test.cc
@@ -1266,6 +1266,15 @@
   // The server does nothing on kPRGC.
   EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
                             ->GetCongestionControlType());
+
+  options.clear();
+  options.push_back(kCQBC);
+  QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  // The server does nothing on kCQBC.
+  EXPECT_EQ(kRenoBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                            ->GetCongestionControlType());
 }
 
 TEST_F(QuicSentPacketManagerTest, NegotiateClientCongestionControlFromOptions) {
@@ -1334,15 +1343,33 @@
   EXPECT_EQ(kPragueCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
                               ->GetCongestionControlType());
 
-  // Test that kPRGC is overriden by other options.
+  options.clear();
+  options.push_back(kCQBC);
+  config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(kCubicBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                             ->GetCongestionControlType());
+
+  // Test that kPRGC is not 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());
+  EXPECT_EQ(kPragueCubic, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                              ->GetCongestionControlType());
+
+  // Test that kCQBC is not overriden by other options.
+  options.clear();
+  options.push_back(kCQBC);
+  options.push_back(kTBBR);
+  config.SetClientConnectionOptions(options);
+  EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+  manager_.SetFromConfig(config);
+  EXPECT_EQ(kCubicBytes, QuicSentPacketManagerPeer::GetSendAlgorithm(manager_)
+                             ->GetCongestionControlType());
 }
 
 TEST_F(QuicSentPacketManagerTest, UseInitialRoundTripTimeToSend) {