Update ACK timeout for NEW_CONNECTION_ID and RETIRE_CONNECTION_ID frames.

For chromium merge duty on-call: please add "FLAGS_quic_reloadable_flag_quic_ack_cid_frames = false;" to:
1) net/quic/quic_chromium_client_session_test.cc
2) net/quic/quic_stream_factory_test.cc
I'll update these tests soon.
Thanks.

Protected by FLAGS_quic_reloadable_flag_quic_ack_cid_frames.

PiperOrigin-RevId: 385197237
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index 22bbda0..04f4afe 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -2092,7 +2092,10 @@
     OnClientConnectionIdAvailable();
   }
   QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v4, 1, 2);
-  // TODO(haoyuewang): update ACK timeout for RETIRE_CONNECTION_ID_FRAME.
+  if (ack_cid_frames_) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(quic_ack_cid_frames, 1, 2);
+    MaybeUpdateAckTimeout();
+  }
   return true;
 }
 
@@ -2153,7 +2156,10 @@
   QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v4, 2, 2);
   // Count successfully received RETIRE_CONNECTION_ID frames.
   QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 5, 6);
-  // TODO(haoyuewang): update ACK timeout for RETIRE_CONNECTION_ID_FRAME.
+  if (ack_cid_frames_) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(quic_ack_cid_frames, 2, 2);
+    MaybeUpdateAckTimeout();
+  }
   return true;
 }
 
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 6e989ba..22fd83e 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -2286,6 +2286,8 @@
 
   const bool add_missing_update_ack_timeout_ =
       GetQuicReloadableFlag(quic_add_missing_update_ack_timeout);
+
+  const bool ack_cid_frames_ = GetQuicReloadableFlag(quic_ack_cid_frames);
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index d47108a..d7d5392 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -1178,7 +1178,12 @@
     }
     if (peer_framer_.version().HasIetfInvariantHeader() &&
         peer_framer_.perspective() == Perspective::IS_SERVER) {
-      header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+      if (!connection_.client_connection_id().IsEmpty()) {
+        header.destination_connection_id = connection_.client_connection_id();
+        header.destination_connection_id_included = CONNECTION_ID_PRESENT;
+      } else {
+        header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+      }
       if (header.version_flag) {
         header.source_connection_id = connection_id_;
         header.source_connection_id_included = CONNECTION_ID_PRESENT;
@@ -15209,11 +15214,17 @@
 }
 
 TEST_P(QuicConnectionTest, AckElicitingFrames) {
+  QuicConfig config;
+  config.SetConnectionOptionsToSend({kRVCM});
+  EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+  connection_.SetFromConfig(config);
   if (!version().HasIetfQuicFrames() ||
-      !connection_.support_multiple_connection_ids() ||
+      !connection_.connection_migration_use_new_cid() ||
+      !GetQuicReloadableFlag(quic_ack_cid_frames) ||
       !GetQuicReloadableFlag(quic_add_missing_update_ack_timeout)) {
     return;
   }
+  EXPECT_CALL(visitor_, SendNewConnectionId(_)).Times(2);
   EXPECT_CALL(visitor_, OnRstStream(_));
   EXPECT_CALL(visitor_, OnWindowUpdateFrame(_));
   EXPECT_CALL(visitor_, OnBlockedFrame(_));
@@ -15226,13 +15237,19 @@
   EXPECT_CALL(visitor_, OnMessageReceived(""));
   EXPECT_CALL(visitor_, OnNewTokenReceived(""));
 
+  SetClientConnectionId(TestConnectionId(12));
   connection_.CreateConnectionIdManager();
+  QuicConnectionPeer::GetSelfIssuedConnectionIdManager(&connection_)
+      ->MaybeSendNewConnectionIds();
   connection_.set_can_receive_ack_frequency_frame();
 
   QuicAckFrame ack_frame = InitAckFrame(1);
   QuicRstStreamFrame rst_stream_frame;
   QuicWindowUpdateFrame window_update_frame;
   QuicPathChallengeFrame path_challenge_frame;
+  QuicNewConnectionIdFrame new_connection_id_frame;
+  QuicRetireConnectionIdFrame retire_connection_id_frame;
+  retire_connection_id_frame.sequence_number = 1u;
   QuicStopSendingFrame stop_sending_frame;
   QuicPathResponseFrame path_response_frame;
   QuicMessageFrame message_frame;
@@ -15304,12 +15321,10 @@
         frame = QuicFrame(&stop_sending_frame);
         break;
       case NEW_CONNECTION_ID_FRAME:
-        // TODO(haoyuewang): add test coverage for RETIRE_CONNECTION_ID_FRAME.
-        skipped = true;
+        frame = QuicFrame(&new_connection_id_frame);
         break;
       case RETIRE_CONNECTION_ID_FRAME:
-        // TODO(haoyuewang): add test coverage for RETIRE_CONNECTION_ID_FRAME.
-        skipped = true;
+        frame = QuicFrame(&retire_connection_id_frame);
         break;
       case PATH_RESPONSE_FRAME:
         frame = QuicFrame(&path_response_frame);
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 90b14fb..e70ae9f 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -103,6 +103,8 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false)
 // If true, time_wait_list can support multiple connection IDs.
 QUIC_FLAG(FLAGS_quic_restart_flag_quic_time_wait_list_support_multiple_cid_v2, true)
+// If true, update ACK timeout for NEW_CONNECTION_ID and RETIRE_CONNECTION_ID frames.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ack_cid_frames, true)
 // If true, upon receiving path challenge, send path response and reverse path challenge in the same function.
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_group_path_response_and_challenge_sending_closer, true)
 // If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.
diff --git a/quic/test_tools/quic_connection_peer.cc b/quic/test_tools/quic_connection_peer.cc
index 05e270d..43c3450 100644
--- a/quic/test_tools/quic_connection_peer.cc
+++ b/quic/test_tools/quic_connection_peer.cc
@@ -521,5 +521,12 @@
   return connection->self_issued_cid_manager_->HasConnectionIdToConsume();
 }
 
+// static
+QuicSelfIssuedConnectionIdManager*
+QuicConnectionPeer::GetSelfIssuedConnectionIdManager(
+    QuicConnection* connection) {
+  return connection->self_issued_cid_manager_.get();
+}
+
 }  // namespace test
 }  // namespace quic
diff --git a/quic/test_tools/quic_connection_peer.h b/quic/test_tools/quic_connection_peer.h
index cbc829a..99b8b94 100644
--- a/quic/test_tools/quic_connection_peer.h
+++ b/quic/test_tools/quic_connection_peer.h
@@ -213,6 +213,9 @@
 
   static bool HasSelfIssuedConnectionIdToConsume(
       const QuicConnection* connection);
+
+  static QuicSelfIssuedConnectionIdManager* GetSelfIssuedConnectionIdManager(
+      QuicConnection* connection);
 };
 
 }  // namespace test