Flush frames in QUIC packet creator when destination connection ID length changes. And do not flush if ID changes but ID length is unchanged.

Protected by FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2.

PiperOrigin-RevId: 373812559
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index f0795cd..027f587 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -722,7 +722,7 @@
       use_connection_id_on_default_path_ &&
       group_path_response_and_challenge_sending_closer_ &&
       GetQuicReloadableFlag(quic_drop_unsent_path_response) &&
-      GetQuicReloadableFlag(quic_connection_migration_use_new_cid);
+      GetQuicReloadableFlag(quic_connection_migration_use_new_cid_v2);
   if (config.HasReceivedMaxPacketSize()) {
     peer_max_packet_size_ = config.ReceivedMaxPacketSize();
     MaybeUpdatePacketCreatorMaxPacketLengthAndPadding();
@@ -2017,7 +2017,7 @@
 }
 
 void QuicConnection::OnClientConnectionIdAvailable() {
-  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid, 3, 5);
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 3, 5);
   QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
   if (!peer_issued_cid_manager_->HasUnusedConnectionId()) {
     return;
@@ -6732,18 +6732,12 @@
   QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
   if (IsAlternativePath(self_address, peer_address)) {
     // Client migration is after path validation.
-    if (peer_issued_cid_manager_ != nullptr) {
-      QUICHE_DCHECK(!default_path_.server_connection_id.IsEmpty());
-      packet_creator_.FlushCurrentPacket();
-    }
     default_path_.client_connection_id = alternative_path_.client_connection_id;
     default_path_.server_connection_id = alternative_path_.server_connection_id;
     default_path_.stateless_reset_token =
         alternative_path_.stateless_reset_token;
     default_path_.stateless_reset_token_received =
         alternative_path_.stateless_reset_token_received;
-    packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
-    packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
     return true;
   }
   // Client migration is without path validation.
@@ -6771,13 +6765,11 @@
     default_path_.stateless_reset_token =
         connection_id_data->stateless_reset_token;
   }
-  packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
-  packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
   return true;
 }
 
 void QuicConnection::RetirePeerIssuedConnectionIdsNoLongerOnPath() {
-  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid, 4, 5);
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 4, 5);
   if (!connection_migration_use_new_cid_ ||
       peer_issued_cid_manager_ == nullptr) {
     return;
@@ -6800,10 +6792,18 @@
   if (!connected_) {
     return false;
   }
+  QUICHE_DCHECK(!version().UsesHttp3() || IsHandshakeConfirmed());
 
-  if (connection_migration_use_new_cid_ &&
-      !UpdateConnectionIdsOnClientMigration(self_address, peer_address)) {
-    return false;
+  if (connection_migration_use_new_cid_) {
+    if (!UpdateConnectionIdsOnClientMigration(self_address, peer_address)) {
+      return false;
+    }
+    if (packet_creator_.GetServerConnectionId().length() !=
+        default_path_.server_connection_id.length()) {
+      packet_creator_.FlushCurrentPacket();
+    }
+    packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
+    packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
   }
 
   const auto self_address_change_type = QuicUtils::DetermineAddressChangeType(
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 33ab3b3..bf61b34 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -13575,6 +13575,9 @@
 }
 
 TEST_P(QuicConnectionTest, MigratePath) {
+  EXPECT_CALL(visitor_, GetHandshakeState())
+      .Times(testing::AtMost(1))
+      .WillOnce(Return(HANDSHAKE_CONFIRMED));
   EXPECT_CALL(visitor_, OnPathDegrading());
   connection_.OnPathDegradingDetected();
   const QuicSocketAddress kNewSelfAddress(QuicIpAddress::Any4(), 12345);
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index d17c8bd..810cb88 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -1015,7 +1015,7 @@
         << server_connection_id << " new_connection_id: " << new_connection_id;
     return;
   }
-  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid, 5, 5);
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 5, 5);
   auto insertion_result = reference_counted_session_map_.insert(
       std::make_pair(new_connection_id, it->second));
   QUICHE_DCHECK(insertion_result.second);
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 1ccad10..899c868 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -114,7 +114,7 @@
 // If true, use WriteOrBufferDataAtLevel to send crypto data. Existing WriteOrBufferData is used to send application data.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_write_or_buffer_data_at_level, false)
 // If true, use new connection ID in connection migration.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, false)
 // If true, use the connection ID and stateless reset token on default PathState.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_connection_id_on_default_path_v2, false)
 // If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index 6674ef4..cbca89d 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -2124,10 +2124,12 @@
          "initialized.";
   creator_->SetDefaultPeerAddress(address);
   if (update_connection_id_) {
-    // Flush current packet if connection ID changes.
+    // Flush current packet if connection ID length changes.
     if (address == old_peer_address_ &&
-        ((client_connection_id != old_client_connection_id_) ||
-         (server_connection_id != old_server_connection_id_))) {
+        ((client_connection_id.length() !=
+          old_client_connection_id_.length()) ||
+         (server_connection_id.length() !=
+          old_server_connection_id_.length()))) {
       creator_->FlushCurrentPacket();
     }
     creator_->SetClientConnectionId(client_connection_id);
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 1d4f697..9d4a5d1 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -2092,14 +2092,14 @@
 }
 
 void QuicSession::SendNewConnectionId(const QuicNewConnectionIdFrame& frame) {
-  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid, 1, 5);
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 1, 5);
   control_frame_manager_.WriteOrBufferNewConnectionId(
       frame.connection_id, frame.sequence_number, frame.retire_prior_to,
       frame.stateless_reset_token);
 }
 
 void QuicSession::SendRetireConnectionId(uint64_t sequence_number) {
-  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid, 2, 5);
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 2, 5);
   control_frame_manager_.WriteOrBufferRetireConnectionId(sequence_number);
 }