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)