In QUIC, add a copt to enable overshooting detection. Protected by gfe2_reloadable_flag_quic_enable_overshooting_detection.
PiperOrigin-RevId: 323844168
Change-Id: I3776c6459611870e85aa7031cde53d4cc8d7e350
diff --git a/quic/core/congestion_control/bbr_sender.cc b/quic/core/congestion_control/bbr_sender.cc
index 05d62ea..7389067 100644
--- a/quic/core/congestion_control/bbr_sender.cc
+++ b/quic/core/congestion_control/bbr_sender.cc
@@ -120,9 +120,10 @@
enable_ack_aggregation_during_startup_(false),
expire_ack_aggregation_in_startup_(false),
drain_to_target_(false),
- network_parameters_adjusted_(false),
- bytes_lost_with_network_parameters_adjusted_(0),
- bytes_lost_multiplier_with_network_parameters_adjusted_(2),
+ detect_overshooting_(false),
+ bytes_lost_while_detecting_overshooting_(0),
+ bytes_lost_multiplier_while_detecting_overshooting_(2),
+ cwnd_to_calculate_min_pacing_rate_(initial_congestion_window_),
max_congestion_window_with_network_parameters_adjusted_(
kMaxInitialCongestionWindow * kDefaultTCPMSS) {
if (stats_) {
@@ -142,6 +143,8 @@
if (mode_ == STARTUP) {
initial_congestion_window_ = congestion_window * kDefaultTCPMSS;
congestion_window_ = congestion_window * kDefaultTCPMSS;
+ cwnd_to_calculate_min_pacing_rate_ = std::min(
+ initial_congestion_window_, cwnd_to_calculate_min_pacing_rate_);
}
}
@@ -254,10 +257,10 @@
drain_to_target_ = true;
}
if (config.HasClientRequestedIndependentOption(kBWM3, perspective)) {
- bytes_lost_multiplier_with_network_parameters_adjusted_ = 3;
+ bytes_lost_multiplier_while_detecting_overshooting_ = 3;
}
if (config.HasClientRequestedIndependentOption(kBWM4, perspective)) {
- bytes_lost_multiplier_with_network_parameters_adjusted_ = 4;
+ bytes_lost_multiplier_while_detecting_overshooting_ = 4;
}
if (config.HasClientRequestedIndependentOption(kBBR4, perspective)) {
sampler_.SetMaxAckHeightTrackerWindowLength(2 * kBandwidthWindowSize);
@@ -288,6 +291,15 @@
max_congestion_window_with_network_parameters_adjusted_ =
100 * kDefaultTCPMSS;
}
+ if (GetQuicReloadableFlag(quic_enable_overshooting_detection) &&
+ config.HasClientRequestedIndependentOption(kDTOS, perspective)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_enable_overshooting_detection);
+ detect_overshooting_ = true;
+ // DTOS would allow pacing rate drop to IW 10 / min_rtt if overshooting is
+ // detected.
+ cwnd_to_calculate_min_pacing_rate_ =
+ std::min(initial_congestion_window_, 10 * kDefaultTCPMSS);
+ }
ApplyConnectionOptions(config.ClientRequestedIndependentOptions(perspective));
}
@@ -354,7 +366,7 @@
QuicBandwidth new_pacing_rate =
QuicBandwidth::FromBytesAndTimeDelta(congestion_window_, GetMinRtt());
pacing_rate_ = std::max(pacing_rate_, new_pacing_rate);
- network_parameters_adjusted_ = true;
+ detect_overshooting_ = true;
}
}
}
@@ -766,29 +778,27 @@
return;
}
- if (network_parameters_adjusted_) {
- bytes_lost_with_network_parameters_adjusted_ += bytes_lost;
+ if (detect_overshooting_) {
+ bytes_lost_while_detecting_overshooting_ += bytes_lost;
// Check for overshooting with network parameters adjusted when pacing rate
// > target_rate and loss has been detected.
if (pacing_rate_ > target_rate &&
- bytes_lost_with_network_parameters_adjusted_ > 0) {
+ bytes_lost_while_detecting_overshooting_ > 0) {
if (has_non_app_limited_sample_ ||
- bytes_lost_with_network_parameters_adjusted_ *
- bytes_lost_multiplier_with_network_parameters_adjusted_ >
+ bytes_lost_while_detecting_overshooting_ *
+ bytes_lost_multiplier_while_detecting_overshooting_ >
initial_congestion_window_) {
// We are fairly sure overshoot happens if 1) there is at least one
// non app-limited bw sample or 2) half of IW gets lost. Slow pacing
// rate.
- // Do not let the pacing rate drop below the connection's initial pacing
- // rate.
- pacing_rate_ =
- std::max(target_rate, QuicBandwidth::FromBytesAndTimeDelta(
- initial_congestion_window_, GetMinRtt()));
+ pacing_rate_ = std::max(
+ target_rate, QuicBandwidth::FromBytesAndTimeDelta(
+ cwnd_to_calculate_min_pacing_rate_, GetMinRtt()));
if (stats_) {
stats_->overshooting_detected_with_network_parameters_adjusted = true;
}
- bytes_lost_with_network_parameters_adjusted_ = 0;
- network_parameters_adjusted_ = false;
+ bytes_lost_while_detecting_overshooting_ = 0;
+ detect_overshooting_ = false;
}
}
}
diff --git a/quic/core/congestion_control/bbr_sender.h b/quic/core/congestion_control/bbr_sender.h
index 446f0dd..d89e3fe 100644
--- a/quic/core/congestion_control/bbr_sender.h
+++ b/quic/core/congestion_control/bbr_sender.h
@@ -384,15 +384,17 @@
// or it's time for high gain mode.
bool drain_to_target_;
- // True if network parameters are adjusted, and this will be reset if
- // overshooting is detected and pacing rate gets slowed.
- bool network_parameters_adjusted_;
- // Bytes lost after network parameters gets adjusted.
- QuicByteCount bytes_lost_with_network_parameters_adjusted_;
- // Decrease pacing rate after parameters adjusted if
- // bytes_lost_with_network_parameters_adjusted_ *
- // bytes_lost_multiplier_with_network_parameters_adjusted_ > IW.
- uint8_t bytes_lost_multiplier_with_network_parameters_adjusted_;
+ // If true, slow down pacing rate in STARTUP when overshooting is detected.
+ bool detect_overshooting_;
+ // Bytes lost while detect_overshooting_ is true.
+ QuicByteCount bytes_lost_while_detecting_overshooting_;
+ // Slow down pacing rate if
+ // bytes_lost_while_detecting_overshooting_ *
+ // bytes_lost_multiplier_while_detecting_overshooting_ > IW.
+ uint8_t bytes_lost_multiplier_while_detecting_overshooting_;
+ // When overshooting is detected, do not drop pacing_rate_ below this value /
+ // min_rtt.
+ QuicByteCount cwnd_to_calculate_min_pacing_rate_;
// Max congestion window when adjusting network parameters.
QuicByteCount max_congestion_window_with_network_parameters_adjusted_;
diff --git a/quic/core/congestion_control/bbr_sender_test.cc b/quic/core/congestion_control/bbr_sender_test.cc
index 000216b..0e94b6b 100644
--- a/quic/core/congestion_control/bbr_sender_test.cc
+++ b/quic/core/congestion_control/bbr_sender_test.cc
@@ -1298,5 +1298,21 @@
EXPECT_EQ(prior_bandwidth_estimate, sender_->BandwidthEstimate());
}
+TEST_F(BbrSenderTest, EnableOvershootingDetection) {
+ if (!GetQuicReloadableFlag(quic_enable_overshooting_detection)) {
+ return;
+ }
+ SetConnectionOption(kDTOS);
+ CreateSmallBufferSetup();
+ // Set a overly large initial cwnd.
+ sender_->SetInitialCongestionWindowInPackets(200);
+ const QuicConnectionStats& stats = bbr_sender_.connection()->GetStats();
+ EXPECT_FALSE(stats.overshooting_detected_with_network_parameters_adjusted);
+ DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(30));
+
+ // Verify overshooting is detected.
+ EXPECT_TRUE(stats.overshooting_detected_with_network_parameters_adjusted);
+}
+
} // namespace test
} // namespace quic
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index f6bebf9..ca972c1 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -292,6 +292,8 @@
// resumption * 4 > IW.
const QuicTag kICW1 = TAG('I', 'C', 'W', '1'); // Max initial congestion window
// 100.
+const QuicTag kDTOS = TAG('D', 'T', 'O', 'S'); // Enable overshooting
+ // detection.
// Enable path MTU discovery experiment.
const QuicTag kMTUH = TAG('M', 'T', 'U', 'H'); // High-target MTU discovery.