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