Remove DCHECK in QuicPingManager.
This change allows the `retransmittable_on_wire_timeout` to be effectively disabled, which is necessary for conducting specific QUIC experiments.
Currently, if `retransmittable_on_wire_timeout_` is set to 0, Chromium overwrites the value to 200ms in `quic_session_pool.cc`. This behavior prevents us from setting a value greater than keep_alive_timeout_ and thus disabling the retransmittable on wire timeout.
https://source.chromium.org/chromium/chromium/src/+/main:net/quic/quic_session_pool.cc;l=2234-2237;drc=2e7604d8aa7dd54f8f4b60c1a1af66c6fbc427fe
This change modifies the logic to permit `retransmittable_on_wire_timeout_` to be set to a value that will always be greater than the keep_alive_timeout_. As a result, `GetEarliestDeadline()` will consistently return keep_alive_deadline_ as the deadline, allowing us to disable the retransmittable_on_wire_timeout for experimental purposes.
PiperOrigin-RevId: 803221973
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index ee93bb0..6e819ff 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -8585,6 +8585,55 @@
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
}
+TEST_P(QuicConnectionTest, RetransmittableOnWireTimeoutGreaterThanPingTimeout) {
+ static constexpr QuicTime::Delta kInitialRetransmittableOnWireTimeout =
+ QuicTime::Delta::FromSeconds(300);
+ static constexpr auto kPingTimeout =
+ QuicTime::Delta::FromSeconds(kPingTimeoutSecs);
+
+ connection_.set_initial_retransmittable_on_wire_timeout(
+ kInitialRetransmittableOnWireTimeout);
+
+ EXPECT_TRUE(connection_.connected());
+ EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
+ .WillRepeatedly(Return(true));
+ // Send a data packet to the peer
+ 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
+ // retransmittable_on_wire_timeout.
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(kPingTimeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _, _, _))
+ .Times(AnyNumber());
+
+ // Receive an ACK of the first packet. Verify there are no in flight packets.
+ // This should still set the ping alarm with kPingTimeout since
+ // retransmittable_on_wire_timeout is greater than kPingTimeout.
+ QUICHE_DCHECK_GT(kInitialRetransmittableOnWireTimeout, kPingTimeout);
+ {
+ QuicPacketNumber ack_num = creator_->packet_number();
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(ack_num), QuicPacketNumber(ack_num + 1)}});
+ ProcessAckPacket(&frame);
+ EXPECT_FALSE(connection_.sent_packet_manager().HasInFlightPackets());
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+ EXPECT_EQ(kPingTimeout,
+ connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
+ }
+ // Simulate the alarm firing and check that a PING is sent.
+ writer_->Reset();
+ clock_.AdvanceTime(kPingTimeout);
+ connection_.GetPingAlarm()->Fire();
+
+ // The ping alarm is set with default ping timeout.
+ EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
+}
+
// Make sure when enabled, the retransmittable on wire timeout is based on the
// PTO.
TEST_P(QuicConnectionTest, PtoBasedRetransmittableOnWireTimeout) {
diff --git a/quiche/quic/core/quic_ping_manager.cc b/quiche/quic/core/quic_ping_manager.cc
index 52a5cd4..7797a35 100644
--- a/quiche/quic/core/quic_ping_manager.cc
+++ b/quiche/quic/core/quic_ping_manager.cc
@@ -115,8 +115,6 @@
static_cast<int>(num_ptos_for_retransmittable_on_wire_timeout_) *
pto_delay;
} else {
- QUICHE_DCHECK_LT(initial_retransmittable_on_wire_timeout_,
- keep_alive_timeout_);
retransmittable_on_wire_timeout = initial_retransmittable_on_wire_timeout_;
}
diff --git a/quiche/quic/core/quic_ping_manager_test.cc b/quiche/quic/core/quic_ping_manager_test.cc
index 0ab3331..7db8dcd 100644
--- a/quiche/quic/core/quic_ping_manager_test.cc
+++ b/quiche/quic/core/quic_ping_manager_test.cc
@@ -534,6 +534,39 @@
}
}
+TEST_F(QuicPingManagerTest,
+ SetAlarmAgnosticToRelativeSizeOfKeepAliveTimeoutVsROWTimeout) {
+ struct TestCase {
+ QuicTime::Delta retransmittable_on_wire_timeout;
+ QuicTime::Delta keep_alive_timeout;
+ };
+ static constexpr TestCase kTestCases[] = {
+ {QuicTime::Delta::FromSeconds(3), QuicTime::Delta::FromSeconds(4)},
+ {QuicTime::Delta::FromSeconds(6), QuicTime::Delta::FromSeconds(5)},
+ {QuicTime::Delta::FromSeconds(7), QuicTime::Delta::FromSeconds(7)}};
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(testing::Message()
+ << "retransmittable_on_wire_timeout: "
+ << test_case.retransmittable_on_wire_timeout
+ << ", keep_alive_timeout: " << test_case.keep_alive_timeout);
+ manager_.Stop();
+ alarm_->Cancel();
+ EXPECT_FALSE(alarm_->IsSet());
+
+ manager_.set_initial_retransmittable_on_wire_timeout(
+ test_case.retransmittable_on_wire_timeout);
+ manager_.set_keep_alive_timeout(test_case.keep_alive_timeout);
+
+ manager_.SetAlarm(clock_.ApproximateNow(), kShouldKeepAlive,
+ /*has_in_flight_packets=*/false, kPtoDelay);
+ EXPECT_TRUE(alarm_->IsSet());
+
+ EXPECT_EQ(alarm_->deadline() - clock_.ApproximateNow(),
+ std::min(test_case.retransmittable_on_wire_timeout,
+ test_case.keep_alive_timeout));
+ }
+}
+
} // namespace
} // namespace test