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.