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)