Internal change

PiperOrigin-RevId: 540935137
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc
index 52efb1a..183609a 100644
--- a/quiche/quic/core/http/end_to_end_test.cc
+++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -5203,7 +5203,8 @@
 
 TEST_P(EndToEndPacketReorderingTest, ReorderedConnectivityProbing) {
   ASSERT_TRUE(Initialize());
-  if (version_.HasIetfQuicFrames()) {
+  if (version_.HasIetfQuicFrames() ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     return;
   }
 
diff --git a/quiche/quic/core/http/quic_spdy_session_test.cc b/quiche/quic/core/http/quic_spdy_session_test.cc
index 86a22c0..cf95ec7 100644
--- a/quiche/quic/core/http/quic_spdy_session_test.cc
+++ b/quiche/quic/core/http/quic_spdy_session_test.cc
@@ -1216,7 +1216,8 @@
 // Test that server session will send a connectivity probe in response to a
 // connectivity probe on the same path.
 TEST_P(QuicSpdySessionTestServer, ServerReplyToConnecitivityProbe) {
-  if (VersionHasIetfQuicFrames(transport_version())) {
+  if (VersionHasIetfQuicFrames(transport_version()) ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     return;
   }
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
@@ -1230,12 +1231,6 @@
   EXPECT_CALL(*connection_,
               SendConnectivityProbingPacket(nullptr, new_peer_address));
 
-  if (VersionHasIetfQuicFrames(transport_version())) {
-    // Need to explicitly do this to emulate the reception of a PathChallenge,
-    // which stores its payload for use in generating the response.
-    connection_->OnPathChallengeFrame(
-        QuicPathChallengeFrame(0, {{0, 1, 2, 3, 4, 5, 6, 7}}));
-  }
   session_.OnPacketReceived(session_.self_address(), new_peer_address,
                             /*is_connectivity_probe=*/true);
   EXPECT_EQ(old_peer_address, session_.peer_address());
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 80945f6..22174b9 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -2138,7 +2138,7 @@
   }
 
   if (IsCurrentPacketConnectivityProbing()) {
-    QUICHE_DCHECK(!version().HasIetfQuicFrames());
+    QUICHE_DCHECK(!version().HasIetfQuicFrames() && !ignore_gquic_probing_);
     ++stats_.num_connectivity_probing_received;
   }
 
@@ -2157,7 +2157,7 @@
       << ENDPOINT << "Received a padded PING packet. is_probing: "
       << IsCurrentPacketConnectivityProbing();
 
-  if (!version().HasIetfQuicFrames()) {
+  if (!version().HasIetfQuicFrames() && !ignore_gquic_probing_) {
     MaybeRespondToConnectivityProbingOrMigration();
   }
 
@@ -5453,57 +5453,66 @@
         last_received_packet_info_.length);
     return connected_;
   }
-  // Packet content is tracked to identify connectivity probe in non-IETF
-  // version, where a connectivity probe is defined as
-  // - a padded PING packet with peer address change received by server,
-  // - a padded PING packet on new path received by client.
 
-  if (current_packet_content_ == NOT_PADDED_PING) {
-    // We have already learned the current packet is not a connectivity
-    // probing packet. Peer migration should have already been started earlier
-    // if needed.
-    return connected_;
-  }
+  if (!ignore_gquic_probing_) {
+    // Packet content is tracked to identify connectivity probe in non-IETF
+    // version, where a connectivity probe is defined as
+    // - a padded PING packet with peer address change received by server,
+    // - a padded PING packet on new path received by client.
 
-  if (type == PING_FRAME) {
-    if (current_packet_content_ == NO_FRAMES_RECEIVED) {
-      current_packet_content_ = FIRST_FRAME_IS_PING;
+    if (current_packet_content_ == NOT_PADDED_PING) {
+      // We have already learned the current packet is not a connectivity
+      // probing packet. Peer migration should have already been started earlier
+      // if needed.
       return connected_;
     }
-  }
 
-  // In Google QUIC, we look for a packet with just a PING and PADDING.
-  // If the condition is met, mark things as connectivity-probing, causing
-  // later processing to generate the correct response.
-  if (type == PADDING_FRAME && current_packet_content_ == FIRST_FRAME_IS_PING) {
-    current_packet_content_ = SECOND_FRAME_IS_PADDING;
-    if (perspective_ == Perspective::IS_SERVER) {
-      is_current_packet_connectivity_probing_ =
-          current_effective_peer_migration_type_ != NO_CHANGE;
-      QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
-          << ENDPOINT
-          << "Detected connectivity probing packet. "
-             "current_effective_peer_migration_type_:"
-          << current_effective_peer_migration_type_;
-    } else {
-      is_current_packet_connectivity_probing_ =
-          (last_received_packet_info_.source_address != peer_address()) ||
-          (last_received_packet_info_.destination_address !=
-           default_path_.self_address);
-      QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
-          << ENDPOINT
-          << "Detected connectivity probing packet. "
-             "last_packet_source_address:"
-          << last_received_packet_info_.source_address
-          << ", peer_address_:" << peer_address()
-          << ", last_packet_destination_address:"
-          << last_received_packet_info_.destination_address
-          << ", default path self_address :" << default_path_.self_address;
+    if (type == PING_FRAME) {
+      if (current_packet_content_ == NO_FRAMES_RECEIVED) {
+        current_packet_content_ = FIRST_FRAME_IS_PING;
+        return connected_;
+      }
     }
-    return connected_;
+
+    // In Google QUIC, we look for a packet with just a PING and PADDING.
+    // If the condition is met, mark things as connectivity-probing, causing
+    // later processing to generate the correct response.
+    if (type == PADDING_FRAME &&
+        current_packet_content_ == FIRST_FRAME_IS_PING) {
+      current_packet_content_ = SECOND_FRAME_IS_PADDING;
+      QUIC_CODE_COUNT(gquic_padded_ping_received);
+      if (perspective_ == Perspective::IS_SERVER) {
+        is_current_packet_connectivity_probing_ =
+            current_effective_peer_migration_type_ != NO_CHANGE;
+        QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
+            << ENDPOINT
+            << "Detected connectivity probing packet. "
+               "current_effective_peer_migration_type_:"
+            << current_effective_peer_migration_type_;
+      } else {
+        is_current_packet_connectivity_probing_ =
+            (last_received_packet_info_.source_address != peer_address()) ||
+            (last_received_packet_info_.destination_address !=
+             default_path_.self_address);
+        QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
+            << ENDPOINT
+            << "Detected connectivity probing packet. "
+               "last_packet_source_address:"
+            << last_received_packet_info_.source_address
+            << ", peer_address_:" << peer_address()
+            << ", last_packet_destination_address:"
+            << last_received_packet_info_.destination_address
+            << ", default path self_address :" << default_path_.self_address;
+      }
+      return connected_;
+    }
+
+    current_packet_content_ = NOT_PADDED_PING;
+  } else {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_ignore_gquic_probing);
+    QUICHE_DCHECK_EQ(current_packet_content_, NO_FRAMES_RECEIVED);
   }
 
-  current_packet_content_ = NOT_PADDED_PING;
   if (GetLargestReceivedPacket().IsInitialized() &&
       last_received_packet_info_.header.packet_number ==
           GetLargestReceivedPacket()) {
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index 90e5018..9004fe0 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -1318,6 +1318,8 @@
     return peer_issued_cid_manager_ != nullptr;
   }
 
+  bool ignore_gquic_probing() const { return ignore_gquic_probing_; }
+
   // Sets the ECN marking for all outgoing packets, assuming that the congestion
   // control supports that codepoint. QuicConnection will revert to sending
   // ECN_NOT_ECT if there is evidence the path is dropping ECN-marked packets,
@@ -1903,8 +1905,7 @@
   // response on server side. And no-op on client side. And for both Google Quic
   // and IETF Quic, start migration if the current packet is a non-probing
   // packet.
-  // TODO(danzh) rename to MaybeRespondToPeerMigration() when Google Quic is
-  // deprecated.
+  // TODO(danzh) remove it when deprecating ignore_gquic_probing_.
   void MaybeRespondToConnectivityProbingOrMigration();
 
   // Called in IETF QUIC. Start peer migration if a non-probing frame is
@@ -2002,8 +2003,9 @@
 
   QuicFramer framer_;
 
-  // Contents received in the current packet, especially used to identify
-  // whether the current packet is a padded PING packet.
+  // TODO(danzh) remove below fields once quic_ignore_gquic_probing_ gets
+  // deprecated. Contents received in the current packet, especially used to
+  // identify whether the current packet is a padded PING packet.
   PacketContent current_packet_content_;
   // Set to true as soon as the packet currently being processed has been
   // detected as a connectivity probing.
@@ -2353,8 +2355,12 @@
 
   std::unique_ptr<MultiPortStats> multi_port_stats_;
 
+  // Client side only.
   bool active_migration_disabled_ = false;
 
+  const bool ignore_gquic_probing_ =
+      GetQuicReloadableFlag(quic_ignore_gquic_probing);
+
   RetransmittableOnWireBehavior retransmittable_on_wire_behavior_ = DEFAULT;
 
   // Server addresses that are known to the client.
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index bdfd034..12cea2f 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -1196,6 +1196,7 @@
           SerializePathChallengeConnectivityProbingPacket(&peer_creator_,
                                                           payload);
     }
+    QUICHE_DCHECK(!GetQuicReloadableFlag(quic_ignore_gquic_probing));
     return QuicPacketCreatorPeer::SerializeConnectivityProbingPacket(
         &peer_creator_);
   }
@@ -1620,6 +1621,7 @@
   ProcessFramePacketWithAddresses(MakeCryptoFrame(), self_address, kPeerAddress,
                                   ENCRYPTION_INITIAL);
   EXPECT_TRUE(connection_.connected());
+  EXPECT_NE(connection_.self_address(), self_address);
 }
 
 TEST_P(QuicConnectionTest, SelfAddressChangeAtServer) {
@@ -2401,6 +2403,10 @@
 }
 
 TEST_P(QuicConnectionTest, ReceivePathProbeWithNoAddressChangeAtServer) {
+  if (!version().HasIetfQuicFrames() &&
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
+    return;
+  }
   PathProbeTestInit(Perspective::IS_SERVER);
 
   EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
@@ -2569,11 +2575,13 @@
   QuicConnection* connection_;
 };
 
-// Receive a path probe request at the server side, i.e.,
-// in non-IETF version: receive a padded PING packet with a peer addess change;
-// in IETF version: receive a packet contains PATH CHALLENGE with peer address
-// change.
+// Receive a path probe request at the server side, in IETF version: receive a
+// packet contains PATH CHALLENGE with peer address change.
 TEST_P(QuicConnectionTest, ReceivePathProbingFromNewPeerAddressAtServer) {
+  if (!version().HasIetfQuicFrames() &&
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
+    return;
+  }
   PathProbeTestInit(Perspective::IS_SERVER);
 
   EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
@@ -2757,7 +2765,8 @@
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
   EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
-  if (GetParam().version.HasIetfQuicFrames()) {
+  if (GetParam().version.HasIetfQuicFrames() ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     // In IETF version, a padded PING packet with port change is not taken as
     // connectivity probe.
     EXPECT_CALL(visitor_, GetHandshakeState())
@@ -2790,7 +2799,8 @@
   ProcessFramesPacketWithAddresses(frames, kSelfAddress, kNewPeerAddress,
                                    ENCRYPTION_INITIAL);
 
-  if (GetParam().version.HasIetfQuicFrames()) {
+  if (GetParam().version.HasIetfQuicFrames() ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     // Padded PING with port changen is not considered as connectivity probe but
     // a PORT CHANGE.
     EXPECT_EQ(num_probing_received,
@@ -2804,11 +2814,11 @@
     EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
   }
 
-  if (GetParam().version.HasIetfQuicFrames()) {
+  if (GetParam().version.HasIetfQuicFrames() ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(1);
   }
-  // Process another packet with the old peer address on server side. gQUIC
-  // shouldn't regard this as a peer migration.
+  // Process another packet with the old peer address on server side.
   ProcessFramePacketWithAddresses(MakeCryptoFrame(), kSelfAddress, kPeerAddress,
                                   ENCRYPTION_INITIAL);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
@@ -2816,6 +2826,10 @@
 }
 
 TEST_P(QuicConnectionTest, ReceiveReorderedPathProbingAtServer) {
+  if (!GetParam().version.HasIetfQuicFrames() &&
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
+    return;
+  }
   PathProbeTestInit(Perspective::IS_SERVER);
 
   // Decrease packet number to simulate out-of-order packets.
@@ -2846,13 +2860,29 @@
       connection_.GetStats().num_connectivity_probing_received;
   ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
 
-  EXPECT_EQ(num_probing_received + 1,
+  EXPECT_EQ(num_probing_received +
+                (!version().HasIetfQuicFrames() &&
+                         GetQuicReloadableFlag(quic_ignore_gquic_probing)
+                     ? 0u
+                     : 1u),
             connection_.GetStats().num_connectivity_probing_received);
-  EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
+  EXPECT_EQ((!version().HasIetfQuicFrames() &&
+                     GetQuicReloadableFlag(quic_ignore_gquic_probing)
+                 ? kNewPeerAddress
+                 : kPeerAddress),
+            connection_.peer_address());
+  EXPECT_EQ((!version().HasIetfQuicFrames() &&
+                     GetQuicReloadableFlag(quic_ignore_gquic_probing)
+                 ? kNewPeerAddress
+                 : kPeerAddress),
+            connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
+  if (!GetParam().version.HasIetfQuicFrames() &&
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
+    return;
+  }
   PathProbeTestInit(Perspective::IS_SERVER);
 
   EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
@@ -2889,6 +2919,10 @@
 }
 
 TEST_P(QuicConnectionTest, ReceiveConnectivityProbingPacketAtClient) {
+  if (!version().HasIetfQuicFrames() &&
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
+    return;
+  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   PathProbeTestInit(Perspective::IS_CLIENT);
 
@@ -2913,10 +2947,8 @@
 }
 
 TEST_P(QuicConnectionTest, ReceiveConnectivityProbingResponseAtClient) {
-  // TODO(b/150095484): add test coverage for IETF to verify that client takes
-  // PATH RESPONSE with peer address change as correct validation on the new
-  // path.
-  if (GetParam().version.HasIetfQuicFrames()) {
+  if (GetParam().version.HasIetfQuicFrames() ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     return;
   }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -8696,6 +8728,10 @@
 
 TEST_P(QuicConnectionTest,
        RestartPathDegradingDetectionAfterMigrationWithProbe) {
+  if (!version().HasIetfQuicFrames() &&
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
+    return;
+  }
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   PathProbeTestInit(Perspective::IS_CLIENT);
 
@@ -8745,7 +8781,8 @@
         connection_.GetStats().num_connectivity_probing_received;
     ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received);
 
-    EXPECT_EQ(num_probing_received + 1,
+    EXPECT_EQ(num_probing_received +
+                  (GetQuicReloadableFlag(quic_ignore_gquic_probing) ? 0u : 1u),
               connection_.GetStats().num_connectivity_probing_received);
     EXPECT_EQ(kPeerAddress, connection_.peer_address());
     EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index f9ffb39..d28cb38 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -17,6 +17,8 @@
 QUIC_FLAG(quic_restart_flag_quic_testonly_default_true, true)
 // If trrue, early return before write control frame in OnCanWrite() if the connection is already closed.
 QUIC_FLAG(quic_reloadable_flag_quic_no_write_control_frame_upon_connection_close, true)
+// If true, QUIC server will not respond to gQUIC probing packet(PING + PADDING) but treat it as a regular packet.
+QUIC_FLAG(quic_reloadable_flag_quic_ignore_gquic_probing, false)
 // If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.
 QUIC_FLAG(quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
 // If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.
diff --git a/quiche/quic/core/quic_session.cc b/quiche/quic/core/quic_session.cc
index 0720fa1..e140bb4 100644
--- a/quiche/quic/core/quic_session.cc
+++ b/quiche/quic/core/quic_session.cc
@@ -488,6 +488,7 @@
 void QuicSession::OnPacketReceived(const QuicSocketAddress& /*self_address*/,
                                    const QuicSocketAddress& peer_address,
                                    bool is_connectivity_probe) {
+  QUICHE_DCHECK(!connection_->ignore_gquic_probing());
   if (is_connectivity_probe && perspective() == Perspective::IS_SERVER) {
     // Server only sends back a connectivity probe after received a
     // connectivity probe from a new peer address.
diff --git a/quiche/quic/core/quic_session_test.cc b/quiche/quic/core/quic_session_test.cc
index fd3ea97..3b90633 100644
--- a/quiche/quic/core/quic_session_test.cc
+++ b/quiche/quic/core/quic_session_test.cc
@@ -1458,7 +1458,8 @@
 // Test that server session will send a connectivity probe in response to a
 // connectivity probe on the same path.
 TEST_P(QuicSessionTestServer, ServerReplyToConnectivityProbe) {
-  if (VersionHasIetfQuicFrames(transport_version())) {
+  if (VersionHasIetfQuicFrames(transport_version()) ||
+      GetQuicReloadableFlag(quic_ignore_gquic_probing)) {
     return;
   }
   connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);