Update QuicConnection to Use ConnectionIdGeneratorInterface.

A derived class of ConnectionIdGeneratorInterface is owned by whatever owns the connection. For most servers, this will be QuicDispatcher, which in turn receives the Generator from whatever owns it.

For Envoy-based consumers of Quiche, generate a derived class of ConnectionIdGeneratorInterface and pass a reference to it into the Constructor for QuicConnection.

The MockQuicConnection and MockGfeQuicConnection classes contain their own MockConnectionIdGenerators instead of taking the interface as a constructor argument, in attempt to reduce the footprint of this CL by several dozen files. It also makes it so that MockQuicConnectionUsers don't have to worry about generators, which is good for most users.

Protected by FLAGS_quic_reloadable_flag_quic_connection_uses_abstract_connection_id_generator.

PiperOrigin-RevId: 471570565
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index ec509b7..999e174 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -253,7 +253,8 @@
     QuicSocketAddress initial_peer_address,
     QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory,
     QuicPacketWriter* writer, bool owns_writer, Perspective perspective,
-    const ParsedQuicVersionVector& supported_versions)
+    const ParsedQuicVersionVector& supported_versions,
+    ConnectionIdGeneratorInterface& generator)
     : framer_(supported_versions, helper->GetClock()->ApproximateNow(),
               perspective, server_connection_id.length()),
       current_packet_content_(NO_FRAMES_RECEIVED),
@@ -342,7 +343,8 @@
       path_validator_(alarm_factory_, &arena_, this, random_generator_, clock_,
                       &context_),
       ping_manager_(perspective, this, &arena_, alarm_factory_, &context_),
-      multi_port_probing_interval_(kDefaultMultiPortProbingInterval) {
+      multi_port_probing_interval_(kDefaultMultiPortProbingInterval),
+      connection_id_generator_(generator) {
   QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
                 default_path_.self_address.IsInitialized());
 
@@ -4014,7 +4016,7 @@
       perspective_ == Perspective::IS_CLIENT
           ? default_path_.client_connection_id
           : default_path_.server_connection_id,
-      clock_, alarm_factory_, this, context());
+      clock_, alarm_factory_, this, context(), connection_id_generator_);
 }
 
 void QuicConnection::MaybeSendConnectionIdToClient() {
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index 5c94c50..fd4c420 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -475,7 +475,8 @@
                  QuicConnectionHelperInterface* helper,
                  QuicAlarmFactory* alarm_factory, QuicPacketWriter* writer,
                  bool owns_writer, Perspective perspective,
-                 const ParsedQuicVersionVector& supported_versions);
+                 const ParsedQuicVersionVector& supported_versions,
+                 ConnectionIdGeneratorInterface& generator);
   QuicConnection(const QuicConnection&) = delete;
   QuicConnection& operator=(const QuicConnection&) = delete;
   ~QuicConnection() override;
@@ -1346,6 +1347,10 @@
     return defer_send_in_response_to_packets_;
   }
 
+  ConnectionIdGeneratorInterface& connection_id_generator() const {
+    return connection_id_generator_;
+  }
+
  private:
   friend class test::QuicConnectionPeer;
 
@@ -2290,6 +2295,8 @@
   // limit.
   const bool enforce_strict_amplification_factor_ =
       GetQuicFlag(FLAGS_quic_enforce_strict_amplification_factor);
+
+  ConnectionIdGeneratorInterface& connection_id_generator_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_connection_id_manager.cc b/quiche/quic/core/quic_connection_id_manager.cc
index 17f7a72..a3909f3 100644
--- a/quiche/quic/core/quic_connection_id_manager.cc
+++ b/quiche/quic/core/quic_connection_id_manager.cc
@@ -11,6 +11,7 @@
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_utils.h"
 #include "quiche/quic/platform/api/quic_flag_utils.h"
+#include "quiche/quic/platform/api/quic_flags.h"
 #include "quiche/common/platform/api/quiche_logging.h"
 
 namespace quic {
@@ -278,7 +279,7 @@
     const QuicConnectionId& initial_connection_id, const QuicClock* clock,
     QuicAlarmFactory* alarm_factory,
     QuicConnectionIdManagerVisitorInterface* visitor,
-    QuicConnectionContext* context)
+    QuicConnectionContext* context, ConnectionIdGeneratorInterface& generator)
     : active_connection_id_limit_(active_connection_id_limit),
       clock_(clock),
       visitor_(visitor),
@@ -286,7 +287,8 @@
           new RetireSelfIssuedConnectionIdAlarmDelegate(this, context))),
       last_connection_id_(initial_connection_id),
       next_connection_id_sequence_number_(1u),
-      last_connection_id_consumed_by_self_sequence_number_(0u) {
+      last_connection_id_consumed_by_self_sequence_number_(0u),
+      connection_id_generator_(generator) {
   active_connection_ids_.emplace_back(initial_connection_id, 0u);
 }
 
@@ -303,18 +305,33 @@
 QuicSelfIssuedConnectionIdManager::MaybeIssueNewConnectionId() {
   const bool check_cid_collision_when_issue_new_cid =
       GetQuicReloadableFlag(quic_check_cid_collision_when_issue_new_cid);
-  QuicConnectionId new_cid = GenerateNewConnectionId(last_connection_id_);
+  absl::optional<QuicConnectionId> new_cid;
+  if (GetQuicReloadableFlag(
+          quic_connection_uses_abstract_connection_id_generator)) {
+    QUIC_RELOADABLE_FLAG_COUNT(
+        quic_connection_uses_abstract_connection_id_generator);
+    new_cid =
+        connection_id_generator_.GenerateNextConnectionId(last_connection_id_);
+  } else {
+    new_cid = GenerateNewConnectionId(last_connection_id_);
+  }
+  if (!new_cid.has_value()) {
+    QUIC_BUG_IF(quic_bug_469887433_1,
+                !GetQuicReloadableFlag(
+                    quic_connection_uses_abstract_connection_id_generator));
+    return {};
+  }
   if (check_cid_collision_when_issue_new_cid) {
     QUIC_RELOADABLE_FLAG_COUNT_N(quic_check_cid_collision_when_issue_new_cid, 1,
                                  2);
-    if (!visitor_->MaybeReserveConnectionId(new_cid)) {
+    if (!visitor_->MaybeReserveConnectionId(*new_cid)) {
       QUIC_RELOADABLE_FLAG_COUNT_N(quic_check_cid_collision_when_issue_new_cid,
                                    2, 2);
       return {};
     }
   }
   QuicNewConnectionIdFrame frame;
-  frame.connection_id = new_cid;
+  frame.connection_id = *new_cid;
   frame.sequence_number = next_connection_id_sequence_number_++;
   frame.stateless_reset_token =
       QuicUtils::GenerateStatelessResetToken(frame.connection_id);
diff --git a/quiche/quic/core/quic_connection_id_manager.h b/quiche/quic/core/quic_connection_id_manager.h
index 7f271e2..1fa48e9 100644
--- a/quiche/quic/core/quic_connection_id_manager.h
+++ b/quiche/quic/core/quic_connection_id_manager.h
@@ -14,6 +14,7 @@
 #include <memory>
 
 #include "absl/types/optional.h"
+#include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/frames/quic_new_connection_id_frame.h"
 #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h"
 #include "quiche/quic/core/quic_alarm.h"
@@ -126,7 +127,8 @@
       const QuicConnectionId& initial_connection_id, const QuicClock* clock,
       QuicAlarmFactory* alarm_factory,
       QuicConnectionIdManagerVisitorInterface* visitor,
-      QuicConnectionContext* context);
+      QuicConnectionContext* context,
+      ConnectionIdGeneratorInterface& generator);
 
   virtual ~QuicSelfIssuedConnectionIdManager();
 
@@ -159,6 +161,9 @@
   // tell if a received packet has a valid connection ID.
   bool IsConnectionIdInUse(const QuicConnectionId& cid) const;
 
+  // TODO(martinduke): This class will be eliminated when
+  // FLAGS_gfe2_reloadable_flag_quic_connection_uses_abstract_connection_id_generator
+  // goes away.
   virtual QuicConnectionId GenerateNewConnectionId(
       const QuicConnectionId& old_connection_id) const;
 
@@ -189,6 +194,8 @@
   uint64_t next_connection_id_sequence_number_;
   // The sequence number of last connection ID consumed.
   uint64_t last_connection_id_consumed_by_self_sequence_number_;
+
+  ConnectionIdGeneratorInterface& connection_id_generator_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_connection_id_manager_test.cc b/quiche/quic/core/quic_connection_id_manager_test.cc
index dbd239f..c0f1333 100644
--- a/quiche/quic/core/quic_connection_id_manager_test.cc
+++ b/quiche/quic/core/quic_connection_id_manager_test.cc
@@ -10,6 +10,7 @@
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/platform/api/quic_test.h"
 #include "quiche/quic/test_tools/mock_clock.h"
+#include "quiche/quic/test_tools/mock_connection_id_generator.h"
 #include "quiche/quic/test_tools/quic_connection_id_manager_peer.h"
 #include "quiche/quic/test_tools/quic_test_utils.h"
 
@@ -535,7 +536,7 @@
   QuicSelfIssuedConnectionIdManagerTest()
       : cid_manager_(/*active_connection_id_limit*/ 2, initial_connection_id_,
                      &clock_, &alarm_factory_, &cid_manager_visitor_,
-                     /*context=*/nullptr) {
+                     /*context=*/nullptr, connection_id_generator_) {
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
     retire_self_issued_cid_alarm_ =
         QuicConnectionIdManagerPeer::GetRetireSelfIssuedConnectionIdAlarm(
@@ -543,6 +544,18 @@
   }
 
  protected:
+  // Verify that a call to GenerateNewConnectionId() does the right thing.
+  QuicConnectionId CheckGenerate(QuicConnectionId old_cid) {
+    QuicConnectionId new_cid =
+        QuicUtils::CreateReplacementConnectionId(old_cid);
+    if (GetQuicRestartFlag(quic_abstract_connection_id_generator)) {
+      // Ready for the actual call.
+      EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(old_cid))
+          .WillOnce(Return(new_cid));
+    }
+    return new_cid;
+  }
+
   MockClock clock_;
   test::MockAlarmFactory alarm_factory_;
   TestSelfIssuedConnectionIdManagerVisitor cid_manager_visitor_;
@@ -551,6 +564,7 @@
   QuicAlarm* retire_self_issued_cid_alarm_ = nullptr;
   std::string error_details_;
   QuicTime::Delta pto_delay_ = QuicTime::Delta::FromMilliseconds(10);
+  MockConnectionIdGenerator connection_id_generator_;
 };
 
 MATCHER_P3(ExpectedNewConnectionIdFrame, connection_id, sequence_number,
@@ -563,11 +577,11 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        RetireSelfIssuedConnectionIdInOrder) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
-  QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
-  QuicConnectionId cid3 = cid_manager_.GenerateNewConnectionId(cid2);
-  QuicConnectionId cid4 = cid_manager_.GenerateNewConnectionId(cid3);
-  QuicConnectionId cid5 = cid_manager_.GenerateNewConnectionId(cid4);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
+  QuicConnectionId cid2 = CheckGenerate(cid1);
+  QuicConnectionId cid3 = CheckGenerate(cid2);
+  QuicConnectionId cid4 = CheckGenerate(cid3);
+  QuicConnectionId cid5 = CheckGenerate(cid4);
 
   // Sends CID #1 to peer.
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
@@ -645,10 +659,10 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        RetireSelfIssuedConnectionIdOutOfOrder) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
-  QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
-  QuicConnectionId cid3 = cid_manager_.GenerateNewConnectionId(cid2);
-  QuicConnectionId cid4 = cid_manager_.GenerateNewConnectionId(cid3);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
+  QuicConnectionId cid2 = CheckGenerate(cid1);
+  QuicConnectionId cid3 = CheckGenerate(cid2);
+  QuicConnectionId cid4 = CheckGenerate(cid3);
 
   // Sends CID #1 to peer.
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
@@ -728,9 +742,9 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        ScheduleConnectionIdRetirementOneAtATime) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
-  QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
-  QuicConnectionId cid3 = cid_manager_.GenerateNewConnectionId(cid2);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
+  QuicConnectionId cid2 = CheckGenerate(cid1);
+  QuicConnectionId cid3 = CheckGenerate(cid2);
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
       .Times(3)
       .WillRepeatedly(Return(true));
@@ -787,9 +801,9 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        ScheduleMultipleConnectionIdRetirement) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
-  QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
-  QuicConnectionId cid3 = cid_manager_.GenerateNewConnectionId(cid2);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
+  QuicConnectionId cid2 = CheckGenerate(cid1);
+  QuicConnectionId cid3 = CheckGenerate(cid2);
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
       .Times(3)
       .WillRepeatedly(Return(true));
@@ -845,9 +859,9 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        AllExpiredConnectionIdsAreRetiredInOneBatch) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
-  QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
-  QuicConnectionId cid3 = cid_manager_.GenerateNewConnectionId(cid2);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
+  QuicConnectionId cid2 = CheckGenerate(cid1);
+  QuicConnectionId cid3 = CheckGenerate(cid2);
   QuicConnectionId cid;
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
       .Times(3)
@@ -907,7 +921,7 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        ErrorWhenRetireConnectionIdNeverIssued) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
 
   // CID #1 is sent to peer.
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
@@ -927,17 +941,20 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        ErrorWhenTooManyConnectionIdWaitingToBeRetired) {
   // CID #0 & #1 are issued.
-  EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
+  QuicConnectionId last_connection_id = CheckGenerate(initial_connection_id_);
+  EXPECT_CALL(cid_manager_visitor_,
+              MaybeReserveConnectionId(last_connection_id))
       .WillOnce(Return(true));
   EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_))
       .WillOnce(Return(true));
   cid_manager_.MaybeSendNewConnectionIds();
 
   // Add 8 connection IDs to the to-be-retired list.
-  QuicConnectionId last_connection_id =
-      cid_manager_.GenerateNewConnectionId(initial_connection_id_);
+
   for (int i = 0; i < 8; ++i) {
-    EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(_))
+    last_connection_id = CheckGenerate(last_connection_id);
+    EXPECT_CALL(cid_manager_visitor_,
+                MaybeReserveConnectionId(last_connection_id))
         .WillOnce(Return(true));
     EXPECT_CALL(cid_manager_visitor_, SendNewConnectionId(_));
     QuicRetireConnectionIdFrame retire_cid_frame;
@@ -945,8 +962,6 @@
     ASSERT_THAT(cid_manager_.OnRetireConnectionIdFrame(
                     retire_cid_frame, pto_delay_, &error_details_),
                 IsQuicNoError());
-    last_connection_id =
-        cid_manager_.GenerateNewConnectionId(last_connection_id);
   }
   QuicRetireConnectionIdFrame retire_cid_frame;
   retire_cid_frame.sequence_number = 8u;
@@ -959,7 +974,7 @@
 
 TEST_F(QuicSelfIssuedConnectionIdManagerTest, CannotIssueNewCidDueToVisitor) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
       .WillOnce(Return(false));
   if (GetQuicReloadableFlag(quic_check_cid_collision_when_issue_new_cid)) {
@@ -973,8 +988,8 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        CannotIssueNewCidUponRetireConnectionIdDueToVisitor) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
-  QuicConnectionId cid2 = cid_manager_.GenerateNewConnectionId(cid1);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
+  QuicConnectionId cid2 = CheckGenerate(cid1);
   // CID #0 & #1 are issued.
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
       .WillOnce(Return(true));
@@ -1000,7 +1015,7 @@
 TEST_F(QuicSelfIssuedConnectionIdManagerTest,
        DoNotIssueConnectionIdVoluntarilyIfOneHasIssuedForPerferredAddress) {
   QuicConnectionId cid0 = initial_connection_id_;
-  QuicConnectionId cid1 = cid_manager_.GenerateNewConnectionId(cid0);
+  QuicConnectionId cid1 = CheckGenerate(cid0);
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
       .WillOnce(Return(true));
   absl::optional<QuicNewConnectionIdFrame> new_cid_frame =
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index 2801334..9ff8413 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -41,6 +41,7 @@
 #include "quiche/quic/platform/api/quic_socket_address.h"
 #include "quiche/quic/platform/api/quic_test.h"
 #include "quiche/quic/test_tools/mock_clock.h"
+#include "quiche/quic/test_tools/mock_connection_id_generator.h"
 #include "quiche/quic/test_tools/mock_random.h"
 #include "quiche/quic/test_tools/quic_coalesced_packet_peer.h"
 #include "quiche/quic/test_tools/quic_config_peer.h"
@@ -187,11 +188,12 @@
                  QuicSocketAddress initial_peer_address,
                  TestConnectionHelper* helper, TestAlarmFactory* alarm_factory,
                  TestPacketWriter* writer, Perspective perspective,
-                 ParsedQuicVersion version)
+                 ParsedQuicVersion version,
+                 ConnectionIdGeneratorInterface& generator)
       : QuicConnection(connection_id, initial_self_address,
                        initial_peer_address, helper, alarm_factory, writer,
                        /* owns_writer= */ false, perspective,
-                       SupportedVersions(version)),
+                       SupportedVersions(version), generator),
         notifier_(nullptr) {
     writer->set_perspective(perspective);
     SetEncrypter(ENCRYPTION_FORWARD_SECURE,
@@ -611,7 +613,7 @@
             new TestPacketWriter(version(), &clock_, Perspective::IS_CLIENT)),
         connection_(connection_id_, kSelfAddress, kPeerAddress, helper_.get(),
                     alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT,
-                    version()),
+                    version(), connection_id_generator_),
         creator_(QuicConnectionPeer::GetPacketCreator(&connection_)),
         manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)),
         frame1_(0, false, 0, absl::string_view(data1)),
@@ -1493,6 +1495,7 @@
 
   QuicConnectionCloseFrame saved_connection_close_frame_;
   int connection_close_frame_count_;
+  MockConnectionIdGenerator connection_id_generator_;
 };
 
 // Run all end to end tests with all supported versions.
@@ -1873,6 +1876,11 @@
   QuicConnectionPeer::SetAddressValidated(&connection_);
 
   // Sends new server CID to client.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         server_cid1 = cid;
@@ -2072,6 +2080,11 @@
 
   // Sends new server CID to client.
   QuicConnectionId new_cid;
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         new_cid = cid;
@@ -2130,6 +2143,11 @@
 
   // Sends new server CID to client.
   QuicConnectionId new_cid;
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         new_cid = cid;
@@ -2198,6 +2216,11 @@
   QuicConnectionId server_cid0 = connection_.connection_id();
   QuicConnectionId server_cid1;
   // Sends new server CID to client.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         server_cid1 = cid;
@@ -2870,7 +2893,8 @@
 TEST_P(QuicConnectionTest, SmallerServerMaxPacketSize) {
   TestConnection connection(TestConnectionId(), kSelfAddress, kPeerAddress,
                             helper_.get(), alarm_factory_.get(), writer_.get(),
-                            Perspective::IS_SERVER, version());
+                            Perspective::IS_SERVER, version(),
+                            connection_id_generator_);
   EXPECT_EQ(Perspective::IS_SERVER, connection.perspective());
   EXPECT_EQ(1000u, connection.max_packet_length());
 }
@@ -2999,7 +3023,8 @@
   writer_->set_max_packet_size(lower_max_packet_size);
   TestConnection connection(connection_id, kSelfAddress, kPeerAddress,
                             helper_.get(), alarm_factory_.get(), writer_.get(),
-                            Perspective::IS_CLIENT, version());
+                            Perspective::IS_CLIENT, version(),
+                            connection_id_generator_);
   EXPECT_EQ(Perspective::IS_CLIENT, connection.perspective());
   EXPECT_EQ(lower_max_packet_size, connection.max_packet_length());
 }
@@ -6926,10 +6951,12 @@
 TEST_P(QuicConnectionTest, Pacing) {
   TestConnection server(connection_id_, kPeerAddress, kSelfAddress,
                         helper_.get(), alarm_factory_.get(), writer_.get(),
-                        Perspective::IS_SERVER, version());
+                        Perspective::IS_SERVER, version(),
+                        connection_id_generator_);
   TestConnection client(connection_id_, kSelfAddress, kPeerAddress,
                         helper_.get(), alarm_factory_.get(), writer_.get(),
-                        Perspective::IS_CLIENT, version());
+                        Perspective::IS_CLIENT, version(),
+                        connection_id_generator_);
   EXPECT_FALSE(QuicSentPacketManagerPeer::UsingPacing(
       static_cast<const QuicSentPacketManager*>(
           &client.sent_packet_manager())));
@@ -13294,6 +13321,11 @@
   QuicConnectionId client_cid1 = TestConnectionId(2);
   QuicConnectionId server_cid1;
   // Sends new server CID to client.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         server_cid1 = cid;
@@ -13442,6 +13474,11 @@
   QuicConnectionId server_cid0 = connection_.connection_id();
   QuicConnectionId server_cid1;
   // Sends new server CID to client.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         server_cid1 = cid;
@@ -13563,6 +13600,11 @@
   QuicConnectionId client_cid1 = TestConnectionId(2);
   QuicConnectionId server_cid1;
   // Sends new server CID to client.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke([&](const QuicConnectionId& cid) {
         server_cid1 = cid;
@@ -13679,6 +13721,11 @@
   QuicConnectionId client_cid1 = TestConnectionId(2);
   QuicConnectionId server_cid1;
   // Sends new server CID to client.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_)).WillOnce(Return(false));
   if (GetQuicReloadableFlag(quic_check_cid_collision_when_issue_new_cid)) {
     EXPECT_CALL(visitor_, SendNewConnectionId(_)).Times(0);
@@ -13812,6 +13859,10 @@
   ASSERT_EQ(packet_creator->GetDestinationConnectionId(), server_cid0);
 
   // Client will issue a new client connection ID to server.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator)) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, SendNewConnectionId(_))
       .WillOnce(Invoke([&](const QuicNewConnectionIdFrame& frame) {
         client_cid1 = frame.connection_id;
@@ -13970,6 +14021,10 @@
 
   // Client will issue a new client connection ID to server.
   QuicConnectionId new_client_connection_id;
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator)) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, SendNewConnectionId(_))
       .WillOnce(Invoke([&](const QuicNewConnectionIdFrame& frame) {
         new_client_connection_id = frame.connection_id;
@@ -14223,6 +14278,11 @@
   set_perspective(Perspective::IS_SERVER);
   connection_.CreateConnectionIdManager();
 
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_));
   EXPECT_CALL(visitor_, SendNewConnectionId(_));
   connection_.MaybeSendConnectionIdToClient();
@@ -14256,6 +14316,14 @@
   QuicRetireConnectionIdFrame frame;
   frame.sequence_number = 0u;
   if (connection_.connection_migration_use_new_cid()) {
+    if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+        !connection_.connection_id().IsEmpty()) {
+      EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(cid0))
+          .WillOnce(Return(TestConnectionId(456)));
+      EXPECT_CALL(connection_id_generator_,
+                  GenerateNextConnectionId(TestConnectionId(456)))
+          .WillOnce(Return(TestConnectionId(789)));
+    }
     EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
         .Times(2)
         .WillRepeatedly(Return(true));
@@ -14289,6 +14357,11 @@
   EXPECT_EQ(connection_.GetOneActiveServerConnectionId(), cid0);
 
   connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke(cid_recorder));
   EXPECT_CALL(visitor_, SendNewConnectionId(_));
@@ -14320,6 +14393,11 @@
 
   // Packet2 with RetireConnectionId frame trigers sending NewConnectionId
   // immediately.
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator) &&
+      !connection_.connection_id().IsEmpty()) {
+    EXPECT_CALL(connection_id_generator_, GenerateNextConnectionId(_))
+        .WillOnce(Return(TestConnectionId(456)));
+  }
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_))
       .WillOnce(Invoke(cid_recorder));
   EXPECT_CALL(visitor_, SendNewConnectionId(_));
@@ -14730,6 +14808,14 @@
       !connection_.connection_migration_use_new_cid()) {
     return;
   }
+  if (GetQuicRestartFlag(quic_abstract_connection_id_generator)) {
+    EXPECT_CALL(connection_id_generator_,
+                GenerateNextConnectionId(TestConnectionId(12)))
+        .WillOnce(Return(TestConnectionId(456)));
+    EXPECT_CALL(connection_id_generator_,
+                GenerateNextConnectionId(TestConnectionId(456)))
+        .WillOnce(Return(TestConnectionId(789)));
+  }
   EXPECT_CALL(visitor_, SendNewConnectionId(_)).Times(2);
   EXPECT_CALL(visitor_, OnRstStream(_));
   EXPECT_CALL(visitor_, OnWindowUpdateFrame(_));
diff --git a/quiche/quic/core/quic_dispatcher.h b/quiche/quic/core/quic_dispatcher.h
index b461690..e2b7761 100644
--- a/quiche/quic/core/quic_dispatcher.h
+++ b/quiche/quic/core/quic_dispatcher.h
@@ -352,6 +352,10 @@
   virtual void MaybeResetPacketsWithNoVersion(
       const quic::ReceivedPacketInfo& packet_info);
 
+  ConnectionIdGeneratorInterface& connection_id_generator() {
+    return connection_id_generator_;
+  }
+
  private:
   friend class test::QuicDispatcherPeer;
 
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 284dd25..793237c 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -95,10 +95,12 @@
 QUIC_FLAG(quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
 // If true, validate header field character at spdy stream instead of qpack for IETF QUIC.
 QUIC_FLAG(quic_reloadable_flag_quic_validate_header_field_value_at_spdy_stream, true)
+// QuicConnection uses a library to generate connection IDs
+QUIC_FLAG(quic_reloadable_flag_quic_connection_uses_abstract_connection_id_generator, false)
+// QuicDispatcher uses a library to generate connection IDs
+QUIC_FLAG(quic_restart_flag_quic_abstract_connection_id_generator, false)
 // Store original QUIC connection IDs in the dispatcher\'s map
 QUIC_FLAG(quic_restart_flag_quic_map_original_connection_ids2, true)
-// Use a library to generate connection IDs
-QUIC_FLAG(quic_restart_flag_quic_abstract_connection_id_generator, false)
 // When the flag is true, exit STARTUP after the same number of loss events as PROBE_UP.
 QUIC_FLAG(quic_reloadable_flag_quic_bbr2_startup_probe_up_loss_events, true)
 // When true, defaults to BBR congestion control instead of Cubic.