Do not use PING only packet for RTT measure or congestion control. Client only and behind IGNP config.
PiperOrigin-RevId: 343891727
Change-Id: I814dc2623ea6533fe36ed73d9d69c09392a63d36
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 96c1be1..8093a68 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -396,6 +396,10 @@
const QuicTag kMAD = TAG('M', 'A', 'D', 0); // Max Ack Delay (IETF QUIC)
+const QuicTag kIGNP = TAG('I', 'G', 'N', 'P'); // Do not use PING only packet
+ // for RTT measure or
+ // congestion control.
+
// Rejection tags
const QuicTag kRREJ = TAG('R', 'R', 'E', 'J'); // Reasons for server sending
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index c823582..fba8b67 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -116,7 +116,8 @@
first_pto_srtt_multiplier_(0),
use_standard_deviation_for_pto_(false),
pto_multiplier_without_rtt_samples_(3),
- num_ptos_for_path_degrading_(0) {
+ num_ptos_for_path_degrading_(0),
+ ignore_pings_(false) {
SetSendAlgorithm(congestion_control_type);
if (pto_enabled_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_on_pto, 1, 2);
@@ -276,6 +277,10 @@
send_algorithm_->SetInitialCongestionWindowInPackets(10);
}
+ if (config.HasClientRequestedIndependentOption(kIGNP, perspective)) {
+ ignore_pings_ = true;
+ }
+
using_pacing_ = !GetQuicFlag(FLAGS_quic_disable_pacing_for_perf_tests);
if (config.HasClientSentConnectionOption(kNTLP, perspective)) {
@@ -798,6 +803,12 @@
}
bool in_flight = has_retransmittable_data == HAS_RETRANSMITTABLE_DATA;
+ if (ignore_pings_ && mutable_packet->retransmittable_frames.size() == 1 &&
+ mutable_packet->retransmittable_frames[0].type == PING_FRAME) {
+ // Dot not use PING only packet for RTT measure or congestion control.
+ in_flight = false;
+ measure_rtt = false;
+ }
if (using_pacing_) {
pacing_sender_.OnPacketSent(sent_time, unacked_packets_.bytes_in_flight(),
packet_number, packet.encrypted_length,
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index f6a6fa8..2dba799 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -736,6 +736,10 @@
// The number of PTOs needed for path degrading alarm. If equals to 0, the
// traditional path degrading mechanism will be used.
int num_ptos_for_path_degrading_;
+
+ // If true, do not use PING only packets for RTT measurement or congestion
+ // control.
+ bool ignore_pings_;
};
} // namespace quic
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index 4ef1664..1aa4974 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -3882,6 +3882,55 @@
EXPECT_EQ(expected_delay, manager_.GetPathDegradingDelay());
}
+TEST_F(QuicSentPacketManagerTest, ClientsIgnorePings) {
+ QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);
+ QuicConfig client_config;
+ QuicTagVector options;
+ QuicTagVector client_options;
+ client_options.push_back(kIGNP);
+ client_config.SetConnectionOptionsToSend(options);
+ client_config.SetClientConnectionOptions(client_options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(client_config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+
+ SendPingPacket(1, ENCRYPTION_INITIAL);
+ // Verify PING only packet is not considered in flight.
+ EXPECT_EQ(QuicTime::Zero(), manager_.GetRetransmissionTime());
+ SendDataPacket(2, ENCRYPTION_INITIAL);
+ EXPECT_NE(QuicTime::Zero(), manager_.GetRetransmissionTime());
+
+ uint64_t acked[] = {1};
+ ExpectAcksAndLosses(/*rtt_updated=*/false, acked, ABSL_ARRAYSIZE(acked),
+ nullptr, 0);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(90));
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_INITIAL));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ // Verify no RTT samples for PING only packet.
+ EXPECT_TRUE(rtt_stats->smoothed_rtt().IsZero());
+
+ ExpectAck(2);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
+ ENCRYPTION_INITIAL));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(100), rtt_stats->smoothed_rtt());
+}
+
// Regression test for b/154050235.
TEST_F(QuicSentPacketManagerTest, ExponentialBackoffWithNoRttMeasurement) {
QuicSentPacketManagerPeer::SetPerspective(&manager_, Perspective::IS_CLIENT);