No public description
PiperOrigin-RevId: 675563943
diff --git a/quiche/quic/core/congestion_control/bbr2_misc.cc b/quiche/quic/core/congestion_control/bbr2_misc.cc
index 1584d02..00879b9 100644
--- a/quiche/quic/core/congestion_control/bbr2_misc.cc
+++ b/quiche/quic/core/congestion_control/bbr2_misc.cc
@@ -226,6 +226,16 @@
std::max(bandwidth_latest_, bandwidth_lo_ * (1.0 - Params().beta));
QUIC_DVLOG(3) << "bandwidth_lo_ updated to " << bandwidth_lo_
<< ", bandwidth_latest_ is " << bandwidth_latest_;
+ if (enable_app_driven_pacing_) {
+ // In this mode, we forcibly cap bandwidth_lo_ at the application driven
+ // pacing rate when congestion_event.bytes_lost > 0. The idea is to
+ // avoid going over what the application needs at the earliest signs of
+ // network congestion.
+ bandwidth_lo_ = std::min(application_bandwidth_target_, bandwidth_lo_);
+ QUIC_DVLOG(3) << "bandwidth_lo_ updated to " << bandwidth_lo_
+ << "after applying application_driven_pacing at "
+ << application_bandwidth_target_;
+ }
if (Params().ignore_inflight_lo) {
return;
diff --git a/quiche/quic/core/congestion_control/bbr2_misc.h b/quiche/quic/core/congestion_control/bbr2_misc.h
index 6dbe904..09654ad 100644
--- a/quiche/quic/core/congestion_control/bbr2_misc.h
+++ b/quiche/quic/core/congestion_control/bbr2_misc.h
@@ -438,6 +438,14 @@
bool MaybeExpireMinRtt(const Bbr2CongestionEvent& congestion_event);
+ void SetEnableAppDrivenPacing(bool value) {
+ enable_app_driven_pacing_ = value;
+ }
+
+ void SetApplicationBandwidthTarget(QuicBandwidth bandwidth) {
+ application_bandwidth_target_ = bandwidth;
+ }
+
QuicBandwidth BandwidthEstimate() const {
return std::min(MaxBandwidth(), bandwidth_lo_);
}
@@ -576,6 +584,9 @@
QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
// Max bandwidth of recent rounds. Updated once per round.
QuicBandwidth bandwidth_lo_ = bandwidth_lo_default();
+ // Target bandwidth from applications for app-driven pacing. Only used when
+ // enable_app_driven_pacing_ is true.
+ QuicBandwidth application_bandwidth_target_ = QuicBandwidth::Infinite();
// bandwidth_lo_ at the beginning of a round with loss. Only used when the
// bw_lo_mode is non-default.
QuicBandwidth prior_bandwidth_lo_ = QuicBandwidth::Zero();
@@ -593,6 +604,9 @@
// epoch.
bool cwnd_limited_before_aggregation_epoch_ = false;
+ // Enable application-driven pacing.
+ bool enable_app_driven_pacing_ = false;
+
// STARTUP-centric fields which experimentally used by PROBE_UP.
bool full_bandwidth_reached_ = false;
QuicBandwidth full_bandwidth_baseline_ = QuicBandwidth::Zero();
diff --git a/quiche/quic/core/congestion_control/bbr2_sender.cc b/quiche/quic/core/congestion_control/bbr2_sender.cc
index 3e4ecb3..6118546 100644
--- a/quiche/quic/core/congestion_control/bbr2_sender.cc
+++ b/quiche/quic/core/congestion_control/bbr2_sender.cc
@@ -194,6 +194,9 @@
if (ContainsQuicTag(connection_options, kBBRB)) {
model_.SetLimitMaxAckHeightTrackerBySendRate(true);
}
+ if (ContainsQuicTag(connection_options, kADP0)) {
+ model_.SetEnableAppDrivenPacing(true);
+ }
if (ContainsQuicTag(connection_options, kB206)) {
params_.startup_full_loss_count = params_.probe_bw_full_loss_count;
}
@@ -273,6 +276,11 @@
}
}
+void Bbr2Sender::SetApplicationDrivenPacingRate(
+ QuicBandwidth application_bandwidth_target) {
+ model_.SetApplicationBandwidthTarget(application_bandwidth_target);
+}
+
void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
QuicByteCount prior_in_flight,
QuicTime event_time,
diff --git a/quiche/quic/core/congestion_control/bbr2_sender.h b/quiche/quic/core/congestion_control/bbr2_sender.h
index 636d340..9338414 100644
--- a/quiche/quic/core/congestion_control/bbr2_sender.h
+++ b/quiche/quic/core/congestion_control/bbr2_sender.h
@@ -52,6 +52,9 @@
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
+ void SetApplicationDrivenPacingRate(
+ QuicBandwidth application_bandwidth_target) override;
+
void OnCongestionEvent(bool rtt_updated, QuicByteCount prior_in_flight,
QuicTime event_time,
const AckedPacketVector& acked_packets,
diff --git a/quiche/quic/core/congestion_control/bbr_sender.h b/quiche/quic/core/congestion_control/bbr_sender.h
index 625394a..132908f 100644
--- a/quiche/quic/core/congestion_control/bbr_sender.h
+++ b/quiche/quic/core/congestion_control/bbr_sender.h
@@ -108,6 +108,8 @@
void AdjustNetworkParameters(const NetworkParams& params) override;
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
+ void SetApplicationDrivenPacingRate(
+ QuicBandwidth /*application_bandwidth_target*/) override {}
void OnCongestionEvent(bool rtt_updated, QuicByteCount prior_in_flight,
QuicTime event_time,
const AckedPacketVector& acked_packets,
diff --git a/quiche/quic/core/congestion_control/send_algorithm_interface.h b/quiche/quic/core/congestion_control/send_algorithm_interface.h
index 95cd8f0..e5f5588 100644
--- a/quiche/quic/core/congestion_control/send_algorithm_interface.h
+++ b/quiche/quic/core/congestion_control/send_algorithm_interface.h
@@ -74,6 +74,11 @@
// if called after the initial congestion window is no longer relevant.
virtual void SetInitialCongestionWindowInPackets(QuicPacketCount packets) = 0;
+ // [Experimental] Sets the application driven pacing rate. This is only used
+ // by an experimental feature for bbr2_sender.
+ virtual void SetApplicationDrivenPacingRate(
+ QuicBandwidth application_bandwidth_target) = 0;
+
// Indicates an update to the congestion state, caused either by an incoming
// ack or loss event timeout. |rtt_updated| indicates whether a new
// latest_rtt sample has been taken, |prior_in_flight| the bytes in flight
diff --git a/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h
index de003f7..b62a808 100644
--- a/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h
+++ b/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h
@@ -50,6 +50,8 @@
void SetNumEmulatedConnections(int num_connections);
void SetInitialCongestionWindowInPackets(
QuicPacketCount congestion_window) override;
+ void SetApplicationDrivenPacingRate(
+ QuicBandwidth /*application_bandwidth_target*/) override {}
void OnConnectionMigration() override;
void OnCongestionEvent(bool rtt_updated, QuicByteCount prior_in_flight,
QuicTime event_time,
diff --git a/quiche/quic/core/crypto/crypto_protocol.h b/quiche/quic/core/crypto/crypto_protocol.h
index e05f869..118de64 100644
--- a/quiche/quic/core/crypto/crypto_protocol.h
+++ b/quiche/quic/core/crypto/crypto_protocol.h
@@ -364,6 +364,9 @@
const QuicTag kNSLC = TAG('N', 'S', 'L', 'C'); // Always send connection close
// for idle timeout.
+// Enable application-driven pacing experiment.
+const QuicTag kADP0 = TAG('A', 'D', 'P', '0'); // Enable App-Driven Pacing.
+
// Proof types (i.e. certificate types)
// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
// is allowed and is equivalent to specifying only kX509.
diff --git a/quiche/quic/test_tools/quic_test_utils.h b/quiche/quic/test_tools/quic_test_utils.h
index ada2cbc..df9fd66 100644
--- a/quiche/quic/test_tools/quic_test_utils.h
+++ b/quiche/quic/test_tools/quic_test_utils.h
@@ -1216,6 +1216,8 @@
(const QuicTagVector& connection_options), (override));
MOCK_METHOD(void, SetInitialCongestionWindowInPackets,
(QuicPacketCount packets), (override));
+ MOCK_METHOD(void, SetApplicationDrivenPacingRate,
+ (QuicBandwidth application_bandwidth_target), (override));
MOCK_METHOD(void, OnCongestionEvent,
(bool rtt_updated, QuicByteCount bytes_in_flight,
QuicTime event_time, const AckedPacketVector& acked_packets,