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_; };