blob: 4ad351e32cd68c4f498df073e9b6d741e641232e [file] [log] [blame]
QUICHE team7872c772019-07-23 10:19:37 -04001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_
6#define QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_
7
8#include <algorithm>
9#include <limits>
10
11#include "net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h"
12#include "net/third_party/quiche/src/quic/core/congestion_control/windowed_filter.h"
13#include "net/third_party/quiche/src/quic/core/quic_bandwidth.h"
14#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
15#include "net/third_party/quiche/src/quic/core/quic_time.h"
16#include "net/third_party/quiche/src/quic/core/quic_types.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
wub174cb5c2019-08-06 08:54:26 -070018#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
QUICHE team7872c772019-07-23 10:19:37 -040019#include "net/quic/platform/impl/quic_export_impl.h"
20
21namespace quic {
22
QUICHE team7872c772019-07-23 10:19:37 -040023template <typename T>
24class QUIC_EXPORT_PRIVATE Limits {
25 public:
26 Limits(T min, T max) : min_(min), max_(max) {}
27
28 // If [min, max] is an empty range, i.e. min > max, this function returns max,
29 // because typically a value larger than max means "risky".
30 T ApplyLimits(T raw_value) const {
31 return std::min(max_, std::max(min_, raw_value));
32 }
33
34 T Min() const { return min_; }
35 T Max() const { return max_; }
36
37 private:
38 T min_;
39 T max_;
40};
41
42template <typename T>
43QUIC_EXPORT_PRIVATE inline Limits<T> MinMax(T min, T max) {
44 return Limits<T>(min, max);
45}
46
47template <typename T>
48QUIC_EXPORT_PRIVATE inline Limits<T> NoLessThan(T min) {
49 return Limits<T>(min, std::numeric_limits<T>::max());
50}
51
52template <typename T>
53QUIC_EXPORT_PRIVATE inline Limits<T> NoGreaterThan(T max) {
54 return Limits<T>(std::numeric_limits<T>::min(), max);
55}
56
57template <typename T>
58QUIC_EXPORT_PRIVATE inline Limits<T> Unlimited() {
59 return Limits<T>(std::numeric_limits<T>::min(),
60 std::numeric_limits<T>::max());
61}
62
63template <typename T>
64QUIC_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& os,
65 const Limits<T>& limits) {
66 return os << "[" << limits.Min() << ", " << limits.Max() << "]";
67}
68
69// Bbr2Params contains all parameters of a Bbr2Sender.
70struct QUIC_EXPORT_PRIVATE Bbr2Params {
71 Bbr2Params(QuicByteCount cwnd_min, QuicByteCount cwnd_max)
72 : cwnd_limits(cwnd_min, cwnd_max) {}
73
74 /*
75 * STARTUP parameters.
76 */
77
78 // The gain for both CWND and PacingRate at startup.
79 // TODO(wub): Maybe change to the newly derived value of 2.773 (4 * ln(2)).
80 float startup_gain = 2.885;
81
82 // Full bandwidth is declared if the total bandwidth growth is less than
83 // |startup_full_bw_threshold| times in the last |startup_full_bw_rounds|
84 // round trips.
85 float startup_full_bw_threshold = 1.25;
86
87 QuicRoundTripCount startup_full_bw_rounds = 3;
88
89 // The minimum number of loss marking events to exit STARTUP.
wubf975eac2019-08-19 19:41:01 -070090 int64_t startup_full_loss_count =
91 GetQuicFlag(FLAGS_quic_bbr2_default_startup_full_loss_count);
QUICHE team7872c772019-07-23 10:19:37 -040092
93 /*
94 * DRAIN parameters.
95 */
96 float drain_cwnd_gain = 2.885;
97 float drain_pacing_gain = 1.0 / 2.885;
98
99 /*
100 * PROBE_BW parameters.
101 */
102 // Max amount of randomness to inject in round counting for Reno-coexistence.
103 QuicRoundTripCount probe_bw_max_probe_rand_rounds = 2;
104
105 // Max number of rounds before probing for Reno-coexistence.
106 uint32_t probe_bw_probe_max_rounds = 63;
107
108 // Multiplier to get Reno-style probe epoch duration as: k * BDP round trips.
109 // If zero, disables Reno-style BDP-scaled coexistence mechanism.
110 float probe_bw_probe_reno_gain = 1.0;
111
112 // Minimum duration for BBR-native probes.
113 QuicTime::Delta probe_bw_probe_base_duration =
wub174cb5c2019-08-06 08:54:26 -0700114 QuicTime::Delta::FromMilliseconds(
115 GetQuicFlag(FLAGS_quic_bbr2_default_probe_bw_base_duration_ms));
QUICHE team7872c772019-07-23 10:19:37 -0400116
wub174cb5c2019-08-06 08:54:26 -0700117 // The upper bound of the random amount of BBR-native probes.
QUICHE team7872c772019-07-23 10:19:37 -0400118 QuicTime::Delta probe_bw_probe_max_rand_duration =
wub174cb5c2019-08-06 08:54:26 -0700119 QuicTime::Delta::FromMilliseconds(
120 GetQuicFlag(FLAGS_quic_bbr2_default_probe_bw_max_rand_duration_ms));
QUICHE team7872c772019-07-23 10:19:37 -0400121
122 // Multiplier to get target inflight (as multiple of BDP) for PROBE_UP phase.
123 float probe_bw_probe_inflight_gain = 1.25;
124
125 // Pacing gains.
126 float probe_bw_probe_up_pacing_gain = 1.25;
127 float probe_bw_probe_down_pacing_gain = 0.75;
128 float probe_bw_default_pacing_gain = 1.0;
129
130 float probe_bw_cwnd_gain = 2.0;
131
132 /*
133 * PROBE_RTT parameters.
134 */
135 float probe_rtt_inflight_target_bdp_fraction = 0.5;
wub174cb5c2019-08-06 08:54:26 -0700136 QuicTime::Delta probe_rtt_period = QuicTime::Delta::FromMilliseconds(
137 GetQuicFlag(FLAGS_quic_bbr2_default_probe_rtt_period_ms));
QUICHE team7872c772019-07-23 10:19:37 -0400138 QuicTime::Delta probe_rtt_duration = QuicTime::Delta::FromMilliseconds(200);
139
140 /*
141 * Parameters used by multiple modes.
142 */
143
144 // The initial value of the max ack height filter's window length.
145 QuicRoundTripCount initial_max_ack_height_filter_window = 10;
146
147 // Fraction of unutilized headroom to try to leave in path upon high loss.
148 float inflight_hi_headroom = 0.15;
149
150 // Estimate startup/bw probing has gone too far if loss rate exceeds this.
wub5a6ea9a2019-08-09 13:10:49 -0700151 float loss_threshold = GetQuicFlag(FLAGS_quic_bbr2_default_loss_threshold);
QUICHE team7872c772019-07-23 10:19:37 -0400152
153 Limits<QuicByteCount> cwnd_limits;
154};
155
156class QUIC_EXPORT_PRIVATE RoundTripCounter {
157 public:
158 RoundTripCounter();
159
160 QuicRoundTripCount Count() const { return round_trip_count_; }
161
162 QuicPacketNumber last_sent_packet() const { return last_sent_packet_; }
163
164 // Must be called in ascending packet number order.
165 void OnPacketSent(QuicPacketNumber packet_number);
166
167 // Return whether a round trip has just completed.
168 bool OnPacketsAcked(QuicPacketNumber last_acked_packet);
169
170 void RestartRound();
171
172 private:
173 QuicRoundTripCount round_trip_count_;
174 QuicPacketNumber last_sent_packet_;
175 // The last sent packet number of the current round trip.
176 QuicPacketNumber end_of_round_trip_;
177};
178
179class QUIC_EXPORT_PRIVATE MinRttFilter {
180 public:
181 MinRttFilter(QuicTime::Delta initial_min_rtt,
182 QuicTime initial_min_rtt_timestamp);
183
184 void Update(QuicTime::Delta sample_rtt, QuicTime now);
185
186 void ForceUpdate(QuicTime::Delta sample_rtt, QuicTime now);
187
188 QuicTime::Delta Get() const { return min_rtt_; }
189
190 QuicTime GetTimestamp() const { return min_rtt_timestamp_; }
191
192 private:
193 QuicTime::Delta min_rtt_;
194 // Time when the current value of |min_rtt_| was assigned.
195 QuicTime min_rtt_timestamp_;
196};
197
198class QUIC_EXPORT_PRIVATE Bbr2MaxBandwidthFilter {
199 public:
200 void Update(QuicBandwidth sample) {
201 max_bandwidth_[1] = std::max(sample, max_bandwidth_[1]);
202 }
203
204 void Advance() {
205 if (max_bandwidth_[1].IsZero()) {
206 return;
207 }
208
209 max_bandwidth_[0] = max_bandwidth_[1];
210 max_bandwidth_[1] = QuicBandwidth::Zero();
211 }
212
213 QuicBandwidth Get() const {
214 return std::max(max_bandwidth_[0], max_bandwidth_[1]);
215 }
216
217 private:
218 QuicBandwidth max_bandwidth_[2] = {QuicBandwidth::Zero(),
219 QuicBandwidth::Zero()};
220};
221
222// Information that are meaningful only when Bbr2Sender::OnCongestionEvent is
223// running.
224struct QUIC_EXPORT_PRIVATE Bbr2CongestionEvent {
225 QuicTime event_time = QuicTime::Zero();
226
227 // The congestion window prior to the processing of the ack/loss events.
228 QuicByteCount prior_cwnd;
229
230 // Total bytes inflight after the processing of the ack/loss events.
231 QuicByteCount bytes_in_flight = 0;
232
233 // Total bytes acked from acks in this event.
234 QuicByteCount bytes_acked = 0;
235
236 // Total bytes lost from losses in this event.
237 QuicByteCount bytes_lost = 0;
238
239 // Whether acked_packets indicates the end of a round trip.
240 bool end_of_round_trip = false;
241
242 // Whether the last bandwidth sample from acked_packets is app limited.
243 // false if acked_packets is empty.
244 bool last_sample_is_app_limited = false;
245
246 // When the event happened, whether the sender is probing for bandwidth.
247 bool is_probing_for_bandwidth = false;
248
249 // Minimum rtt of all bandwidth samples from acked_packets.
250 // QuicTime::Delta::Infinite() if acked_packets is empty.
251 QuicTime::Delta sample_min_rtt = QuicTime::Delta::Infinite();
252
wubeedb91b2019-07-23 14:31:57 -0700253 // Maximum bandwidth of all bandwidth samples from acked_packets.
254 QuicBandwidth sample_max_bandwidth = QuicBandwidth::Zero();
255
QUICHE team7872c772019-07-23 10:19:37 -0400256 // Send time state of the largest-numbered packet in this event.
257 // SendTimeState send_time_state;
258 struct {
259 QuicPacketNumber packet_number;
260 BandwidthSample bandwidth_sample;
261 // Total bytes acked while |packet| is inflight.
262 QuicByteCount inflight_sample;
263 } last_acked_sample;
264
265 struct {
266 QuicPacketNumber packet_number;
267 SendTimeState send_time_state;
268 } last_lost_sample;
269};
270
271QUIC_EXPORT_PRIVATE const SendTimeState& SendStateOfLargestPacket(
272 const Bbr2CongestionEvent& congestion_event);
273
QUICHE team7872c772019-07-23 10:19:37 -0400274// Bbr2NetworkModel takes low level congestion signals(packets sent/acked/lost)
275// as input and produces BBRv2 model parameters like inflight_(hi|lo),
276// bandwidth_(hi|lo), bandwidth and rtt estimates, etc.
277class QUIC_EXPORT_PRIVATE Bbr2NetworkModel {
278 public:
279 Bbr2NetworkModel(const Bbr2Params* params,
280 QuicTime::Delta initial_rtt,
281 QuicTime initial_rtt_timestamp,
282 float cwnd_gain,
283 float pacing_gain);
284
285 void OnPacketSent(QuicTime sent_time,
286 QuicByteCount bytes_in_flight,
287 QuicPacketNumber packet_number,
288 QuicByteCount bytes,
289 HasRetransmittableData is_retransmittable);
290
291 void OnCongestionEventStart(QuicTime event_time,
292 const AckedPacketVector& acked_packets,
293 const LostPacketVector& lost_packets,
294 Bbr2CongestionEvent* congestion_event);
295
296 void OnCongestionEventFinish(QuicPacketNumber least_unacked_packet,
297 const Bbr2CongestionEvent& congestion_event);
298
299 // Update the model without a congestion event.
300 // Max bandwidth is updated if |bandwidth| is larger than existing max
301 // bandwidth. Min rtt is updated if |rtt| is non-zero and smaller than
302 // existing min rtt.
303 void UpdateNetworkParameters(QuicBandwidth bandwidth, QuicTime::Delta rtt);
304
305 // Update inflight/bandwidth short-term lower bounds.
306 void AdaptLowerBounds(const Bbr2CongestionEvent& congestion_event);
307
308 // Restart the current round trip as if it is starting now.
309 void RestartRound();
310
311 void AdvanceMaxBandwidthFilter() { max_bandwidth_filter_.Advance(); }
312
313 void OnApplicationLimited() { bandwidth_sampler_.OnAppLimited(); }
314
315 QuicByteCount BDP(QuicBandwidth bandwidth) const {
316 return bandwidth * MinRtt();
317 }
318
319 QuicByteCount BDP(QuicBandwidth bandwidth, float gain) const {
320 return bandwidth * MinRtt() * gain;
321 }
322
323 QuicTime::Delta MinRtt() const { return min_rtt_filter_.Get(); }
324
325 QuicTime MinRttTimestamp() const { return min_rtt_filter_.GetTimestamp(); }
326
327 QuicBandwidth MaxBandwidth() const { return max_bandwidth_filter_.Get(); }
328
wubf35ea982019-08-06 16:19:38 -0700329 QuicByteCount MaxAckHeight() const {
330 return bandwidth_sampler_.max_ack_height();
331 }
QUICHE team7872c772019-07-23 10:19:37 -0400332
333 bool MaybeExpireMinRtt(const Bbr2CongestionEvent& congestion_event);
334
335 QuicBandwidth BandwidthEstimate() const {
336 return std::min(MaxBandwidth(), bandwidth_lo_);
337 }
338
339 QuicRoundTripCount RoundTripCount() const {
340 return round_trip_counter_.Count();
341 }
342
343 bool IsCongestionWindowLimited(
344 const Bbr2CongestionEvent& congestion_event) const;
345
346 bool IsInflightTooHigh(const Bbr2CongestionEvent& congestion_event) const;
347
348 QuicPacketNumber last_sent_packet() const {
349 return round_trip_counter_.last_sent_packet();
350 }
351
352 QuicByteCount total_bytes_acked() const {
353 return bandwidth_sampler_.total_bytes_acked();
354 }
355
356 QuicByteCount total_bytes_lost() const {
357 return bandwidth_sampler_.total_bytes_lost();
358 }
359
360 QuicByteCount total_bytes_sent() const {
361 return bandwidth_sampler_.total_bytes_sent();
362 }
363
364 QuicByteCount bytes_in_flight() const {
365 return total_bytes_sent() - total_bytes_acked() - total_bytes_lost();
366 }
367
368 QuicPacketNumber end_of_app_limited_phase() const {
369 return bandwidth_sampler_.end_of_app_limited_phase();
370 }
371
372 QuicBandwidth bandwidth_latest() const { return bandwidth_latest_; }
373 QuicBandwidth bandwidth_lo() const { return bandwidth_lo_; }
374 void clear_bandwidth_lo() { bandwidth_lo_ = QuicBandwidth::Infinite(); }
375
376 QuicByteCount inflight_latest() const { return inflight_latest_; }
377 QuicByteCount inflight_lo() const { return inflight_lo_; }
378 static QuicByteCount inflight_lo_default() {
379 return std::numeric_limits<QuicByteCount>::max();
380 }
381 void clear_inflight_lo() { inflight_lo_ = inflight_lo_default(); }
382
383 QuicByteCount inflight_hi_with_headroom() const;
384 QuicByteCount inflight_hi() const { return inflight_hi_; }
385 static QuicByteCount inflight_hi_default() {
386 return std::numeric_limits<QuicByteCount>::max();
387 }
388 void set_inflight_hi(QuicByteCount inflight_hi) {
389 inflight_hi_ = inflight_hi;
390 }
391
392 float cwnd_gain() const { return cwnd_gain_; }
393 void set_cwnd_gain(float cwnd_gain) { cwnd_gain_ = cwnd_gain; }
394
395 float pacing_gain() const { return pacing_gain_; }
396 void set_pacing_gain(float pacing_gain) { pacing_gain_ = pacing_gain; }
397
398 private:
399 const Bbr2Params& Params() const { return *params_; }
400 const Bbr2Params* const params_;
401 RoundTripCounter round_trip_counter_;
402
403 // Bandwidth sampler provides BBR with the bandwidth measurements at
404 // individual points.
405 BandwidthSampler bandwidth_sampler_;
406 // The filter that tracks the maximum bandwidth over multiple recent round
407 // trips.
408 Bbr2MaxBandwidthFilter max_bandwidth_filter_;
409 MinRttFilter min_rtt_filter_;
410
QUICHE team7872c772019-07-23 10:19:37 -0400411 // Bytes lost in the current round. Updated once per congestion event.
412 QuicByteCount bytes_lost_in_round_ = 0;
413
414 // Max bandwidth in the current round. Updated once per congestion event.
415 QuicBandwidth bandwidth_latest_ = QuicBandwidth::Zero();
416 // Max bandwidth of recent rounds. Updated once per round.
417 QuicBandwidth bandwidth_lo_ = QuicBandwidth::Infinite();
418
419 // Max inflight in the current round. Updated once per congestion event.
420 QuicByteCount inflight_latest_ = 0;
421 // Max inflight of recent rounds. Updated once per round.
422 QuicByteCount inflight_lo_ = inflight_lo_default();
423 QuicByteCount inflight_hi_ = inflight_hi_default();
424
425 float cwnd_gain_;
426 float pacing_gain_;
427};
428
429enum class Bbr2Mode : uint8_t {
430 // Startup phase of the connection.
431 STARTUP,
432 // After achieving the highest possible bandwidth during the startup, lower
433 // the pacing rate in order to drain the queue.
434 DRAIN,
435 // Cruising mode.
436 PROBE_BW,
437 // Temporarily slow down sending in order to empty the buffer and measure
438 // the real minimum RTT.
439 PROBE_RTT,
440};
441
442QUIC_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& os,
443 const Bbr2Mode& mode) {
444 switch (mode) {
445 case Bbr2Mode::STARTUP:
446 return os << "STARTUP";
447 case Bbr2Mode::DRAIN:
448 return os << "DRAIN";
449 case Bbr2Mode::PROBE_BW:
450 return os << "PROBE_BW";
451 case Bbr2Mode::PROBE_RTT:
452 return os << "PROBE_RTT";
453 }
454 return os << "<Invalid Mode>";
455}
456
457// The base class for all BBRv2 modes. A Bbr2Sender is in one mode at a time,
458// this interface is used to implement mode-specific behaviors.
459class Bbr2Sender;
460class QUIC_EXPORT_PRIVATE Bbr2ModeBase {
461 public:
462 Bbr2ModeBase(const Bbr2Sender* sender, Bbr2NetworkModel* model)
463 : sender_(sender), model_(model) {}
464
465 virtual ~Bbr2ModeBase() = default;
466
467 virtual void Enter(const Bbr2CongestionEvent& congestion_event) = 0;
468
469 virtual Bbr2Mode OnCongestionEvent(
470 QuicByteCount prior_in_flight,
471 QuicTime event_time,
472 const AckedPacketVector& acked_packets,
473 const LostPacketVector& lost_packets,
474 const Bbr2CongestionEvent& congestion_event) = 0;
475
476 virtual Limits<QuicByteCount> GetCwndLimits() const = 0;
477
478 virtual bool IsProbingForBandwidth() const = 0;
479
480 protected:
481 const Bbr2Sender* const sender_;
482 Bbr2NetworkModel* model_;
483};
484
485QUIC_EXPORT_PRIVATE inline QuicByteCount BytesInFlight(
486 const SendTimeState& send_state) {
487 DCHECK(send_state.is_valid);
488 return send_state.total_bytes_sent - send_state.total_bytes_acked -
489 send_state.total_bytes_lost;
490}
491
492} // namespace quic
493
494#endif // QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_MISC_H_