gfe-relnote: (n/a) In QUIC BBRv2, avoid unnecessary PROBE_RTTs when coming out of quiescence. Protected by --gfe2_reloadable_flag_quic_bbr2_avoid_unnecessary_probe_rtt. This changes BBRv2 behavior in 2 places: 1. If BBRv2 is in PROBE_RTT out of quiescence, immediately transition to PROBE_BW. This allows the first round after quiescence to send more data. 2. If BBRv2 is in PROBE_BW out of quiescence, postpone the time for the next PROBE_RTT by the duration of the quiescence. PiperOrigin-RevId: 298492623 Change-Id: I13aa0db84da70b6dd84b3478309c4dd559cf531c
diff --git a/quic/core/congestion_control/bbr2_sender.cc b/quic/core/congestion_control/bbr2_sender.cc index e75e4bf..5b6f6e8 100644 --- a/quic/core/congestion_control/bbr2_sender.cc +++ b/quic/core/congestion_control/bbr2_sender.cc
@@ -12,6 +12,7 @@ #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_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_logging.h" namespace quic { @@ -196,6 +197,10 @@ model_.OnCongestionEventFinish(unacked_packets_->GetLeastUnacked(), congestion_event); last_sample_is_app_limited_ = congestion_event.last_sample_is_app_limited; + if (avoid_unnecessary_probe_rtt_ && congestion_event.bytes_in_flight == 0) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_avoid_unnecessary_probe_rtt, 2, 2); + OnEnterQuiescence(event_time); + } QUIC_DVLOG(3) << this << " END CongestionEvent(acked:" << acked_packets @@ -287,6 +292,10 @@ << ", total_acked:" << model_.total_bytes_acked() << ", total_lost:" << model_.total_bytes_lost() << " @ " << sent_time; + if (avoid_unnecessary_probe_rtt_ && bytes_in_flight == 0) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_avoid_unnecessary_probe_rtt, 1, 2); + OnExitQuiescence(sent_time); + } model_.OnPacketSent(sent_time, bytes_in_flight, packet_number, bytes, is_retransmittable); } @@ -332,6 +341,23 @@ stats->num_ack_aggregation_epochs = model_.num_ack_aggregation_epochs(); } +void Bbr2Sender::OnEnterQuiescence(QuicTime now) { + last_quiescence_start_ = now; +} + +void Bbr2Sender::OnExitQuiescence(QuicTime now) { + if (last_quiescence_start_ != QuicTime::Zero()) { + Bbr2Mode next_mode = BBR2_MODE_DISPATCH( + OnExitQuiescence(now, std::min(now, last_quiescence_start_))); + if (next_mode != mode_) { + BBR2_MODE_DISPATCH(Leave(now, nullptr)); + mode_ = next_mode; + BBR2_MODE_DISPATCH(Enter(now, nullptr)); + } + last_quiescence_start_ = QuicTime::Zero(); + } +} + bool Bbr2Sender::ShouldSendProbingPacket() const { // TODO(wub): Implement ShouldSendProbingPacket properly. if (!BBR2_MODE_DISPATCH(IsProbingForBandwidth())) {