Index: net/quic/core/congestion_control/bbr_sender.cc |
diff --git a/net/quic/core/congestion_control/bbr_sender.cc b/net/quic/core/congestion_control/bbr_sender.cc |
index 9fd9d3bd6608a5051b7f3dad61e6230166aca99e..b64dc99d8542578352f796af799b51338dc3a4a8 100644 |
--- a/net/quic/core/congestion_control/bbr_sender.cc |
+++ b/net/quic/core/congestion_control/bbr_sender.cc |
@@ -82,6 +82,9 @@ BbrSender::BbrSender(const RttStats* rtt_stats, |
max_ack_spacing_(kBandwidthWindowSize, QuicTime::Delta::Zero(), 0), |
largest_acked_time_(QuicTime::Zero()), |
largest_acked_sent_time_(QuicTime::Zero()), |
+ max_ack_height_(kBandwidthWindowSize, 0, 0), |
+ aggregation_epoch_start_time_(QuicTime::Zero()), |
+ aggregation_epoch_bytes_(0), |
min_rtt_(QuicTime::Delta::Zero()), |
min_rtt_timestamp_(QuicTime::Zero()), |
congestion_window_(initial_tcp_congestion_window * kDefaultTCPMSS), |
@@ -209,6 +212,12 @@ void BbrSender::OnCongestionEvent(bool /*rtt_updated*/, |
QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 1, 2); |
UpdateAckSpacing(event_time, last_acked_packet, acked_packets); |
} |
+ if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes) { |
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 1, |
+ 2); |
+ UpdateAckAggregationBytes( |
+ event_time, sampler_.total_bytes_acked() - total_bytes_acked_before); |
+ } |
} |
// Handle logic specific to PROBE_BW mode. |
@@ -508,6 +517,29 @@ void BbrSender::UpdateAckSpacing(QuicTime ack_time, |
max_ack_spacing_.Update(ack_spacing, round_trip_count_); |
} |
+// TODO(ianswett): Move this logic into BandwidthSampler. |
+void BbrSender::UpdateAckAggregationBytes(QuicTime ack_time, |
+ QuicByteCount newly_acked_bytes) { |
+ // Compute how many bytes are expected to be delivered, assuming max bandwidth |
+ // is correct. |
+ QuicByteCount expected_bytes_acked = |
+ max_bandwidth_.GetBest() * (ack_time - aggregation_epoch_start_time_); |
+ // Reset the current aggregation epoch as soon as the ack arrival rate is less |
+ // than or equal to the max bandwidth. |
+ if (aggregation_epoch_bytes_ <= expected_bytes_acked) { |
+ // Reset to start measuring a new aggregation epoch. |
+ aggregation_epoch_bytes_ = newly_acked_bytes; |
+ aggregation_epoch_start_time_ = ack_time; |
+ return; |
+ } |
+ |
+ // Compute how many extra bytes were delivered vs max bandwidth. |
+ // Include the bytes most recently acknowledged to account for stretch acks. |
+ aggregation_epoch_bytes_ += newly_acked_bytes; |
+ max_ack_height_.Update(aggregation_epoch_bytes_ - expected_bytes_acked, |
+ round_trip_count_); |
+} |
+ |
void BbrSender::CalculatePacingRate() { |
if (BandwidthEstimate().IsZero()) { |
return; |
@@ -547,6 +579,11 @@ void BbrSender::CalculateCongestionWindow(QuicByteCount bytes_acked) { |
QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_spacing2, 2, 2); |
// Add CWND for inter-ack spacing once STARTUP has been exited. |
target_window += max_ack_spacing_.GetBest() * BandwidthEstimate(); |
+ } else if (FLAGS_quic_reloadable_flag_quic_bbr_ack_aggregation_bytes && |
+ is_at_full_bandwidth_) { |
+ QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_bbr_ack_aggregation_bytes, 2, |
+ 2); |
+ target_window += max_ack_height_.GetBest(); |
} |
// Instead of immediately setting the target CWND as the new one, BBR grows |