Plumb active_connection_id_limit to QuicConfig
We currently do not use active_connection_id_limit anywhere because we do not yet support IETF QUIC connection migration. This CL plumbs that value to QuicConfig to allow us to remember it for 0-RTT and validate that values are not lowered by the server.
This CL also changes the default and minimum values for active_connection_id_limit from 0 to 2, due to recent changes to the spec. This does not change our behavior because we currently never send this transport parameter, nor act in any way on the value received. (This is because we do not send a transport parameter when it is configured to a value that is equal to the default.)
Plumb unused active_connection_id_limit, no behavior change
PiperOrigin-RevId: 310382355
Change-Id: Ifdda3ec3473f1472256788c87ca172fe037a12cb
diff --git a/quic/core/crypto/transport_parameters.cc b/quic/core/crypto/transport_parameters.cc
index 75f55ca..4e761b3 100644
--- a/quic/core/crypto/transport_parameters.cc
+++ b/quic/core/crypto/transport_parameters.cc
@@ -59,12 +59,14 @@
// The following constants define minimum and maximum allowed values for some of
// the parameters. These come from the "Transport Parameter Definitions"
// section of draft-ietf-quic-transport.
-const uint64_t kMinMaxPacketSizeTransportParam = 1200;
-const uint64_t kMaxAckDelayExponentTransportParam = 20;
-const uint64_t kDefaultAckDelayExponentTransportParam = 3;
-const uint64_t kMaxMaxAckDelayTransportParam = 16383;
-const uint64_t kDefaultMaxAckDelayTransportParam = 25;
-const size_t kStatelessResetTokenLength = 16;
+constexpr uint64_t kMinMaxPacketSizeTransportParam = 1200;
+constexpr uint64_t kMaxAckDelayExponentTransportParam = 20;
+constexpr uint64_t kDefaultAckDelayExponentTransportParam = 3;
+constexpr uint64_t kMaxMaxAckDelayTransportParam = 16383;
+constexpr uint64_t kDefaultMaxAckDelayTransportParam = 25;
+constexpr size_t kStatelessResetTokenLength = 16;
+constexpr uint64_t kMinActiveConnectionIdLimitTransportParam = 2;
+constexpr uint64_t kDefaultActiveConnectionIdLimitTransportParam = 2;
std::string TransportParameterIdToString(
TransportParameters::TransportParameterId param_id) {
@@ -449,7 +451,10 @@
0,
kMaxMaxAckDelayTransportParam),
disable_migration(false),
- active_connection_id_limit(kActiveConnectionIdLimit),
+ active_connection_id_limit(kActiveConnectionIdLimit,
+ kDefaultActiveConnectionIdLimitTransportParam,
+ kMinActiveConnectionIdLimitTransportParam,
+ kVarInt62MaxValue),
max_datagram_frame_size(kMaxDatagramFrameSize)
// Important note: any new transport parameters must be added
// to TransportParameters::AreValid, SerializeTransportParameters and
diff --git a/quic/core/crypto/transport_parameters.h b/quic/core/crypto/transport_parameters.h
index d4dd82f..9f9e616 100644
--- a/quic/core/crypto/transport_parameters.h
+++ b/quic/core/crypto/transport_parameters.h
@@ -181,7 +181,7 @@
IntegerParameter active_connection_id_limit;
// Indicates support for the DATAGRAM frame and the maximum frame size that
- // the sender accepts. See draft-pauly-quic-datagram.
+ // the sender accepts. See draft-ietf-quic-datagram.
IntegerParameter max_datagram_frame_size;
// Transport parameters used by Google QUIC but not IETF QUIC. This is
diff --git a/quic/core/crypto/transport_parameters_test.cc b/quic/core/crypto/transport_parameters_test.cc
index 72654a7..c3d5d57 100644
--- a/quic/core/crypto/transport_parameters_test.cc
+++ b/quic/core/crypto/transport_parameters_test.cc
@@ -388,6 +388,29 @@
"Invalid transport parameters [Client ack_delay_exponent 21 "
"(Invalid)]");
}
+ {
+ TransportParameters params;
+ std::string error_details;
+ params.perspective = Perspective::IS_CLIENT;
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
+ params.active_connection_id_limit.set_value(2);
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
+ params.active_connection_id_limit.set_value(999999);
+ EXPECT_TRUE(params.AreValid(&error_details));
+ EXPECT_TRUE(error_details.empty());
+ params.active_connection_id_limit.set_value(1);
+ EXPECT_FALSE(params.AreValid(&error_details));
+ EXPECT_EQ(error_details,
+ "Invalid transport parameters [Client active_connection_id_limit"
+ " 1 (Invalid)]");
+ params.active_connection_id_limit.set_value(0);
+ EXPECT_FALSE(params.AreValid(&error_details));
+ EXPECT_EQ(error_details,
+ "Invalid transport parameters [Client active_connection_id_limit"
+ " 0 (Invalid)]");
+ }
}
TEST_P(TransportParametersTest, NoClientParamsWithStatelessResetToken) {
diff --git a/quic/core/quic_config.cc b/quic/core/quic_config.cc
index 0eaf9d6..d0f42b7 100644
--- a/quic/core/quic_config.cc
+++ b/quic/core/quic_config.cc
@@ -453,7 +453,8 @@
max_ack_delay_ms_(kMAD, PRESENCE_OPTIONAL),
ack_delay_exponent_(kADE, PRESENCE_OPTIONAL),
max_packet_size_(0, PRESENCE_OPTIONAL),
- max_datagram_frame_size_(0, PRESENCE_OPTIONAL) {
+ max_datagram_frame_size_(0, PRESENCE_OPTIONAL),
+ active_connection_id_limit_(0, PRESENCE_OPTIONAL) {
SetDefaults();
}
@@ -652,6 +653,23 @@
return max_datagram_frame_size_.GetReceivedValue();
}
+void QuicConfig::SetActiveConnectionIdLimitToSend(
+ uint64_t active_connection_id_limit) {
+ active_connection_id_limit_.SetSendValue(active_connection_id_limit);
+}
+
+uint64_t QuicConfig::GetActiveConnectionIdLimitToSend() const {
+ return active_connection_id_limit_.GetSendValue();
+}
+
+bool QuicConfig::HasReceivedActiveConnectionIdLimit() const {
+ return active_connection_id_limit_.HasReceivedValue();
+}
+
+uint64_t QuicConfig::ReceivedActiveConnectionIdLimit() const {
+ return active_connection_id_limit_.GetReceivedValue();
+}
+
bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
return bytes_for_connection_id_.HasSendValue();
}
@@ -1115,6 +1133,11 @@
preferred_address);
}
+ if (active_connection_id_limit_.HasSendValue()) {
+ params->active_connection_id_limit.set_value(
+ active_connection_id_limit_.GetSendValue());
+ }
+
if (!params->google_quic_params) {
params->google_quic_params = std::make_unique<CryptoHandshakeMessage>();
}
@@ -1217,6 +1240,9 @@
connection_migration_disabled_.SetReceivedValue(1u);
}
+ active_connection_id_limit_.SetReceivedValue(
+ params.active_connection_id_limit.value());
+
const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
if (peer_params != nullptr) {
QuicErrorCode error = initial_round_trip_time_us_.ProcessPeerHello(
diff --git a/quic/core/quic_config.h b/quic/core/quic_config.h
index f2ca652..893e3e7 100644
--- a/quic/core/quic_config.h
+++ b/quic/core/quic_config.h
@@ -432,6 +432,12 @@
bool HasReceivedMaxDatagramFrameSize() const;
uint64_t ReceivedMaxDatagramFrameSize() const;
+ // IETF QUIC active_connection_id_limit transport parameter.
+ void SetActiveConnectionIdLimitToSend(uint64_t active_connection_id_limit);
+ uint64_t GetActiveConnectionIdLimitToSend() const;
+ bool HasReceivedActiveConnectionIdLimit() const;
+ uint64_t ReceivedActiveConnectionIdLimit() const;
+
bool negotiated() const;
void SetCreateSessionTagIndicators(QuicTagVector tags);
@@ -584,6 +590,10 @@
// Uses the max_datagram_frame_size transport parameter in IETF QUIC.
QuicFixedUint62 max_datagram_frame_size_;
+ // Maximum number of connection IDs from the peer.
+ // Uses the active_connection_id_limit transport parameter in IETF QUIC.
+ QuicFixedUint62 active_connection_id_limit_;
+
// Sent by the server when it has previously sent a RETRY packet.
// Uses the original_connection_id transport parameter in IETF QUIC.
quiche::QuicheOptional<QuicConnectionId> original_connection_id_to_send_;
diff --git a/quic/core/quic_config_test.cc b/quic/core/quic_config_test.cc
index dbdd0f8..4aa10ef 100644
--- a/quic/core/quic_config_test.cc
+++ b/quic/core/quic_config_test.cc
@@ -22,13 +22,14 @@
namespace test {
namespace {
-const uint32_t kMaxPacketSizeForTest = 1234;
-const uint32_t kMaxDatagramFrameSizeForTest = 1333;
-const uint8_t kFakeStatelessResetTokenData[16] = {
+constexpr uint32_t kMaxPacketSizeForTest = 1234;
+constexpr uint32_t kMaxDatagramFrameSizeForTest = 1333;
+constexpr uint8_t kFakeStatelessResetTokenData[16] = {
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F};
-const uint64_t kFakeAckDelayExponent = 10;
-const uint64_t kFakeMaxAckDelay = 51;
+constexpr uint64_t kFakeAckDelayExponent = 10;
+constexpr uint64_t kFakeMaxAckDelay = 51;
+constexpr uint64_t kFakeActiveConnectionIdLimit = 52;
// TODO(b/153726130): Consider merging this with methods in
// transport_parameters_test.cc.
@@ -465,6 +466,7 @@
4 * kMinimumFlowControlSendWindow);
config_.SetMaxPacketSizeToSend(kMaxPacketSizeForTest);
config_.SetMaxDatagramFrameSizeToSend(kMaxDatagramFrameSizeForTest);
+ config_.SetActiveConnectionIdLimitToSend(kFakeActiveConnectionIdLimit);
TransportParameters params;
config_.FillTransportParameters(¶ms);
@@ -482,6 +484,8 @@
EXPECT_EQ(kMaxPacketSizeForTest, params.max_packet_size.value());
EXPECT_EQ(kMaxDatagramFrameSizeForTest,
params.max_datagram_frame_size.value());
+ EXPECT_EQ(kFakeActiveConnectionIdLimit,
+ params.active_connection_id_limit.value());
}
TEST_P(QuicConfigTest, ProcessTransportParametersServer) {
@@ -504,6 +508,7 @@
params.stateless_reset_token = CreateFakeStatelessResetToken();
params.max_ack_delay.set_value(kFakeMaxAckDelay);
params.ack_delay_exponent.set_value(kFakeAckDelayExponent);
+ params.active_connection_id_limit.set_value(kFakeActiveConnectionIdLimit);
std::string error_details;
EXPECT_THAT(config_.ProcessTransportParameters(
@@ -600,6 +605,10 @@
ASSERT_TRUE(config_.HasReceivedAckDelayExponent());
EXPECT_EQ(config_.ReceivedAckDelayExponent(), kFakeAckDelayExponent);
+
+ ASSERT_TRUE(config_.HasReceivedActiveConnectionIdLimit());
+ EXPECT_EQ(config_.ReceivedActiveConnectionIdLimit(),
+ kFakeActiveConnectionIdLimit);
}
TEST_P(QuicConfigTest, DisableMigrationTransportParameter) {