Add a QUIC protocol flag to not require the the kSPAD connection option
in order to use QUIC server preferred address support.
quic_always_support_server_preferred_address defaults to false to match
existing behavior but may be set to true. This will make it easier for
QUICHE servers to support non-QUICHE clients using server preferred address.
For context: https://github.com/envoyproxy/envoy/pull/32130
PiperOrigin-RevId: 603488744
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc
index 6024569..3eaddf2 100644
--- a/quiche/quic/core/http/end_to_end_test.cc
+++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -467,7 +467,9 @@
server_writer_ = new PacketDroppingTestWriter();
StartServer();
- client_config_.SetConnectionOptionsToSend(QuicTagVector{kSPAD});
+ if (!GetQuicFlag(quic_always_support_server_preferred_address)) {
+ client_config_.SetConnectionOptionsToSend(QuicTagVector{kSPAD});
+ }
}
if (!connect_to_server_on_initialize_) {
@@ -5467,6 +5469,35 @@
EXPECT_FALSE(client_stats.failed_to_validate_server_preferred_address);
}
+TEST_P(EndToEndTest, SimpleServerPreferredAddressTestNoSPAD) {
+ SetQuicFlag(quic_always_support_server_preferred_address, true);
+ use_preferred_address_ = true;
+ ASSERT_TRUE(Initialize());
+ if (!version_.HasIetfQuicFrames()) {
+ return;
+ }
+ client_.reset(CreateQuicClient(nullptr));
+ QuicConnection* client_connection = GetClientConnection();
+ EXPECT_TRUE(client_->client()->WaitForHandshakeConfirmed());
+ EXPECT_EQ(server_address_, client_connection->effective_peer_address());
+ EXPECT_EQ(server_address_, client_connection->peer_address());
+ EXPECT_TRUE(client_->client()->HasPendingPathValidation());
+ QuicConnectionId server_cid1 = client_connection->connection_id();
+
+ SendSynchronousFooRequestAndCheckResponse();
+ while (client_->client()->HasPendingPathValidation()) {
+ client_->client()->WaitForEvents();
+ }
+ EXPECT_EQ(server_preferred_address_,
+ client_connection->effective_peer_address());
+ EXPECT_EQ(server_preferred_address_, client_connection->peer_address());
+ EXPECT_NE(server_cid1, client_connection->connection_id());
+
+ const auto client_stats = GetClientConnection()->GetStats();
+ EXPECT_TRUE(client_stats.server_preferred_address_validated);
+ EXPECT_FALSE(client_stats.failed_to_validate_server_preferred_address);
+}
+
TEST_P(EndToEndTest, OptimizedServerPreferredAddress) {
use_preferred_address_ = true;
ASSERT_TRUE(Initialize());
diff --git a/quiche/quic/core/quic_config.cc b/quiche/quic/core/quic_config.cc
index 75d29f3..2516c8c 100644
--- a/quiche/quic/core/quic_config.cc
+++ b/quiche/quic/core/quic_config.cc
@@ -1428,4 +1428,9 @@
}
}
+bool QuicConfig::SupportsServerPreferredAddress(Perspective perspective) const {
+ return HasClientSentConnectionOption(kSPAD, perspective) ||
+ GetQuicFlag(quic_always_support_server_preferred_address);
+}
+
} // namespace quic
diff --git a/quiche/quic/core/quic_config.h b/quiche/quic/core/quic_config.h
index bf1cc6c..c635689 100644
--- a/quiche/quic/core/quic_config.h
+++ b/quiche/quic/core/quic_config.h
@@ -418,6 +418,11 @@
void ClearAlternateServerAddressToSend(
quiche::IpAddressFamily address_family);
+ // Returns true if this config supports server preferred address,
+ // either via the kSPAD connection option or the QUIC protocol flag
+ // quic_always_support_server_preferred_address.
+ bool SupportsServerPreferredAddress(Perspective perspective) const;
+
// Original destination connection ID.
void SetOriginalConnectionIdToSend(
const QuicConnectionId& original_destination_connection_id);
diff --git a/quiche/quic/core/quic_config_test.cc b/quiche/quic/core/quic_config_test.cc
index 86e5a99..625f645 100644
--- a/quiche/quic/core/quic_config_test.cc
+++ b/quiche/quic/core/quic_config_test.cc
@@ -568,6 +568,26 @@
kTestServerAddressV6);
}
+TEST_P(QuicConfigTest, SupportsServerPreferredAddress) {
+ SetQuicFlag(quic_always_support_server_preferred_address, true);
+ EXPECT_TRUE(config_.SupportsServerPreferredAddress(Perspective::IS_CLIENT));
+ EXPECT_TRUE(config_.SupportsServerPreferredAddress(Perspective::IS_SERVER));
+
+ SetQuicFlag(quic_always_support_server_preferred_address, false);
+ EXPECT_FALSE(config_.SupportsServerPreferredAddress(Perspective::IS_CLIENT));
+ EXPECT_FALSE(config_.SupportsServerPreferredAddress(Perspective::IS_SERVER));
+
+ QuicTagVector copt;
+ copt.push_back(kSPAD);
+ config_.SetConnectionOptionsToSend(copt);
+ EXPECT_TRUE(config_.SupportsServerPreferredAddress(Perspective::IS_CLIENT));
+ EXPECT_FALSE(config_.SupportsServerPreferredAddress(Perspective::IS_SERVER));
+
+ config_.SetInitialReceivedConnectionOptions(copt);
+ EXPECT_TRUE(config_.SupportsServerPreferredAddress(Perspective::IS_CLIENT));
+ EXPECT_TRUE(config_.SupportsServerPreferredAddress(Perspective::IS_SERVER));
+}
+
TEST_P(QuicConfigTest, ProcessTransportParametersServer) {
if (!version_.UsesTls()) {
// TransportParameters are only used for QUIC+TLS.
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 3a3b356..88f52d8 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -648,7 +648,7 @@
if (version().HasIetfQuicFrames() &&
config.HasReceivedPreferredAddressConnectionIdAndToken() &&
- config.HasClientSentConnectionOption(kSPAD, perspective_)) {
+ config.SupportsServerPreferredAddress(perspective_)) {
if (self_address().host().IsIPv4() &&
config.HasReceivedIPv4AlternateServerAddress()) {
received_server_preferred_address_ =
diff --git a/quiche/quic/core/quic_protocol_flags_list.h b/quiche/quic/core/quic_protocol_flags_list.h
index bd337e9..417c1a6 100644
--- a/quiche/quic/core/quic_protocol_flags_list.h
+++ b/quiche/quic/core/quic_protocol_flags_list.h
@@ -231,4 +231,8 @@
bool, quic_enable_chaos_protection, true,
"If true, use chaos protection to randomize client initials.")
+QUIC_PROTOCOL_FLAG(bool, quic_always_support_server_preferred_address, false,
+ "If false, the kSPAD connection option is required to use "
+ "QUIC server preferred address support.")
+
#endif
diff --git a/quiche/quic/core/quic_session.cc b/quiche/quic/core/quic_session.cc
index 6e655c5..359841a 100644
--- a/quiche/quic/core/quic_session.cc
+++ b/quiche/quic/core/quic_session.cc
@@ -1384,7 +1384,7 @@
if (perspective_ == Perspective::IS_SERVER && version().HasIetfQuicFrames() &&
connection_->effective_peer_address().IsInitialized()) {
- if (config_.HasClientSentConnectionOption(kSPAD, perspective_)) {
+ if (config_.SupportsServerPreferredAddress(perspective_)) {
quiche::IpAddressFamily address_family =
connection_->effective_peer_address()
.Normalized()