Proactively retires client-issued connection ID (if any) when reverse path validation fails.

This is a minor bug fix as client "typically" does not issue non-empty connection ID.

Protected by FLAGS_quic_reloadable_flag_quic_retire_cid_on_reverse_path_validation_failure.

PiperOrigin-RevId: 424360758
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 1244a44..12372ed 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -5532,13 +5532,14 @@
   EXPECT_EQ(0u, client_connection->GetStats().num_new_connection_id_sent);
 }
 
-// TODO(haoyuewang) Re-enable this test in cr/418502410.
 TEST_P(EndToEndPacketReorderingTest,
-       DISABLED_MigrateAgainAfterPathValidationFailureWithNonZeroClientCid) {
+       MigrateAgainAfterPathValidationFailureWithNonZeroClientCid) {
   if (!version_.SupportsClientConnectionIds()) {
     ASSERT_TRUE(Initialize());
     return;
   }
+  SetQuicReloadableFlag(quic_retire_cid_on_reverse_path_validation_failure,
+                        true);
   override_client_connection_id_length_ = kQuicDefaultConnectionIdLength;
   ASSERT_TRUE(Initialize());
   if (!GetClientConnection()->connection_migration_use_new_cid()) {
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index e31408a..1c1a4ea 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -6765,6 +6765,21 @@
   }
 }
 
+void QuicConnection::RetirePeerIssuedConnectionIdsOnPathValidationFailure() {
+  // The alarm to retire connection IDs no longer on paths is scheduled at the
+  // end of writing and reading packet. On path validation failure, there could
+  // be no packet to write or read. Hence the retirement alarm for the
+  // connection ID associated with the failed path needs to be proactively
+  // scheduled here.
+  if (GetQuicReloadableFlag(
+          quic_retire_cid_on_reverse_path_validation_failure) ||
+      perspective_ == Perspective::IS_CLIENT) {
+    QUIC_RELOADABLE_FLAG_COUNT(
+        quic_retire_cid_on_reverse_path_validation_failure);
+    RetirePeerIssuedConnectionIdsNoLongerOnPath();
+  }
+}
+
 bool QuicConnection::MigratePath(const QuicSocketAddress& self_address,
                                  const QuicSocketAddress& peer_address,
                                  QuicPacketWriter* writer,
@@ -6816,12 +6831,7 @@
     QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
     alternative_path_.Clear();
   }
-  // The alarm to retire connection IDs no longer on paths is scheduled at the
-  // end of writing and reading packet. On path validation failure, there could
-  // be no packet to write or read. Hence the retirement alarm for the
-  // connection ID associated with the failed path needs to be proactively
-  // scheduled here.
-  RetirePeerIssuedConnectionIdsNoLongerOnPath();
+  RetirePeerIssuedConnectionIdsOnPathValidationFailure();
 }
 
 QuicConnectionId QuicConnection::GetOneActiveServerConnectionId() const {
@@ -7075,6 +7085,7 @@
     QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 6, 6);
     connection_->alternative_path_.Clear();
   }
+  connection_->RetirePeerIssuedConnectionIdsOnPathValidationFailure();
 }
 
 QuicConnection::ScopedRetransmissionTimeoutIndicator::
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 3b310c8..a545527 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -1564,6 +1564,10 @@
   // any path.
   void RetirePeerIssuedConnectionIdsNoLongerOnPath();
 
+  // When path validation fails, proactively retire peer issued connection IDs
+  // no longer used on any path.
+  void RetirePeerIssuedConnectionIdsOnPathValidationFailure();
+
   // Writes the given packet to socket, encrypted with packet's
   // encryption_level. Returns true on successful write, and false if the writer
   // was blocked and the write needs to be tried again. Notifies the
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index ddbe47b..7482050 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -99,6 +99,8 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reset_per_packet_state_for_undecryptable_packets, true)
 // If true, send PATH_RESPONSE upon receiving PATH_CHALLENGE regardless of perspective. --gfe2_reloadable_flag_quic_start_peer_migration_earlier has to be true before turn on this flag.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response2, true)
+// If true, server proactively retires client issued connection ID on reverse path validation failure. 
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_retire_cid_on_reverse_path_validation_failure, false)
 // If true, set burst token to 2 in cwnd bootstrapping experiment.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false)
 // If true, stop resetting ideal_next_packet_send_time_ in pacing sender.