Add connection option kRVCM to enable reverse path validation upon new client address on server side.
Replace gfe2_reloadable_flag_quic_server_reverse_validate_new_path2 with gfe2_reloadable_flag_quic_server_reverse_validate_new_path3.
IETF QUIC server will validate new client address if kRVCM is present AND all path validation flags are true.
Protected by FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3.
PiperOrigin-RevId: 365133871
Change-Id: I86f40688c2e34995a5738b3f174f5f3014f54337
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 99f5372..e08d90b 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -267,6 +267,9 @@
const QuicTag kELDT = TAG('E', 'L', 'D', 'T'); // Enable Loss Detection Tuning
+const QuicTag kRVCM = TAG('R', 'V', 'C', 'M'); // Validate the new address
+ // upon client address change.
+
// 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/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 585aab7..48ed82d 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -376,6 +376,7 @@
copt.push_back(kILD0);
}
copt.push_back(kPLE1);
+ copt.push_back(kRVCM);
client_config_.SetConnectionOptionsToSend(copt);
// Start the server first, because CreateQuicClient() attempts
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 8510737..c53ceea 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -371,11 +371,7 @@
GetQuicReloadableFlag(quic_use_encryption_level_context)),
path_validator_(alarm_factory_, &arena_, this, random_generator_),
alternative_path_(QuicSocketAddress(), QuicSocketAddress()),
- most_recent_frame_type_(NUM_FRAME_TYPES),
- validate_client_addresses_(
- framer_.version().HasIetfQuicFrames() && use_path_validator_ &&
- count_bytes_on_alternative_path_separately_ &&
- GetQuicReloadableFlag(quic_server_reverse_validate_new_path2)) {
+ most_recent_frame_type_(NUM_FRAME_TYPES) {
QUIC_BUG_IF(quic_bug_12714_1,
!start_peer_migration_earlier_ && send_path_response_);
@@ -701,6 +697,13 @@
if (config.HasClientSentConnectionOption(kDFER, perspective_)) {
defer_send_in_response_to_packets_ = false;
}
+ if (framer_.version().HasIetfQuicFrames() && use_path_validator_ &&
+ count_bytes_on_alternative_path_separately_ &&
+ GetQuicReloadableFlag(quic_server_reverse_validate_new_path3) &&
+ config.HasClientSentConnectionOption(kRVCM, perspective_)) {
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 6, 6);
+ validate_client_addresses_ = true;
+ }
if (config.HasReceivedMaxPacketSize()) {
peer_max_packet_size_ = config.ReceivedMaxPacketSize();
MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
@@ -1674,7 +1677,7 @@
if (!validate_client_addresses_) {
return OnPathChallengeFrameInternal(frame);
}
- QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path2, 1, 5);
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 1, 6);
{
// UpdatePacketStateAndReplyPathChallenge() may start reverse path
// validation, if so bundle the PATH_CHALLENGE together with the
@@ -4968,7 +4971,7 @@
if (!validate_client_addresses_) {
return;
}
- QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path2, 2, 5);
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 2, 6);
if (debug_visitor_ != nullptr) {
const QuicTime now = clock_->ApproximateNow();
if (now >= stats_.handshake_completion_time) {
@@ -4998,11 +5001,12 @@
<< "EffectivePeerMigration started without address change.";
return;
}
- QUIC_DLOG(INFO) << ENDPOINT << "Effective peer's ip:port changed from "
- << default_path_.peer_address.ToString() << " to "
- << GetEffectivePeerAddressFromCurrentPacket().ToString()
- << ", address change type is " << type
- << ", migrating connection.";
+ QUIC_DLOG(INFO)
+ << ENDPOINT << "Effective peer's ip:port changed from "
+ << default_path_.peer_address.ToString() << " to "
+ << GetEffectivePeerAddressFromCurrentPacket().ToString()
+ << ", address change type is " << type
+ << ", migrating connection without validating new client address.";
highest_packet_sent_before_effective_peer_migration_ =
sent_packet_manager_.GetLargestSentPacket();
@@ -5013,7 +5017,7 @@
return;
}
- QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path2, 3, 5);
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 3, 6);
if (type == NO_CHANGE) {
UpdatePeerAddress(last_packet_source_address_);
QUIC_BUG(quic_bug_10511_36)
@@ -5293,7 +5297,7 @@
alternative_path_ = PathState(last_packet_destination_address_,
current_effective_peer_address);
} else if (!default_path_.validated) {
- QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path2, 4, 5);
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 4, 6);
// Skip reverse path validation because either handshake hasn't
// completed or the connection is validating the default path. Using
// PATH_CHALLENGE to validate alternative client address before
@@ -5307,7 +5311,7 @@
IsHandshakeConfirmed() && !alternative_path_.validated)
<< "No validated peer address to send after handshake comfirmed.";
} else if (!IsReceivedPeerAddressValidated()) {
- QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path2, 5, 5);
+ QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 5, 6);
// Only override alternative path state upon receiving a PATH_CHALLENGE
// from an unvalidated peer address, and the connection isn't validating
// a recent peer migration.
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index a6dc7f5..2c70c04 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -2157,7 +2157,7 @@
GetQuicReloadableFlag(quic_count_bytes_on_alternative_path_seperately);
// If true, upon seeing a new client address, validate the client address.
- const bool validate_client_addresses_;
+ bool validate_client_addresses_ = false;
bool support_multiple_connection_ids_ = false;
};
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 6b34ece..efeb53b 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1322,6 +1322,13 @@
void set_perspective(Perspective perspective) {
connection_.set_perspective(perspective);
if (perspective == Perspective::IS_SERVER) {
+ QuicConfig config;
+ QuicTagVector connection_options;
+ connection_options.push_back(kRVCM);
+ config.SetInitialReceivedConnectionOptions(connection_options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+
connection_.set_can_truncate_connection_ids(true);
QuicConnectionPeer::SetNegotiatedVersion(&connection_);
connection_.OnSuccessfulVersionNegotiation();
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 1ba0aa9..44e3e56 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -56,7 +56,7 @@
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response2, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_tls_crypto_error_code, true)
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path2, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_single_ack_in_packet2, false)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_start_peer_migration_earlier, true)
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_stateless_reset_faster_random, true)