Reduce number of packets sent by ROWP
This CL changes our default ROWP behavior to start the exponential backoff after 10 packets instead of 200, and also adds a connection-lifetime cap on ROWP to disable ROWP after 1000 ROWPs have been sent.
PiperOrigin-RevId: 338078574
Change-Id: If025717bf5b509c6bbbfb3dec34a928dfdeec7d5
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index fa02801..1e59d4f 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -285,6 +285,7 @@
ping_timeout_(QuicTime::Delta::FromSeconds(kPingTimeoutSecs)),
initial_retransmittable_on_wire_timeout_(QuicTime::Delta::Infinite()),
consecutive_retransmittable_on_wire_ping_count_(0),
+ retransmittable_on_wire_ping_count_(0),
arena_(),
ack_alarm_(alarm_factory_->CreateAlarm(arena_.New<AckAlarmDelegate>(this),
&arena_)),
@@ -4054,7 +4055,9 @@
return;
}
if (initial_retransmittable_on_wire_timeout_.IsInfinite() ||
- sent_packet_manager_.HasInFlightPackets()) {
+ sent_packet_manager_.HasInFlightPackets() ||
+ retransmittable_on_wire_ping_count_ >
+ GetQuicFlag(FLAGS_quic_max_retransmittable_on_wire_ping_count)) {
// Extend the ping alarm.
ping_alarm_->Update(clock_->ApproximateNow() + ping_timeout_,
QuicTime::Delta::FromSeconds(1));
@@ -4090,6 +4093,7 @@
if (max_aggressive_retransmittable_on_wire_ping_count != 0) {
consecutive_retransmittable_on_wire_ping_count_++;
}
+ retransmittable_on_wire_ping_count_++;
return;
}
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 4be1b96..59fa80d 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -526,6 +526,10 @@
QuicConnectionStats& mutable_stats() { return stats_; }
+ int retransmittable_on_wire_ping_count() const {
+ return retransmittable_on_wire_ping_count_;
+ }
+
// Returns statistics tracked for this connection.
const QuicConnectionStats& GetStats();
@@ -1651,6 +1655,9 @@
// receiving any new data in between.
int consecutive_retransmittable_on_wire_ping_count_;
+ // Indicates how many retransmittable-on-wire pings have been emitted.
+ int retransmittable_on_wire_ping_count_;
+
// Arena to store class implementations within the QuicConnection.
QuicConnectionArena arena_;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 433ba74..7d736b3 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -8251,6 +8251,75 @@
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
}
+// Make sure that we never send more retransmissible on the wire pings than
+// the limit in FLAGS_quic_max_retransmittable_on_wire_ping_count.
+TEST_P(QuicConnectionTest, RetransmittableOnWirePingLimit) {
+ static constexpr int kMaxRetransmittableOnWirePingCount = 3;
+ SetQuicFlag(FLAGS_quic_max_retransmittable_on_wire_ping_count,
+ kMaxRetransmittableOnWirePingCount);
+ static constexpr QuicTime::Delta initial_retransmittable_on_wire_timeout =
+ QuicTime::Delta::FromMilliseconds(200);
+ static constexpr QuicTime::Delta short_delay =
+ QuicTime::Delta::FromMilliseconds(5);
+ ASSERT_LT(short_delay * 10, initial_retransmittable_on_wire_timeout);
+ connection_.set_initial_retransmittable_on_wire_timeout(
+ initial_retransmittable_on_wire_timeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+ .WillRepeatedly(Return(true));
+
+ const char data[] = "data";
+ // Advance 5ms, send a retransmittable data packet to the peer.
+ clock_.AdvanceTime(short_delay);
+ EXPECT_FALSE(connection_.GetPingAlarm()->IsSet());
+ connection_.SendStreamDataWithString(1, data, 0, NO_FIN);
+ EXPECT_TRUE(connection_.sent_packet_manager().HasInFlightPackets());
+ // The ping alarm is set for the ping timeout, not the shorter
+ // retransmittable_on_wire_timeout.
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(connection_.ping_timeout(),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _))
+ .Times(AnyNumber());
+
+ // Verify that the first few consecutive retransmittable on wire pings are
+ // sent with aggressive timeout.
+ for (int i = 0; i <= kMaxRetransmittableOnWirePingCount; i++) {
+ // Receive an ACK of the previous packet. This should set the ping alarm
+ // with the initial retransmittable-on-wire timeout.
+ clock_.AdvanceTime(short_delay);
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(initial_retransmittable_on_wire_timeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
+ clock_.AdvanceTime(initial_retransmittable_on_wire_timeout);
+ connection_.GetPingAlarm()->Fire();
+ }
+
+ // Receive an ACK of the previous packet. This should set the ping alarm
+ // but this time with the default ping timeout.
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(connection_.ping_timeout(),
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+}
+
TEST_P(QuicConnectionTest, ValidStatelessResetToken) {
const QuicUint128 kTestToken = 1010101;
const QuicUint128 kWrongTestToken = 1010100;