Handle PINGs in QUIC connection.
Currently, sending and retransmission of PINGs are handled by control frame manager (and session).
Protected by FLAGS_quic_reloadable_flag_quic_let_connection_handle_pings.
PiperOrigin-RevId: 335072367
Change-Id: I79f20404656beee3d9404c1ccaa8ef2f00af567c
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index b18b367..06488e5 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -4024,7 +4024,11 @@
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Simulate firing of the retransmittable on wire and send a PING.
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
clock_.AdvanceTime(retransmittable_on_wire_timeout);
connection_.GetPingAlarm()->Fire();
@@ -4038,13 +4042,21 @@
QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs);
srtt = manager_->GetRttStats()->SmoothedOrInitialRtt();
- // First TLP without unacked stream data will no longer use TLPR.
- expected_delay = std::max(2 * srtt, 1.5 * srtt + 0.5 * min_rto_timeout);
+ if (GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ // Arm RTO mode since there is only PING in flight.
+ expected_delay = manager_->GetPtoDelay();
+ } else {
+ // First TLP without unacked stream data will no longer use TLPR.
+ expected_delay = std::max(2 * srtt, 1.5 * srtt + 0.5 * min_rto_timeout);
+ }
EXPECT_EQ(expected_delay,
connection_.GetRetransmissionAlarm()->deadline() - clock_.Now());
// Verify the path degrading delay = TLP delay + 1st RTO + 2nd RTO.
// Add 1st RTO.
+ if (GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ expected_delay = std::max(2 * srtt, 1.5 * srtt + 0.5 * min_rto_timeout);
+ }
retransmission_delay =
std::max(manager_->GetRttStats()->smoothed_rtt() +
4 * manager_->GetRttStats()->mean_deviation(),
@@ -4071,7 +4083,12 @@
// Verify the retransmission delay.
// First TLP without unacked stream data will no longer use TLPR.
- expected_delay = std::max(2 * srtt, 1.5 * srtt + 0.5 * min_rto_timeout);
+ if (GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ // Arm RTO mode since there is only PING in flight.
+ expected_delay = manager_->GetPtoDelay();
+ } else {
+ expected_delay = std::max(2 * srtt, 1.5 * srtt + 0.5 * min_rto_timeout);
+ }
expected_delay = expected_delay - QuicTime::Delta::FromMilliseconds(5);
EXPECT_EQ(expected_delay,
connection_.GetRetransmissionAlarm()->deadline() - clock_.Now());
@@ -4597,7 +4614,11 @@
writer_->Reset();
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(15));
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
connection_.GetPingAlarm()->Fire();
size_t padding_frame_count = writer_->padding_frames().size();
EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
@@ -4651,9 +4672,11 @@
writer_->Reset();
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ }
connection_.GetPingAlarm()->Fire();
size_t padding_frame_count = writer_->padding_frames().size();
EXPECT_EQ(padding_frame_count + 1u, writer_->frame_count());
@@ -7159,9 +7182,11 @@
// Simulate firing the ping alarm and sending a PING.
clock_.AdvanceTime(retransmittable_on_wire_timeout);
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ }
connection_.GetPingAlarm()->Fire();
// Now there's a retransmittable packet (PING) on the wire, so the path
@@ -7862,9 +7887,11 @@
EXPECT_EQ(prev_deadline, connection_.GetPingAlarm()->deadline());
// Simulate the alarm firing and check that a PING is sent.
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ }
connection_.GetPingAlarm()->Fire();
size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
@@ -7935,9 +7962,11 @@
// Simulate the alarm firing and check that a PING is sent.
writer_->Reset();
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
- }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ connection_.SendControlFrame(QuicFrame(QuicPingFrame(1)));
+ }));
+ }
connection_.GetPingAlarm()->Fire();
size_t padding_frame_count = writer_->padding_frames().size();
if (GetParam().no_stop_waiting) {
@@ -7997,9 +8026,11 @@
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Simulate the alarm firing and check that a PING is sent.
writer_->Reset();
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- SendPing();
- }));
+ 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();
}
@@ -8024,9 +8055,11 @@
// Simulate the alarm firing and check that a PING is sent.
writer_->Reset();
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- SendPing();
- }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
clock_.AdvanceTime(retransmittable_on_wire_timeout);
connection_.GetPingAlarm()->Fire();
}
@@ -8092,7 +8125,11 @@
// Simulate the alarm firing and check that a PING is sent.
writer_->Reset();
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ 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();
@@ -8128,9 +8165,11 @@
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
// Simulate the alarm firing and check that a PING is sent.
writer_->Reset();
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
- SendPing();
- }));
+ 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();
// Advance 5ms to receive next packet.
@@ -8148,7 +8187,11 @@
connection_.GetPingAlarm()->deadline() - clock_.ApproximateNow());
writer_->Reset();
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
clock_.AdvanceTime(2 * initial_retransmittable_on_wire_timeout);
connection_.GetPingAlarm()->Fire();
@@ -9110,7 +9153,11 @@
// RTO fires, verify a PING packet gets sent because there is no data to send.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(3), _, _));
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
clock_.AdvanceTime(retransmission_time - clock_.Now());
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(1u, connection_.GetStats().tlp_count);
@@ -9330,7 +9377,11 @@
? QuicPacketNumber(2)
: QuicPacketNumber(3),
_, _));
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(1u, connection_.GetStats().pto_count);
EXPECT_EQ(1u, connection_.GetStats().crypto_retransmit_count);
@@ -9627,7 +9678,11 @@
// Fires TLP, verify a PING gets sent because packet 3 is marked
// RTO_RETRANSMITTED.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(70), _, _));
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
connection_.GetRetransmissionAlarm()->Fire();
}
@@ -10218,7 +10273,11 @@
// PTO fires, verify a PING packet gets sent because there is no data to
// send.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(3), _, _));
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(1u, connection_.GetStats().pto_count);
EXPECT_EQ(0u, connection_.GetStats().crypto_retransmit_count);
@@ -11003,7 +11062,11 @@
EXPECT_CALL(visitor_, ShouldKeepConnectionAlive())
.WillRepeatedly(Return(false));
// Verify PING does not get sent.
- EXPECT_CALL(visitor_, SendPing()).Times(0);
+ if (GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ } else {
+ EXPECT_CALL(visitor_, SendPing()).Times(0);
+ }
connection_.GetPingAlarm()->Fire();
}
@@ -11581,6 +11644,10 @@
if (!GetQuicReloadableFlag(quic_fix_missing_initial_keys2)) {
EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(1);
}
+ } else if (GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ if (!GetQuicReloadableFlag(quic_fix_missing_initial_keys2)) {
+ EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(1);
+ }
} else {
EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(0);
EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
@@ -11592,10 +11659,15 @@
// Verify a handshake packet gets PTOed and 1-RTT packet gets coalesced.
EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
} else {
- // Verify an 1-RTT PING gets sent because there is nothing to PTO, bummer,
- // since this 1-RTT PING cannot be processed by peer and there is a
- // deadlock.
- EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
+ if (GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ // Verify PING is sent in the right encryption level.
+ EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+ } else {
+ // Verify an 1-RTT PING gets sent because there is nothing to PTO, bummer,
+ // since this 1-RTT PING cannot be processed by peer and there is a
+ // deadlock.
+ EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
+ }
EXPECT_FALSE(writer_->ping_frames().empty());
}
}
@@ -11684,7 +11756,11 @@
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
// Fire retransmission alarm.
- EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() { SendPing(); }));
+ if (!GetQuicReloadableFlag(quic_let_connection_handle_pings)) {
+ EXPECT_CALL(visitor_, SendPing()).WillOnce(Invoke([this]() {
+ SendPing();
+ }));
+ }
connection_.GetRetransmissionAlarm()->Fire();
QuicFrames frames1;