Use a smaller lower bound(5ms) to clamp the initial rtt, when setting initial rtt from a trusted value. Currently only the min_rtt from CachedNetworkParameters is considered trusted.
Protected by FLAGS_quic_reloadable_flag_quic_use_lower_min_for_trusted_irtt.
PiperOrigin-RevId: 431821410
diff --git a/quic/core/congestion_control/send_algorithm_interface.h b/quic/core/congestion_control/send_algorithm_interface.h
index 4271603..3135f21 100644
--- a/quic/core/congestion_control/send_algorithm_interface.h
+++ b/quic/core/congestion_control/send_algorithm_interface.h
@@ -34,8 +34,7 @@
// Network Params for AdjustNetworkParameters.
struct QUIC_NO_EXPORT NetworkParams {
NetworkParams() = default;
- NetworkParams(const QuicBandwidth& bandwidth,
- const QuicTime::Delta& rtt,
+ NetworkParams(const QuicBandwidth& bandwidth, const QuicTime::Delta& rtt,
bool allow_cwnd_to_decrease)
: bandwidth(bandwidth),
rtt(rtt),
@@ -47,7 +46,8 @@
max_initial_congestion_window ==
other.max_initial_congestion_window &&
burst_token == other.burst_token &&
- allow_cwnd_to_decrease == other.allow_cwnd_to_decrease;
+ allow_cwnd_to_decrease == other.allow_cwnd_to_decrease &&
+ is_rtt_trusted == other.is_rtt_trusted;
}
QuicBandwidth bandwidth = QuicBandwidth::Zero();
@@ -55,6 +55,7 @@
int max_initial_congestion_window = 0;
int burst_token = 0;
bool allow_cwnd_to_decrease = false;
+ bool is_rtt_trusted = false;
};
static SendAlgorithmInterface* Create(
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index cad9cac..ccf2d3a 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -1672,7 +1672,11 @@
// QuicSentPacketManager::SetInitialRtt clamps the initial_rtt to between
// [min_initial_rtt, max_initial_rtt].
const QuicTime::Delta min_initial_rtt =
- QuicTime::Delta::FromMicroseconds(kMinInitialRoundTripTimeUs);
+ server_connection->sent_packet_manager().use_lower_min_irtt()
+ ? QuicTime::Delta::FromMicroseconds(
+ kMinTrustedInitialRoundTripTimeUs)
+ : QuicTime::Delta::FromMicroseconds(
+ kMinUntrustedInitialRoundTripTimeUs);
const QuicTime::Delta max_initial_rtt =
QuicTime::Delta::FromMicroseconds(kMaxInitialRoundTripTimeUs);
const QuicTime::Delta expected_initial_rtt =
diff --git a/quic/core/http/quic_server_session_base.cc b/quic/core/http/quic_server_session_base.cc
index 8edcb69..5b1fe05 100644
--- a/quic/core/http/quic_server_session_base.cc
+++ b/quic/core/http/quic_server_session_base.cc
@@ -47,8 +47,13 @@
void QuicServerSessionBase::OnConfigNegotiated() {
QuicSpdySession::OnConfigNegotiated();
- if (!config()->HasReceivedConnectionOptions()) {
- return;
+ const bool use_lower_min_irtt =
+ connection()->sent_packet_manager().use_lower_min_irtt();
+
+ if (!use_lower_min_irtt) {
+ if (!config()->HasReceivedConnectionOptions()) {
+ return;
+ }
}
const CachedNetworkParameters* cached_network_params =
@@ -61,20 +66,29 @@
cached_network_params != nullptr) {
if (cached_network_params->serving_region() == serving_region_) {
QUIC_CODE_COUNT(quic_server_received_network_params_at_same_region);
- if (ContainsQuicTag(config()->ReceivedConnectionOptions(), kTRTT)) {
+ if ((!use_lower_min_irtt || config()->HasReceivedConnectionOptions()) &&
+ ContainsQuicTag(config()->ReceivedConnectionOptions(), kTRTT)) {
QUIC_DLOG(INFO)
<< "Server: Setting initial rtt to "
<< cached_network_params->min_rtt_ms()
<< "ms which is received from a validated address token";
connection()->sent_packet_manager().SetInitialRtt(
QuicTime::Delta::FromMilliseconds(
- cached_network_params->min_rtt_ms()));
+ cached_network_params->min_rtt_ms()),
+ /*trusted=*/use_lower_min_irtt);
}
} else {
QUIC_CODE_COUNT(quic_server_received_network_params_at_different_region);
}
}
+ if (use_lower_min_irtt) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_lower_min_for_trusted_irtt, 1, 2);
+ if (!config()->HasReceivedConnectionOptions()) {
+ return;
+ }
+ }
+
// Enable bandwidth resumption if peer sent correct connection options.
const bool last_bandwidth_resumption =
ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE);
diff --git a/quic/core/quic_constants.h b/quic/core/quic_constants.h
index 214417e..812b28b 100644
--- a/quic/core/quic_constants.h
+++ b/quic/core/quic_constants.h
@@ -86,8 +86,11 @@
// Default size of the socket receive buffer in bytes.
const QuicByteCount kDefaultSocketReceiveBuffer = 1024 * 1024;
-// Don't allow a client to suggest an RTT shorter than 10ms.
-const uint32_t kMinInitialRoundTripTimeUs = 10 * kNumMicrosPerMilli;
+// The lower bound of an untrusted initial rtt value.
+const uint32_t kMinUntrustedInitialRoundTripTimeUs = 10 * kNumMicrosPerMilli;
+
+// The lower bound of a trusted initial rtt value.
+const uint32_t kMinTrustedInitialRoundTripTimeUs = 5 * kNumMicrosPerMilli;
// Don't allow a client to suggest an RTT longer than 1 second.
const uint32_t kMaxInitialRoundTripTimeUs = kNumMicrosPerSecond;
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h
index 5c63ddc..938877f 100644
--- a/quic/core/quic_flags_list.h
+++ b/quic/core/quic_flags_list.h
@@ -23,6 +23,8 @@
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_no_probe_up_exit_if_no_queue, true)
// If true, 1) NEW_TOKENs sent from a IETF QUIC session will include the cached network parameters proto, 2) A min_rtt received from a validated token will be used to set the initial rtt, 3) Enable bandwidth resumption for IETF QUIC when connection options BWRE or BWMX exists.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_cached_network_parameters_to_address_token2, true)
+// If true, 1) QUIC connections will use a lower minimum for trusted initial rtt, 2) When TRTT is received, QUIC server sessions will mark the initial rtt from CachedNetworkParameters as trusted.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_lower_min_for_trusted_irtt, false)
// If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
// If true, QpackEncoder will stop emitting instructions on the encoder stream if amount of buffered data exceeds a hardcoded limit.
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index 588c3ef..0d6c862 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -138,12 +138,14 @@
config.ReceivedInitialRoundTripTimeUs() > 0) {
if (!config.HasClientSentConnectionOption(kNRTT, perspective)) {
SetInitialRtt(QuicTime::Delta::FromMicroseconds(
- config.ReceivedInitialRoundTripTimeUs()));
+ config.ReceivedInitialRoundTripTimeUs()),
+ /*trusted=*/false);
}
} else if (config.HasInitialRoundTripTimeUsToSend() &&
config.GetInitialRoundTripTimeUsToSend() > 0) {
SetInitialRtt(QuicTime::Delta::FromMicroseconds(
- config.GetInitialRoundTripTimeUsToSend()));
+ config.GetInitialRoundTripTimeUsToSend()),
+ /*trusted=*/false);
}
if (config.HasReceivedMaxAckDelayMs()) {
peer_max_ack_delay_ =
@@ -384,8 +386,12 @@
// This calls the old AdjustNetworkParameters interface, and fills certain
// fields in SendAlgorithmInterface::NetworkParams
// (e.g., quic_bbr_fix_pacing_rate) using GFE flags.
- AdjustNetworkParameters(SendAlgorithmInterface::NetworkParams(
- bandwidth, rtt, /*allow_cwnd_to_decrease = */ false));
+ SendAlgorithmInterface::NetworkParams params(
+ bandwidth, rtt, /*allow_cwnd_to_decrease = */ false);
+ // The rtt is trusted because it's a min_rtt measured from a previous
+ // connection with the same network path between client and server.
+ params.is_rtt_trusted = true;
+ AdjustNetworkParameters(params);
}
void QuicSentPacketManager::AdjustNetworkParameters(
@@ -404,8 +410,24 @@
}
const QuicBandwidth& bandwidth = params.bandwidth;
const QuicTime::Delta& rtt = params.rtt;
- if (!rtt.IsZero()) {
- SetInitialRtt(rtt);
+
+ if (use_lower_min_irtt()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_lower_min_for_trusted_irtt, 2, 2);
+ if (!rtt.IsZero()) {
+ if (params.is_rtt_trusted) {
+ // Always set initial rtt if it's trusted.
+ SetInitialRtt(rtt, /*trusted=*/true);
+ } else if (rtt_stats_.initial_rtt() ==
+ QuicTime::Delta::FromMilliseconds(kInitialRttMs)) {
+ // Only set initial rtt if we are using the default. This avoids
+ // overwriting a trusted initial rtt by an untrusted one.
+ SetInitialRtt(rtt, /*trusted=*/false);
+ }
+ }
+ } else {
+ if (!rtt.IsZero()) {
+ SetInitialRtt(rtt, /*trusted=*/false);
+ }
}
const QuicByteCount old_cwnd = send_algorithm_->GetCongestionWindow();
if (GetQuicReloadableFlag(quic_conservative_bursts) && using_pacing_ &&
@@ -1710,9 +1732,10 @@
return pacing_sender_.GetNextReleaseTime();
}
-void QuicSentPacketManager::SetInitialRtt(QuicTime::Delta rtt) {
- const QuicTime::Delta min_rtt =
- QuicTime::Delta::FromMicroseconds(kMinInitialRoundTripTimeUs);
+void QuicSentPacketManager::SetInitialRtt(QuicTime::Delta rtt, bool trusted) {
+ const QuicTime::Delta min_rtt = QuicTime::Delta::FromMicroseconds(
+ trusted ? kMinTrustedInitialRoundTripTimeUs
+ : kMinUntrustedInitialRoundTripTimeUs);
QuicTime::Delta max_rtt =
QuicTime::Delta::FromMicroseconds(kMaxInitialRoundTripTimeUs);
rtt_stats_.set_initial_rtt(std::max(min_rtt, std::min(max_rtt, rtt)));
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index cb4fdef..7b127b5 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -482,8 +482,13 @@
num_ptos_for_path_degrading_ = num_ptos_for_path_degrading;
}
- // Sets the initial RTT of the connection.
- void SetInitialRtt(QuicTime::Delta rtt);
+ // Sets the initial RTT of the connection. The inital RTT is clamped to
+ // - A maximum of kMaxInitialRoundTripTimeUs.
+ // - A minimum of kMinTrustedInitialRoundTripTimeUs if |trusted|, or
+ // kMinUntrustedInitialRoundTripTimeUs if not |trusted|.
+ void SetInitialRtt(QuicTime::Delta rtt, bool trusted);
+
+ bool use_lower_min_irtt() const { return use_lower_min_irtt_; }
private:
friend class test::QuicConnectionPeer;
@@ -756,6 +761,10 @@
// Whether to ignore the ack_delay in received ACKs.
bool ignore_ack_delay_;
+
+ // Latched value of --quic_use_lower_min_for_trusted_irtt.
+ bool use_lower_min_irtt_ =
+ GetQuicReloadableFlag(quic_use_lower_min_for_trusted_irtt);
};
} // namespace quic
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index d038f4f..565eb96 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -2101,6 +2101,7 @@
params.bandwidth = QuicBandwidth::Zero();
params.allow_cwnd_to_decrease = false;
params.rtt = kRtt;
+ params.is_rtt_trusted = true;
EXPECT_CALL(*send_algorithm_, AdjustNetworkParameters(params));
EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
@@ -4682,6 +4683,42 @@
QuicTime::Delta::FromMilliseconds(1u)));
}
+TEST_F(QuicSentPacketManagerTest, SetInitialRtt) {
+ // Upper bounds.
+ manager_.SetInitialRtt(
+ QuicTime::Delta::FromMicroseconds(kMaxInitialRoundTripTimeUs + 1), false);
+ EXPECT_EQ(manager_.GetRttStats()->initial_rtt().ToMicroseconds(),
+ kMaxInitialRoundTripTimeUs);
+
+ manager_.SetInitialRtt(
+ QuicTime::Delta::FromMicroseconds(kMaxInitialRoundTripTimeUs + 1), true);
+ EXPECT_EQ(manager_.GetRttStats()->initial_rtt().ToMicroseconds(),
+ kMaxInitialRoundTripTimeUs);
+
+ EXPECT_GT(kMinUntrustedInitialRoundTripTimeUs,
+ kMinTrustedInitialRoundTripTimeUs);
+
+ // Lower bounds for untrusted rtt.
+ manager_.SetInitialRtt(QuicTime::Delta::FromMicroseconds(
+ kMinUntrustedInitialRoundTripTimeUs - 1),
+ false);
+ EXPECT_EQ(manager_.GetRttStats()->initial_rtt().ToMicroseconds(),
+ kMinUntrustedInitialRoundTripTimeUs);
+
+ // Lower bounds for trusted rtt.
+ manager_.SetInitialRtt(QuicTime::Delta::FromMicroseconds(
+ kMinUntrustedInitialRoundTripTimeUs - 1),
+ true);
+ EXPECT_EQ(manager_.GetRttStats()->initial_rtt().ToMicroseconds(),
+ kMinUntrustedInitialRoundTripTimeUs - 1);
+
+ manager_.SetInitialRtt(
+ QuicTime::Delta::FromMicroseconds(kMinTrustedInitialRoundTripTimeUs - 1),
+ true);
+ EXPECT_EQ(manager_.GetRttStats()->initial_rtt().ToMicroseconds(),
+ kMinTrustedInitialRoundTripTimeUs);
+}
+
} // namespace
} // namespace test
} // namespace quic