For QUIC BBRv2, if connection option B2NE is set, do not exit STARTUP on loss if there are enough bandwidth growth in round. Protected by FLAGS_quic_reloadable_flag_quic_bbr2_no_exit_startup_on_loss_with_bw_growth. PiperOrigin-RevId: 337094247 Change-Id: I6d120e45004e4aa2cd894ea29a2f502d50ed8921
diff --git a/quic/core/congestion_control/bbr2_misc.h b/quic/core/congestion_control/bbr2_misc.h index a6f710a..80a7423 100644 --- a/quic/core/congestion_control/bbr2_misc.h +++ b/quic/core/congestion_control/bbr2_misc.h
@@ -92,6 +92,10 @@ int64_t startup_full_loss_count = GetQuicFlag(FLAGS_quic_bbr2_default_startup_full_loss_count); + // If true, always exit STARTUP on loss, even if bandwidth exceeds threshold. + // If false, exit STARTUP on loss only if bandwidth is below threshold. + bool always_exit_startup_on_excess_loss = true; + /* * DRAIN parameters. */
diff --git a/quic/core/congestion_control/bbr2_sender.cc b/quic/core/congestion_control/bbr2_sender.cc index 3185cc0..4e57a9a 100644 --- a/quic/core/congestion_control/bbr2_sender.cc +++ b/quic/core/congestion_control/bbr2_sender.cc
@@ -11,6 +11,7 @@ #include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" #include "net/third_party/quiche/src/quic/core/quic_bandwidth.h" +#include "net/third_party/quiche/src/quic/core/quic_tag.h" #include "net/third_party/quiche/src/quic/core/quic_types.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" @@ -156,6 +157,12 @@ params_.drain_cwnd_gain = 2; } } + if (GetQuicReloadableFlag(quic_bbr2_no_exit_startup_on_loss_with_bw_growth) && + ContainsQuicTag(connection_options, kB2NE)) { + QUIC_RELOADABLE_FLAG_COUNT( + quic_bbr2_no_exit_startup_on_loss_with_bw_growth); + params_.always_exit_startup_on_excess_loss = false; + } if (ContainsQuicTag(connection_options, kBSAO)) { model_.EnableOverestimateAvoidance(); }
diff --git a/quic/core/congestion_control/bbr2_simulator_test.cc b/quic/core/congestion_control/bbr2_simulator_test.cc index 4273667..5e5ffee 100644 --- a/quic/core/congestion_control/bbr2_simulator_test.cc +++ b/quic/core/congestion_control/bbr2_simulator_test.cc
@@ -413,6 +413,25 @@ EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->smoothed_rtt(), 1.0f); } +TEST_F(Bbr2DefaultTopologyTest, SimpleTransferB2NE) { + SetConnectionOption(kB2NE); + DefaultTopologyParams params; + CreateNetwork(params); + + // Transfer 12MB. + DoSimpleTransfer(12 * 1024 * 1024, QuicTime::Delta::FromSeconds(35)); + EXPECT_TRUE(Bbr2ModeIsOneOf({Bbr2Mode::PROBE_BW, Bbr2Mode::PROBE_RTT})); + + EXPECT_APPROX_EQ(params.BottleneckBandwidth(), + sender_->ExportDebugState().bandwidth_hi, 0.01f); + + EXPECT_LE(sender_loss_rate_in_packets(), 0.05); + // The margin here is high, because the aggregation greatly increases + // smoothed rtt. + EXPECT_GE(params.RTT() * 4, rtt_stats()->smoothed_rtt()); + EXPECT_APPROX_EQ(params.RTT(), rtt_stats()->min_rtt(), 0.2f); +} + TEST_F(Bbr2DefaultTopologyTest, SimpleTransferSmallBuffer) { DefaultTopologyParams params; params.switch_queue_capacity_in_bdp = 0.5;
diff --git a/quic/core/congestion_control/bbr2_startup.cc b/quic/core/congestion_control/bbr2_startup.cc index 72ad66f..8947766 100644 --- a/quic/core/congestion_control/bbr2_startup.cc +++ b/quic/core/congestion_control/bbr2_startup.cc
@@ -44,11 +44,13 @@ const LostPacketVector& /*lost_packets*/, const Bbr2CongestionEvent& congestion_event) { if (!full_bandwidth_reached_ && congestion_event.end_of_round_trip) { - if (!congestion_event.last_sample_is_app_limited) { - CheckBandwidthGrowth(congestion_event); - } + // TCP BBR always exits upon excessive losses. QUIC BBRv1 does not exits + // upon excessive losses, if enough bandwidth growth is observed. + bool has_enough_bw_growth = CheckBandwidthGrowth(congestion_event); - CheckExcessiveLosses(congestion_event); + if (Params().always_exit_startup_on_excess_loss || !has_enough_bw_growth) { + CheckExcessiveLosses(congestion_event); + } } model_->set_pacing_gain(Params().startup_pacing_gain); @@ -62,7 +64,11 @@ const Bbr2CongestionEvent& congestion_event) { DCHECK(!full_bandwidth_reached_); DCHECK(congestion_event.end_of_round_trip); - DCHECK(!congestion_event.last_sample_is_app_limited); + if (congestion_event.last_sample_is_app_limited) { + // Return true such that when Params().always_exit_startup_on_excess_loss is + // false, we'll not check excess loss, which is the behavior of QUIC BBRv1. + return true; + } QuicBandwidth threshold = full_bandwidth_baseline_ * Params().startup_full_bw_threshold;
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h index d272aeb..de9d9d3 100644 --- a/quic/core/crypto/crypto_protocol.h +++ b/quic/core/crypto/crypto_protocol.h
@@ -118,6 +118,9 @@ const QuicTag kB2ON = TAG('B', '2', 'O', 'N'); // Enable BBRv2 const QuicTag kB2NA = TAG('B', '2', 'N', 'A'); // For BBRv2, do not add ack // height to queueing threshold +const QuicTag kB2NE = TAG('B', '2', 'N', 'E'); // For BBRv2, do not exit + // STARTUP if there's enough + // bandwidth growth const QuicTag kB2RP = TAG('B', '2', 'R', 'P'); // For BBRv2, run PROBE_RTT on // the regular schedule const QuicTag kB2CL = TAG('B', '2', 'C', 'L'); // For BBRv2, allow PROBE_BW