Let QuicReceivedPacketManager trim ack ranges when packet is received, instead of when sending acks.

Protected by FLAGS_quic_rpm_trim_ack_ranges_early.

PiperOrigin-RevId: 547664172
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 072b449..0d8d539 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -27,6 +27,8 @@
 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.
 QUIC_FLAG(quic_restart_flag_quic_support_release_time_for_gso, false)
+// If true, QuicReceivedPacketManager will trim ack ranges when packet is received.
+QUIC_FLAG(quic_reloadable_flag_quic_rpm_trim_ack_ranges_early, true)
 // If true, ack frequency frame can be sent from server to client.
 QUIC_FLAG(quic_reloadable_flag_quic_can_send_ack_frequency, true)
 // If true, allow client to enable BBRv2 on server via connection option \'B2ON\'.
diff --git a/quiche/quic/core/quic_received_packet_manager.cc b/quiche/quic/core/quic_received_packet_manager.cc
index 6b566f4..b941e8c 100644
--- a/quiche/quic/core/quic_received_packet_manager.cc
+++ b/quiche/quic/core/quic_received_packet_manager.cc
@@ -14,6 +14,7 @@
 #include "quiche/quic/core/quic_connection_stats.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/platform/api/quic_bug_tracker.h"
+#include "quiche/quic/platform/api/quic_flag_utils.h"
 #include "quiche/quic/platform/api/quic_flags.h"
 #include "quiche/quic/platform/api/quic_logging.h"
 
@@ -104,6 +105,7 @@
     time_largest_observed_ = receipt_time;
   }
   ack_frame_.packets.Add(packet_number);
+  MaybeTrimAckRanges();
 
   if (save_timestamps_) {
     // The timestamp format only handles packets in time order.
@@ -151,6 +153,19 @@
   }
 }
 
+void QuicReceivedPacketManager::MaybeTrimAckRanges() {
+  if (!trim_ack_ranges_early_) {
+    return;
+  }
+
+  QUIC_RELOADABLE_FLAG_COUNT_N(quic_rpm_trim_ack_ranges_early, 1, 2);
+  while (max_ack_ranges_ > 0 &&
+         ack_frame_.packets.NumIntervals() > max_ack_ranges_) {
+    QUIC_RELOADABLE_FLAG_COUNT_N(quic_rpm_trim_ack_ranges_early, 2, 2);
+    ack_frame_.packets.RemoveSmallestInterval();
+  }
+}
+
 bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) {
   return LargestAcked(ack_frame_).IsInitialized() &&
          packet_number < LargestAcked(ack_frame_) &&
diff --git a/quiche/quic/core/quic_received_packet_manager.h b/quiche/quic/core/quic_received_packet_manager.h
index 0f80865..79e55af 100644
--- a/quiche/quic/core/quic_received_packet_manager.h
+++ b/quiche/quic/core/quic_received_packet_manager.h
@@ -145,6 +145,8 @@
     return last_ack_frequency_frame_sequence_number_ >= 0;
   }
 
+  void MaybeTrimAckRanges();
+
   // Least packet number of the the packet sent by the peer for which it
   // hasn't received an ack.
   QuicPacketNumber peer_least_packet_awaiting_ack_;
@@ -204,6 +206,9 @@
   // Whether the most recent packet was missing before it was received.
   bool was_last_packet_missing_;
 
+  const bool trim_ack_ranges_early_ =
+      GetQuicReloadableFlag(quic_rpm_trim_ack_ranges_early);
+
   // Last sent largest acked, which gets updated when ACK was successfully sent.
   QuicPacketNumber last_sent_largest_acked_;
 
diff --git a/quiche/quic/core/quic_received_packet_manager_test.cc b/quiche/quic/core/quic_received_packet_manager_test.cc
index b3bc9b7..b1d46db 100644
--- a/quiche/quic/core/quic_received_packet_manager_test.cc
+++ b/quiche/quic/core/quic_received_packet_manager_test.cc
@@ -184,6 +184,21 @@
   }
 }
 
+TEST_F(QuicReceivedPacketManagerTest, TrimAckRangesEarly) {
+  const size_t kMaxAckRanges = 10;
+  received_manager_.set_max_ack_ranges(kMaxAckRanges);
+  for (size_t i = 0; i < kMaxAckRanges + 10; ++i) {
+    RecordPacketReceipt(1 + 2 * i);
+    if (i < kMaxAckRanges ||
+        !GetQuicReloadableFlag(quic_rpm_trim_ack_ranges_early)) {
+      EXPECT_EQ(i + 1, received_manager_.ack_frame().packets.NumIntervals());
+    } else {
+      EXPECT_EQ(kMaxAckRanges,
+                received_manager_.ack_frame().packets.NumIntervals());
+    }
+  }
+}
+
 TEST_F(QuicReceivedPacketManagerTest, IgnoreOutOfOrderTimestamps) {
   EXPECT_FALSE(received_manager_.ack_frame_updated());
   RecordPacketReceipt(1, QuicTime::Zero());