gfe-relnote: In QUIC, add a connection option to make first n PTOs more aggressive (i.e., 2 * srtt) when calculating PTO timeout. Protected by existing gfe2_reloadable_flag_quic_enable_pto.
PiperOrigin-RevId: 288538935
Change-Id: Ieee2bfa5035a42da104107ed7a36b4e4275d0bf6
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index 8e2fc68..7e8e3e7 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -3201,6 +3201,118 @@
manager_.OnRetransmissionTimeout();
}
+TEST_F(QuicSentPacketManagerTest, Aggressive1Pto) {
+ EnablePto(k1PTO);
+ // Let the first PTO be aggressive.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPAG1);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay = 2 * srtt;
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+
+ // Verify PTO period gets set correctly.
+ QuicTime sent_time = clock_.Now();
+ expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+ EXPECT_EQ(sent_time + expected_pto_delay * 2,
+ manager_.GetRetransmissionTime());
+}
+
+TEST_F(QuicSentPacketManagerTest, Aggressive2Ptos) {
+ EnablePto(k1PTO);
+ // Let the first PTO be aggressive.
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kPTOS);
+ options.push_back(kPAG2);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ EXPECT_CALL(*send_algorithm_, PacingRate(_))
+ .WillRepeatedly(Return(QuicBandwidth::Zero()));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ RttStats* rtt_stats = const_cast<RttStats*>(manager_.GetRttStats());
+ rtt_stats->UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), QuicTime::Zero());
+ QuicTime::Delta srtt = rtt_stats->smoothed_rtt();
+ SendDataPacket(1, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO is correctly set.
+ QuicTime::Delta expected_pto_delay = 2 * srtt;
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(1u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(3, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+
+ // Verify PTO period gets set correctly.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay,
+ manager_.GetRetransmissionTime());
+
+ // Invoke 2nd PTO.
+ clock_.AdvanceTime(expected_pto_delay);
+ manager_.OnRetransmissionTimeout();
+ EXPECT_EQ(QuicTime::Delta::Zero(), manager_.TimeUntilSend(clock_.Now()));
+ EXPECT_EQ(2u, stats_.pto_count);
+
+ // Verify 1 probe packets get sent and packet number gets skipped.
+ EXPECT_CALL(notifier_, RetransmitFrames(_, _))
+ .WillOnce(WithArgs<1>(Invoke([this](TransmissionType type) {
+ RetransmitDataPacket(5, type, ENCRYPTION_FORWARD_SECURE);
+ })));
+ manager_.MaybeSendProbePackets();
+ expected_pto_delay =
+ srtt + 4 * rtt_stats->mean_deviation() +
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
+
+ // Verify PTO period gets set correctly.
+ EXPECT_EQ(clock_.Now() + expected_pto_delay * 4,
+ manager_.GetRetransmissionTime());
+}
+
} // namespace
} // namespace test
} // namespace quic