Close QUIC connection with QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS when unacked map exceeds a threshold.

Currently QUIC connection is closed with this error code when (largest acked - least unacked) exceeds the threshold.

Protected by FLAGS_quic_reloadable_flag_quic_close_connection_with_too_many_outstanding_packets.

PiperOrigin-RevId: 353950850
Change-Id: Ic72fec026dc80e7217022c701fff8cf35dbe23bb
diff --git a/quic/core/congestion_control/bbr2_simulator_test.cc b/quic/core/congestion_control/bbr2_simulator_test.cc
index bebe710..489a958 100644
--- a/quic/core/congestion_control/bbr2_simulator_test.cc
+++ b/quic/core/congestion_control/bbr2_simulator_test.cc
@@ -125,6 +125,9 @@
     // Enable this for all tests because it moves where cwnd and pacing gain
     // are initialized.
     SetQuicReloadableFlag(quic_bbr2_bw_startup, true);
+    // Prevent the server(receiver), which only sends acks, from closing
+    // connection due to too many outstanding packets.
+    SetQuicFlag(FLAGS_quic_max_tracked_packet_count, 1000000);
   }
 
   void SetUp() override {
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index d2899ee..5c14542 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -2140,11 +2140,24 @@
 }
 
 void QuicConnection::CloseIfTooManyOutstandingSentPackets() {
+  bool should_close;
+  if (GetQuicReloadableFlag(
+          quic_close_connection_with_too_many_outstanding_packets)) {
+    QUIC_RELOADABLE_FLAG_COUNT(
+        quic_close_connection_with_too_many_outstanding_packets);
+    should_close =
+        sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
+        sent_packet_manager_.GetLargestSentPacket() >
+            sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_;
+  } else {
+    should_close =
+        sent_packet_manager_.GetLargestObserved().IsInitialized() &&
+        sent_packet_manager_.GetLargestObserved() >
+            sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_;
+  }
   // This occurs if we don't discard old packets we've seen fast enough. It's
   // possible largest observed is less than leaset unacked.
-  if (sent_packet_manager_.GetLargestObserved().IsInitialized() &&
-      sent_packet_manager_.GetLargestObserved() >
-          sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) {
+  if (should_close) {
     CloseConnection(
         QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
         absl::StrCat("More than ", max_tracked_packets_,
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 0c9f75c..1851c31 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -2844,14 +2844,25 @@
     SendStreamDataToPeer(1, "foo", 3 * i, NO_FIN, nullptr);
   }
 
-  // Ack packet 1, which leaves more than the limit outstanding.
-  EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
   EXPECT_CALL(visitor_,
               OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF));
 
-  // Nack the first packet and ack the rest, leaving a huge gap.
-  QuicAckFrame frame1 = ConstructAckFrame(num_packets, 1);
-  ProcessAckPacket(&frame1);
+  ProcessFramePacket(QuicFrame(QuicPingFrame()));
+
+  if (!GetQuicReloadableFlag(
+          quic_close_connection_with_too_many_outstanding_packets)) {
+    // When the flag is false, the ping packet processed above shouldn't cause
+    // the connection to close. But the ack packet below will.
+    EXPECT_TRUE(connection_.connected());
+
+    // Ack packet 1, which leaves more than the limit outstanding.
+    EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
+
+    // Nack the first packet and ack the rest, leaving a huge gap.
+    QuicAckFrame frame1 = ConstructAckFrame(num_packets, 1);
+    ProcessAckPacket(&frame1);
+  }
+
   TestConnectionCloseQuicErrorCode(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS);
 }
 
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 8ff6bd6..53b4e40 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -19,6 +19,7 @@
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_use_bytes_delivered, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, true)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_on_0rtt_packet_number_higher_than_1rtt, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_close_connection_with_too_many_outstanding_packets, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
 QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_count_bytes_on_alternative_path_seperately, false)