gfe-relnote: Move QUIC crypto frames to be gated behind new flag gfe2_reloadable_flag_quic_enable_version_48

PiperOrigin-RevId: 256297207
Change-Id: I6f4ab9e8d39ff096f34a761a208af67b1ba7061e
diff --git a/quic/core/legacy_quic_stream_id_manager_test.cc b/quic/core/legacy_quic_stream_id_manager_test.cc
index 823cdc0..ca4491a 100644
--- a/quic/core/legacy_quic_stream_id_manager_test.cc
+++ b/quic/core/legacy_quic_stream_id_manager_test.cc
@@ -27,7 +27,11 @@
     session_->Initialize();
   }
 
-  QuicStreamId GetNthClientInitiatedId(int n) { return 3 + 2 * n; }
+  QuicStreamId GetNthClientInitiatedId(int n) {
+    return QuicUtils::GetFirstBidirectionalStreamId(
+               connection_->transport_version(), Perspective::IS_CLIENT) +
+           2 * n;
+  }
 
   QuicStreamId GetNthServerInitiatedId(int n) { return 2 + 2 * n; }
 
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index 66d066a..ccac80c 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -880,11 +880,12 @@
 }
 
 TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
   SetQuicReloadableFlag(quic_disable_version_39, false);
   SetQuicReloadableFlag(quic_disable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_47, true);
+  SetQuicReloadableFlag(quic_enable_version_48, true);
   SetQuicReloadableFlag(quic_enable_version_99, true);
 
   VerifyVersionNotSupported(QuicVersionReservedForNegotiation());
@@ -893,6 +894,16 @@
                                            QuicVersionMin().transport_version));
   VerifyVersionSupported(QuicVersionMax());
 
+  // Turn off version 48.
+  SetQuicReloadableFlag(quic_enable_version_48, false);
+  VerifyVersionNotSupported(
+      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
+
+  // Turn on version 48.
+  SetQuicReloadableFlag(quic_enable_version_48, true);
+  VerifyVersionSupported(
+      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48));
+
   // Turn off version 47.
   SetQuicReloadableFlag(quic_enable_version_47, false);
   VerifyVersionNotSupported(
@@ -925,7 +936,7 @@
 }
 
 TEST_F(QuicDispatcherTest, RejectDeprecatedVersionsWithVersionNegotiation) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Please add deprecated versions to this test");
   QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
   CreateTimeWaitListManager();
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index 486023a..3e0f68b 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -6619,7 +6619,28 @@
   QuicFrames frames = {QuicFrame(&crypto_frame)};
 
   // clang-format off
-  unsigned char packet[] = {
+  unsigned char packet48[] = {
+    // type (short header, 4 byte packet number)
+    0x43,
+    // connection_id
+    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+    // packet number
+    0x12, 0x34, 0x56, 0x78,
+
+    // frame type (QuicFrameType CRYPTO_FRAME)
+    0x08,
+    // offset
+    kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+    0x32, 0x10, 0x76, 0x54,
+    // length
+    kVarInt62OneByte + 12,
+    // data
+    'h',  'e',  'l',  'l',
+    'o',  ' ',  'w',  'o',
+    'r',  'l',  'd',  '!',
+  };
+
+  unsigned char packet99[] = {
     // type (short header, 4 byte packet number)
     0x43,
     // connection_id
@@ -6641,7 +6662,12 @@
   };
   // clang-format on
 
-  size_t packet_size = QUIC_ARRAYSIZE(packet);
+  unsigned char* packet = packet48;
+  size_t packet_size = QUIC_ARRAYSIZE(packet48);
+  if (framer_.transport_version() == QUIC_VERSION_99) {
+    packet = packet99;
+    packet_size = QUIC_ARRAYSIZE(packet99);
+  }
 
   std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_TRUE(data != nullptr);
@@ -6651,14 +6677,41 @@
 }
 
 TEST_P(QuicFramerTest, CryptoFrame) {
-  if (framer_.transport_version() < QUIC_VERSION_99) {
-    // CRYPTO frames aren't supported prior to v46.
+  if (framer_.transport_version() < QUIC_VERSION_48) {
+    // CRYPTO frames aren't supported prior to v48.
     return;
   }
   SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
 
   // clang-format off
-  PacketFragments packet = {
+  PacketFragments packet48 = {
+      // type (short header, 4 byte packet number)
+      {"",
+       {0x43}},
+      // connection_id
+      {"",
+       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+      // packet number
+      {"",
+       {0x12, 0x34, 0x56, 0x78}},
+      // frame type (QuicFrameType CRYPTO_FRAME)
+      {"",
+       {0x08}},
+      // offset
+      {"",
+       {kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+        0x32, 0x10, 0x76, 0x54}},
+      // data length
+      {"Invalid data length.",
+       {kVarInt62OneByte + 12}},
+      // data
+      {"Unable to read frame data.",
+       {'h',  'e',  'l',  'l',
+        'o',  ' ',  'w',  'o',
+        'r',  'l',  'd',  '!'}},
+  };
+
+  PacketFragments packet99 = {
       // type (short header, 4 byte packet number)
       {"",
        {0x43}},
@@ -6686,8 +6739,10 @@
   };
   // clang-format on
 
+  PacketFragments& fragments =
+      framer_.transport_version() == QUIC_VERSION_99 ? packet99 : packet48;
   std::unique_ptr<QuicEncryptedPacket> encrypted(
-      AssemblePacketFromFragments(packet));
+      AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
 
   EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -6701,7 +6756,7 @@
   EXPECT_EQ("hello world!",
             std::string(frame->data_buffer, frame->data_length));
 
-  CheckFramingBoundaries(packet, QUIC_INVALID_FRAME_DATA);
+  CheckFramingBoundaries(fragments, QUIC_INVALID_FRAME_DATA);
 }
 
 TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
diff --git a/quic/core/quic_version_manager.cc b/quic/core/quic_version_manager.cc
index 8886afb..49aee67 100644
--- a/quic/core/quic_version_manager.cc
+++ b/quic/core/quic_version_manager.cc
@@ -15,6 +15,7 @@
 QuicVersionManager::QuicVersionManager(
     ParsedQuicVersionVector supported_versions)
     : enable_version_99_(GetQuicReloadableFlag(quic_enable_version_99)),
+      enable_version_48_(GetQuicReloadableFlag(quic_enable_version_48)),
       enable_version_47_(GetQuicReloadableFlag(quic_enable_version_47)),
       disable_version_44_(GetQuicReloadableFlag(quic_disable_version_44)),
       disable_version_39_(GetQuicReloadableFlag(quic_disable_version_39)),
@@ -38,11 +39,13 @@
 
 void QuicVersionManager::MaybeRefilterSupportedVersions() {
   if (enable_version_99_ != GetQuicReloadableFlag(quic_enable_version_99) ||
+      enable_version_48_ != GetQuicReloadableFlag(quic_enable_version_48) ||
       enable_version_47_ != GetQuicReloadableFlag(quic_enable_version_47) ||
       disable_version_44_ != GetQuicReloadableFlag(quic_disable_version_44) ||
       disable_version_39_ != GetQuicReloadableFlag(quic_disable_version_39) ||
       enable_tls_ != GetQuicFlag(FLAGS_quic_supports_tls_handshake)) {
     enable_version_99_ = GetQuicReloadableFlag(quic_enable_version_99);
+    enable_version_48_ = GetQuicReloadableFlag(quic_enable_version_48);
     enable_version_47_ = GetQuicReloadableFlag(quic_enable_version_47);
     disable_version_44_ = GetQuicReloadableFlag(quic_disable_version_44);
     disable_version_39_ = GetQuicReloadableFlag(quic_disable_version_39);
diff --git a/quic/core/quic_version_manager.h b/quic/core/quic_version_manager.h
index c87c092..a6b7bcb 100644
--- a/quic/core/quic_version_manager.h
+++ b/quic/core/quic_version_manager.h
@@ -40,6 +40,8 @@
  private:
   // quic_enable_version_99 flag
   bool enable_version_99_;
+  // quic_enable_version_48 flag
+  bool enable_version_48_;
   // quic_enable_version_47 flag
   bool enable_version_47_;
   // quic_disable_version_44 flag
diff --git a/quic/core/quic_version_manager_test.cc b/quic/core/quic_version_manager_test.cc
index 0716ca9..886c0d3 100644
--- a/quic/core/quic_version_manager_test.cc
+++ b/quic/core/quic_version_manager_test.cc
@@ -16,9 +16,10 @@
 class QuicVersionManagerTest : public QuicTest {};
 
 TEST_F(QuicVersionManagerTest, QuicVersionManager) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
   SetQuicReloadableFlag(quic_enable_version_99, false);
+  SetQuicReloadableFlag(quic_enable_version_48, false);
   SetQuicReloadableFlag(quic_enable_version_47, false);
   SetQuicReloadableFlag(quic_disable_version_44, true);
   SetQuicReloadableFlag(quic_disable_version_39, true);
@@ -46,12 +47,19 @@
                                         QUIC_VERSION_39}),
             manager.GetSupportedTransportVersions());
 
-  SetQuicReloadableFlag(quic_enable_version_99, true);
-  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_99, QUIC_VERSION_47,
+  SetQuicReloadableFlag(quic_enable_version_48, true);
+  EXPECT_EQ(QuicTransportVersionVector({QUIC_VERSION_48, QUIC_VERSION_47,
                                         QUIC_VERSION_46, QUIC_VERSION_44,
                                         QUIC_VERSION_43, QUIC_VERSION_39}),
             manager.GetSupportedTransportVersions());
 
+  SetQuicReloadableFlag(quic_enable_version_99, true);
+  EXPECT_EQ(
+      QuicTransportVersionVector(
+          {QUIC_VERSION_99, QUIC_VERSION_48, QUIC_VERSION_47, QUIC_VERSION_46,
+           QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39}),
+      manager.GetSupportedTransportVersions());
+
   // Ensure that all versions are now supported.
   EXPECT_EQ(FilterSupportedTransportVersions(AllSupportedTransportVersions()),
             manager.GetSupportedTransportVersions());
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 0801c02..686e983 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -121,6 +121,8 @@
       return MakeVersionLabel(proto, '0', '4', '6');
     case QUIC_VERSION_47:
       return MakeVersionLabel(proto, '0', '4', '7');
+    case QUIC_VERSION_48:
+      return MakeVersionLabel(proto, '0', '4', '8');
     case QUIC_VERSION_99:
       if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3 &&
           GetQuicFlag(FLAGS_quic_ietf_draft_version) != 0) {
@@ -216,8 +218,7 @@
     for (QuicTransportVersion version : kSupportedTransportVersions) {
       if (protocol == PROTOCOL_TLS1_3 &&
           !QuicVersionUsesCryptoFrames(version)) {
-        // The TLS handshake is only deployable if CRYPTO frames are also used,
-        // which are added in v47.
+        // The TLS handshake is only deployable if CRYPTO frames are also used.
         continue;
       }
       supported_versions.push_back(ParsedQuicVersion(protocol, version));
@@ -264,6 +265,10 @@
       if (GetQuicReloadableFlag(quic_enable_version_99)) {
         filtered_versions.push_back(version);
       }
+    } else if (version.transport_version == QUIC_VERSION_48) {
+      if (GetQuicReloadableFlag(quic_enable_version_48)) {
+        filtered_versions.push_back(version);
+      }
     } else if (version.transport_version == QUIC_VERSION_47) {
       if (GetQuicReloadableFlag(quic_enable_version_47)) {
         filtered_versions.push_back(version);
@@ -369,6 +374,7 @@
     RETURN_STRING_LITERAL(QUIC_VERSION_44);
     RETURN_STRING_LITERAL(QUIC_VERSION_46);
     RETURN_STRING_LITERAL(QUIC_VERSION_47);
+    RETURN_STRING_LITERAL(QUIC_VERSION_48);
     RETURN_STRING_LITERAL(QUIC_VERSION_99);
     default:
       return "QUIC_VERSION_UNSUPPORTED";
@@ -456,11 +462,14 @@
   if (parsed_version.handshake_protocol == PROTOCOL_TLS1_3) {
     SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
   }
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
   if (parsed_version.transport_version == QUIC_VERSION_99) {
     SetQuicReloadableFlag(quic_enable_version_99, true);
   }
+  if (parsed_version.transport_version == QUIC_VERSION_48) {
+    SetQuicReloadableFlag(quic_enable_version_48, true);
+  }
   if (parsed_version.transport_version == QUIC_VERSION_47) {
     SetQuicReloadableFlag(quic_enable_version_47, true);
   }
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h
index c8af447..72bb32c 100644
--- a/quic/core/quic_versions.h
+++ b/quic/core/quic_versions.h
@@ -104,6 +104,7 @@
   QUIC_VERSION_46 = 46,  // Use IETF draft-17 header format with demultiplexing
                          // bit.
   QUIC_VERSION_47 = 47,  // Allow variable-length QUIC connection IDs.
+  QUIC_VERSION_48 = 48,  // Use CRYPTO frames for the handshake.
   QUIC_VERSION_99 = 99,  // Dumping ground for IETF QUIC changes which are not
                          // yet ready for production.
   // QUIC_VERSION_RESERVED_FOR_NEGOTIATION is sent over the wire as ?a?a?a?a
@@ -197,7 +198,7 @@
 //
 // See go/new-quic-version for more details on how to roll out new versions.
 static const QuicTransportVersion kSupportedTransportVersions[] = {
-    QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46,
+    QUIC_VERSION_99, QUIC_VERSION_48, QUIC_VERSION_47, QUIC_VERSION_46,
     QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39,
 };
 
@@ -410,7 +411,7 @@
 // instead of stream 1.
 QUIC_EXPORT_PRIVATE inline bool QuicVersionUsesCryptoFrames(
     QuicTransportVersion transport_version) {
-  return transport_version == QUIC_VERSION_99;
+  return transport_version >= QUIC_VERSION_48;
 }
 
 // Returns whether |transport_version| does not have the
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc
index 0828860..016ae5f 100644
--- a/quic/core/quic_versions_test.cc
+++ b/quic/core/quic_versions_test.cc
@@ -122,6 +122,8 @@
             ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '6')));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
             ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '7')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48),
+            ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '8')));
 
   // Test TLS versions:
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_39),
@@ -134,6 +136,8 @@
             ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6')));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
             ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48),
+            ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '8')));
 }
 
 TEST_F(QuicVersionsTest, ParseQuicVersionString) {
@@ -147,6 +151,8 @@
             ParseQuicVersionString("Q046"));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
             ParseQuicVersionString("Q047"));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48),
+            ParseQuicVersionString("Q048"));
 
   EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString(""));
   EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionString("Q 47"));
@@ -164,6 +170,8 @@
             ParseQuicVersionString("T046"));
   EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
             ParseQuicVersionString("T047"));
+  EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48),
+            ParseQuicVersionString("T048"));
 }
 
 TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
@@ -182,6 +190,9 @@
   EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '7'),
             CreateQuicVersionLabel(
                 ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47)));
+  EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '8'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48)));
 
   // Test a TLS version:
   EXPECT_EQ(MakeVersionLabel('T', '0', '3', '9'),
@@ -199,6 +210,9 @@
   EXPECT_EQ(MakeVersionLabel('T', '0', '4', '7'),
             CreateQuicVersionLabel(
                 ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47)));
+  EXPECT_EQ(MakeVersionLabel('T', '0', '4', '8'),
+            CreateQuicVersionLabel(
+                ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48)));
 
   // Make sure the negotiation reserved version is in the IETF reserved space.
   EXPECT_EQ(MakeVersionLabel(0xda, 0x5a, 0x3a, 0x3a) & 0x0f0f0f0f,
@@ -296,13 +310,14 @@
   SetQuicReloadableFlag(quic_disable_version_39, false);
   SetQuicReloadableFlag(quic_disable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_47, true);
+  SetQuicReloadableFlag(quic_enable_version_48, true);
   SetQuicReloadableFlag(quic_enable_version_99, true);
   ParsedQuicVersionVector parsed_versions;
   for (QuicTransportVersion version : all_versions) {
     parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
   }
   QuicTransportVersionVector expected_versions = {
-      QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46,
+      QUIC_VERSION_99, QUIC_VERSION_48, QUIC_VERSION_47, QUIC_VERSION_46,
       QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39};
   ParsedQuicVersionVector expected_parsed_versions;
   for (QuicTransportVersion version : expected_versions) {
@@ -319,6 +334,31 @@
   SetQuicReloadableFlag(quic_disable_version_39, false);
   SetQuicReloadableFlag(quic_disable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_47, true);
+  SetQuicReloadableFlag(quic_enable_version_48, true);
+  SetQuicReloadableFlag(quic_enable_version_99, false);
+  ParsedQuicVersionVector parsed_versions;
+  for (QuicTransportVersion version : all_versions) {
+    parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
+  }
+  QuicTransportVersionVector expected_versions = {
+      QUIC_VERSION_48, QUIC_VERSION_47, QUIC_VERSION_46,
+      QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39};
+  ParsedQuicVersionVector expected_parsed_versions;
+  for (QuicTransportVersion version : expected_versions) {
+    expected_parsed_versions.push_back(
+        ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
+  }
+
+  ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
+  ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
+}
+
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo48) {
+  QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
+  SetQuicReloadableFlag(quic_disable_version_39, false);
+  SetQuicReloadableFlag(quic_disable_version_44, false);
+  SetQuicReloadableFlag(quic_enable_version_47, true);
+  SetQuicReloadableFlag(quic_enable_version_48, false);
   SetQuicReloadableFlag(quic_enable_version_99, false);
   ParsedQuicVersionVector parsed_versions;
   for (QuicTransportVersion version : all_versions) {
@@ -342,6 +382,7 @@
   SetQuicReloadableFlag(quic_disable_version_39, false);
   SetQuicReloadableFlag(quic_disable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_47, false);
+  SetQuicReloadableFlag(quic_enable_version_48, false);
   SetQuicReloadableFlag(quic_enable_version_99, false);
   ParsedQuicVersionVector parsed_versions;
   for (QuicTransportVersion version : all_versions) {
@@ -364,6 +405,7 @@
   SetQuicReloadableFlag(quic_disable_version_39, false);
   SetQuicReloadableFlag(quic_disable_version_44, true);
   SetQuicReloadableFlag(quic_enable_version_47, false);
+  SetQuicReloadableFlag(quic_enable_version_48, false);
   SetQuicReloadableFlag(quic_enable_version_99, false);
   ParsedQuicVersionVector parsed_versions;
   for (QuicTransportVersion version : all_versions) {
@@ -386,6 +428,7 @@
   SetQuicReloadableFlag(quic_disable_version_39, true);
   SetQuicReloadableFlag(quic_disable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_47, false);
+  SetQuicReloadableFlag(quic_enable_version_48, false);
   SetQuicReloadableFlag(quic_enable_version_99, false);
   ParsedQuicVersionVector parsed_versions;
   for (QuicTransportVersion version : all_versions) {
@@ -442,13 +485,14 @@
 // yet a typo was made in doing the #defines and it was caught
 // only in some test far removed from here... Better safe than sorry.
 TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
-  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
+  static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
                 "Supported versions out of sync");
   EXPECT_EQ(QUIC_VERSION_39, 39);
   EXPECT_EQ(QUIC_VERSION_43, 43);
   EXPECT_EQ(QUIC_VERSION_44, 44);
   EXPECT_EQ(QUIC_VERSION_46, 46);
   EXPECT_EQ(QUIC_VERSION_47, 47);
+  EXPECT_EQ(QUIC_VERSION_48, 48);
   EXPECT_EQ(QUIC_VERSION_99, 99);
 }
 
@@ -457,11 +501,17 @@
       ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47);
   ParsedQuicVersion parsed_version_t047 =
       ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47);
+  ParsedQuicVersion parsed_version_q048 =
+      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48);
+  ParsedQuicVersion parsed_version_t048 =
+      ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48);
   ParsedQuicVersion parsed_version_t099 =
       ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
 
   EXPECT_EQ("h3-google-Q047", AlpnForVersion(parsed_version_q047));
   EXPECT_EQ("h3-google-T047", AlpnForVersion(parsed_version_t047));
+  EXPECT_EQ("h3-google-Q048", AlpnForVersion(parsed_version_q048));
+  EXPECT_EQ("h3-google-T048", AlpnForVersion(parsed_version_t048));
   EXPECT_EQ("h3-google-T099", AlpnForVersion(parsed_version_t099));
 }
 
@@ -496,28 +546,63 @@
       ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47);
   ParsedQuicVersion parsed_version_t047 =
       ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47);
+  ParsedQuicVersion parsed_version_q048 =
+      ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_48);
+  ParsedQuicVersion parsed_version_t048 =
+      ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_48);
   ParsedQuicVersion parsed_version_t099 =
       ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99);
   SetQuicFlag(FLAGS_quic_supports_tls_handshake, false);
   SetQuicReloadableFlag(quic_disable_version_39, false);
   SetQuicReloadableFlag(quic_disable_version_44, false);
   SetQuicReloadableFlag(quic_enable_version_47, false);
+  SetQuicReloadableFlag(quic_enable_version_48, false);
   SetQuicReloadableFlag(quic_enable_version_99, false);
 
-  QuicEnableVersion(parsed_version_q047);
-  EXPECT_FALSE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
-  EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
-  EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+  {
+    QuicFlagSaver flag_saver;
+    QuicEnableVersion(parsed_version_q047);
+    EXPECT_FALSE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
+    EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+  }
 
-  QuicEnableVersion(parsed_version_t047);
-  EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
-  EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
-  EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+  {
+    QuicFlagSaver flag_saver;
+    QuicEnableVersion(parsed_version_t047);
+    EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
+    EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+  }
 
-  QuicEnableVersion(parsed_version_t099);
-  EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
-  EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_47));
-  EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_99));
+  {
+    QuicFlagSaver flag_saver;
+    QuicEnableVersion(parsed_version_q048);
+    EXPECT_FALSE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
+    EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_48));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+  }
+
+  {
+    QuicFlagSaver flag_saver;
+    QuicEnableVersion(parsed_version_t048);
+    EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
+    EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_48));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_99));
+  }
+
+  {
+    QuicFlagSaver flag_saver;
+    QuicEnableVersion(parsed_version_t099);
+    EXPECT_TRUE(GetQuicFlag(FLAGS_quic_supports_tls_handshake));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_47));
+    EXPECT_FALSE(GetQuicReloadableFlag(quic_enable_version_48));
+    EXPECT_TRUE(GetQuicReloadableFlag(quic_enable_version_99));
+  }
 }
 
 TEST_F(QuicVersionsTest, ReservedForNegotiation) {
diff --git a/quic/core/tls_handshaker_test.cc b/quic/core/tls_handshaker_test.cc
index 33f3d05..f15a266 100644
--- a/quic/core/tls_handshaker_test.cc
+++ b/quic/core/tls_handshaker_test.cc
@@ -275,33 +275,22 @@
   }
 }
 
-ParsedQuicVersionVector AllTlsSupportedVersions() {
-  SetQuicReloadableFlag(quic_enable_version_99, true);
-  SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
-  ParsedQuicVersionVector supported_versions;
-  for (QuicTransportVersion version : kSupportedTransportVersions) {
-    if (!QuicVersionUsesCryptoFrames(version)) {
-      // The TLS handshake is only deployable if CRYPTO frames are also used.
-      continue;
-    }
-    supported_versions.push_back(ParsedQuicVersion(PROTOCOL_TLS1_3, version));
-  }
-  return supported_versions;
-}
-
 class TlsHandshakerTest : public QuicTest {
  public:
   TlsHandshakerTest()
-      : client_conn_(new MockQuicConnection(&conn_helper_,
-                                            &alarm_factory_,
-                                            Perspective::IS_CLIENT,
-                                            AllTlsSupportedVersions())),
-        server_conn_(new MockQuicConnection(&conn_helper_,
-                                            &alarm_factory_,
-                                            Perspective::IS_SERVER,
-                                            AllTlsSupportedVersions())),
+      : client_conn_(new MockQuicConnection(
+            &conn_helper_,
+            &alarm_factory_,
+            Perspective::IS_CLIENT,
+            {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)})),
+        server_conn_(new MockQuicConnection(
+            &conn_helper_,
+            &alarm_factory_,
+            Perspective::IS_SERVER,
+            {ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)})),
         client_session_(client_conn_, /*create_mock_crypto_stream=*/false),
         server_session_(server_conn_, /*create_mock_crypto_stream=*/false) {
+    SetQuicFlag(FLAGS_quic_supports_tls_handshake, true);
     client_stream_ = new TestQuicCryptoClientStream(&client_session_);
     client_session_.SetCryptoStream(client_stream_);
     server_stream_ =
diff --git a/quic/test_tools/quic_packet_creator_peer.cc b/quic/test_tools/quic_packet_creator_peer.cc
index 85c7687..d4dc008 100644
--- a/quic/test_tools/quic_packet_creator_peer.cc
+++ b/quic/test_tools/quic_packet_creator_peer.cc
@@ -19,7 +19,9 @@
 void QuicPacketCreatorPeer::SetSendVersionInPacket(
     QuicPacketCreator* creator,
     bool send_version_in_packet) {
-  if (!VersionHasIetfQuicFrames(creator->framer_->transport_version())) {
+  ParsedQuicVersion version = creator->framer_->version();
+  if (!VersionHasIetfQuicFrames(version.transport_version) &&
+      version.handshake_protocol != PROTOCOL_TLS1_3) {
     creator->send_version_in_packet_ = send_version_in_packet;
     return;
   }