gfe-relnote: For QUIC BBRv2, always count the number of loss marking events in a round and only exit PROBE_UP if that number is above a threshold. Protected by --gfe2_reloadable_flag_quic_bbr2_always_count_loss_events.
The loss event threshold for exiting PROBE_UP is controlled by protocol flag --quic_bbr2_default_probe_bw_full_loss_count, with a default value of 2.
PiperOrigin-RevId: 289924952
Change-Id: Ia7779b1c80302affec2fcfd98d6cdf8e48ce38dd
diff --git a/quic/core/congestion_control/bbr2_misc.cc b/quic/core/congestion_control/bbr2_misc.cc
index 6f6757b..352e7e6 100644
--- a/quic/core/congestion_control/bbr2_misc.cc
+++ b/quic/core/congestion_control/bbr2_misc.cc
@@ -185,7 +185,11 @@
congestion_event->bytes_in_flight = 0;
}
}
- bytes_lost_in_round_ += congestion_event->bytes_lost;
+
+ if (congestion_event->bytes_lost > 0) {
+ bytes_lost_in_round_ += congestion_event->bytes_lost;
+ loss_events_in_round_++;
+ }
bandwidth_sampler_.OnAckEventEnd(BandwidthEstimate(), RoundTripCount());
@@ -251,7 +255,10 @@
congestion_event->bytes_in_flight = 0;
}
- bytes_lost_in_round_ += congestion_event->bytes_lost;
+ if (congestion_event->bytes_lost > 0) {
+ bytes_lost_in_round_ += congestion_event->bytes_lost;
+ loss_events_in_round_++;
+ }
// |bandwidth_latest_| and |inflight_latest_| only increased within a round.
if (sample.sample_max_bandwidth > bandwidth_latest_) {
@@ -316,6 +323,7 @@
}
bytes_lost_in_round_ = 0;
+ loss_events_in_round_ = 0;
}
bandwidth_sampler_.RemoveObsoletePackets(least_unacked_packet);
@@ -391,6 +399,7 @@
void Bbr2NetworkModel::RestartRound() {
bytes_lost_in_round_ = 0;
+ loss_events_in_round_ = 0;
round_trip_counter_.RestartRound();
}
diff --git a/quic/core/congestion_control/bbr2_misc.h b/quic/core/congestion_control/bbr2_misc.h
index 5c8c0e2..1d6fb35 100644
--- a/quic/core/congestion_control/bbr2_misc.h
+++ b/quic/core/congestion_control/bbr2_misc.h
@@ -119,6 +119,10 @@
QuicTime::Delta::FromMilliseconds(
GetQuicFlag(FLAGS_quic_bbr2_default_probe_bw_max_rand_duration_ms));
+ // The minimum number of loss marking events to exit the PROBE_UP phase.
+ int64_t probe_bw_full_loss_count =
+ GetQuicFlag(FLAGS_quic_bbr2_default_probe_bw_full_loss_count);
+
// Multiplier to get target inflight (as multiple of BDP) for PROBE_UP phase.
float probe_bw_probe_inflight_gain = 1.25;
@@ -372,6 +376,8 @@
bool IsCongestionWindowLimited(
const Bbr2CongestionEvent& congestion_event) const;
+ // TODO(wub): Replace this by a new version which takes two thresholds, one
+ // is the number of loss events, the other is the percentage of bytes lost.
bool IsInflightTooHigh(const Bbr2CongestionEvent& congestion_event) const;
QuicPacketNumber last_sent_packet() const {
@@ -395,6 +401,10 @@
return total_bytes_sent() - total_bytes_acked() - total_bytes_lost();
}
+ int64_t loss_events_in_round() const { return loss_events_in_round_; }
+
+ bool always_count_loss_events() const { return always_count_loss_events_; }
+
QuicPacketNumber end_of_app_limited_phase() const {
return bandwidth_sampler_.end_of_app_limited_phase();
}
@@ -452,6 +462,11 @@
// Bytes lost in the current round. Updated once per congestion event.
QuicByteCount bytes_lost_in_round_ = 0;
+ // Number of loss marking events in the current round.
+ int64_t loss_events_in_round_ = 0;
+ // Latched value of --quic_bbr2_always_count_loss_events.
+ const bool always_count_loss_events_ =
+ GetQuicReloadableFlag(quic_bbr2_always_count_loss_events);
// Max bandwidth in the current round. Updated once per congestion event.
QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
diff --git a/quic/core/congestion_control/bbr2_probe_bw.cc b/quic/core/congestion_control/bbr2_probe_bw.cc
index 11b389c..781e218 100644
--- a/quic/core/congestion_control/bbr2_probe_bw.cc
+++ b/quic/core/congestion_control/bbr2_probe_bw.cc
@@ -159,7 +159,14 @@
return NOT_ADAPTED_INVALID_SAMPLE;
}
- if (model_->IsInflightTooHigh(congestion_event)) {
+ bool has_enough_loss_events = true;
+ if (model_->always_count_loss_events()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_always_count_loss_events, 2, 2);
+ has_enough_loss_events =
+ model_->loss_events_in_round() >= Params().probe_bw_full_loss_count;
+ }
+
+ if (has_enough_loss_events && model_->IsInflightTooHigh(congestion_event)) {
if (cycle_.is_sample_from_probing) {
cycle_.is_sample_from_probing = false;
diff --git a/quic/core/congestion_control/bbr2_startup.cc b/quic/core/congestion_control/bbr2_startup.cc
index 8591d71..090dd40 100644
--- a/quic/core/congestion_control/bbr2_startup.cc
+++ b/quic/core/congestion_control/bbr2_startup.cc
@@ -98,6 +98,15 @@
++loss_events_in_round_;
}
+ if (model_->always_count_loss_events()) {
+ DCHECK_EQ(loss_events_in_round_, model_->loss_events_in_round());
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_always_count_loss_events, 1, 2);
+ }
+
+ const int64_t loss_events_in_round = model_->always_count_loss_events()
+ ? model_->loss_events_in_round()
+ : loss_events_in_round_;
+
// TODO(wub): In TCP, loss based exit only happens at end of a loss round, in
// QUIC we use the end of the normal round here. It is possible to exit after
// any congestion event, using information of the "rolling round".
@@ -107,13 +116,13 @@
QUIC_DVLOG(3)
<< sender_
- << " CheckExcessiveLosses at end of round. loss_events_in_round_:"
- << loss_events_in_round_
+ << " CheckExcessiveLosses at end of round. loss_events_in_round:"
+ << loss_events_in_round
<< ", threshold:" << Params().startup_full_loss_count << " @ "
<< congestion_event.event_time;
// At the end of a round trip. Check if loss is too high in this round.
- if (loss_events_in_round_ >= Params().startup_full_loss_count &&
+ if (loss_events_in_round >= Params().startup_full_loss_count &&
model_->IsInflightTooHigh(congestion_event)) {
const QuicByteCount bdp = model_->BDP(model_->MaxBandwidth());
QUIC_DVLOG(3) << sender_
diff --git a/quic/core/congestion_control/bbr2_startup.h b/quic/core/congestion_control/bbr2_startup.h
index 80539d9..6477957 100644
--- a/quic/core/congestion_control/bbr2_startup.h
+++ b/quic/core/congestion_control/bbr2_startup.h
@@ -59,6 +59,7 @@
QuicRoundTripCount rounds_without_bandwidth_growth_;
// Number of loss events in the current round trip.
+ // TODO(wub): Remove when deprecating --quic_bbr2_always_count_loss_events.
int64_t loss_events_in_round_;
};