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