In quic, add a connection option to enable more aggressive pto timeout before any rtt sample is available. not protected.
PiperOrigin-RevId: 317280920
Change-Id: Ia607d240d11d3365eef0518c76fb9d5e86c1d55e
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index fc7d363..c178aa2 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -233,6 +233,8 @@
// earliest in flight sent time
// and at least 1.5*srtt from
// last sent packet.
+const QuicTag kAPTO = TAG('A', 'P', 'T', 'O'); // Use 1.5 * initial RTT before
+ // any RTT sample is available.
const QuicTag kELDT = TAG('E', 'L', 'D', 'T'); // Enable Loss Detection Tuning
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index d74a487..eeeddf2 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -107,7 +107,8 @@
one_rtt_packet_acked_(false),
one_rtt_packet_sent_(false),
first_pto_srtt_multiplier_(0),
- use_standard_deviation_for_pto_(false) {
+ use_standard_deviation_for_pto_(false),
+ pto_multiplier_without_rtt_samples_(3) {
SetSendAlgorithm(congestion_control_type);
if (pto_enabled_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_on_pto, 1, 2);
@@ -197,6 +198,9 @@
} else if (config.HasClientSentConnectionOption(kPLE2, perspective)) {
first_pto_srtt_multiplier_ = 1.5;
}
+ if (config.HasClientSentConnectionOption(kAPTO, perspective)) {
+ pto_multiplier_without_rtt_samples_ = 1.5;
+ }
if (config.HasClientSentConnectionOption(kPSDA, perspective)) {
use_standard_deviation_for_pto_ = true;
rtt_stats_.EnableStandardDeviationCalculation();
@@ -1230,8 +1234,9 @@
if (rtt_stats_.smoothed_rtt().IsZero()) {
// Respect kMinHandshakeTimeoutMs to avoid a potential amplification attack.
QUIC_BUG_IF(rtt_stats_.initial_rtt().IsZero());
- return std::max(3 * rtt_stats_.initial_rtt(),
- QuicTime::Delta::FromMilliseconds(kMinHandshakeTimeoutMs)) *
+ return std::max(
+ pto_multiplier_without_rtt_samples_ * rtt_stats_.initial_rtt(),
+ QuicTime::Delta::FromMilliseconds(kMinHandshakeTimeoutMs)) *
(1 << consecutive_pto_count_);
}
const QuicTime::Delta rtt_var = use_standard_deviation_for_pto_
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index af32eba..ca43d3d 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -658,6 +658,10 @@
// If true, use standard deviation (instead of mean deviation) when
// calculating PTO timeout.
bool use_standard_deviation_for_pto_;
+
+ // The multiplier for caculating PTO timeout before any RTT sample is
+ // available.
+ float pto_multiplier_without_rtt_samples_;
};
} // namespace quic
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index 90c7e15..33b2470 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -4096,6 +4096,30 @@
manager_.GetRetransmissionTime());
}
+TEST_F(QuicSentPacketManagerTest,
+ AggressivePtoBeforeAnyRttSamplesAreAvailable) {
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+ 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());
+
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kAPTO);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ manager_.SetFromConfig(config);
+
+ // Send INITIAL 1.
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ // Verify retransmission timeout is expected.
+ EXPECT_EQ(clock_.Now() + 1.5 * rtt_stats->initial_rtt(),
+ manager_.GetRetransmissionTime());
+}
+
} // namespace
} // namespace test
} // namespace quic