1 // 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_PROBE_BW_H_ 6 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_PROBE_BW_H_ 7 8 #include <cstdint> 9 10 #include "quiche/quic/core/congestion_control/bbr2_misc.h" 11 #include "quiche/quic/core/quic_time.h" 12 #include "quiche/quic/core/quic_types.h" 13 #include "quiche/quic/platform/api/quic_export.h" 14 #include "quiche/quic/platform/api/quic_flags.h" 15 16 namespace quic { 17 18 class Bbr2Sender; 19 class QUICHE_EXPORT Bbr2ProbeBwMode final : public Bbr2ModeBase { 20 public: 21 using Bbr2ModeBase::Bbr2ModeBase; 22 23 void Enter(QuicTime now, 24 const Bbr2CongestionEvent* congestion_event) override; Leave(QuicTime,const Bbr2CongestionEvent *)25 void Leave(QuicTime /*now*/, 26 const Bbr2CongestionEvent* /*congestion_event*/) override {} 27 28 Bbr2Mode OnCongestionEvent( 29 QuicByteCount prior_in_flight, QuicTime event_time, 30 const AckedPacketVector& acked_packets, 31 const LostPacketVector& lost_packets, 32 const Bbr2CongestionEvent& congestion_event) override; 33 34 Limits<QuicByteCount> GetCwndLimits() const override; 35 36 bool IsProbingForBandwidth() const override; 37 38 Bbr2Mode OnExitQuiescence(QuicTime now, 39 QuicTime quiescence_start_time) override; 40 41 enum class CyclePhase : uint8_t { 42 PROBE_NOT_STARTED, 43 PROBE_UP, 44 PROBE_DOWN, 45 PROBE_CRUISE, 46 PROBE_REFILL, 47 }; 48 49 static const char* CyclePhaseToString(CyclePhase phase); 50 51 struct QUICHE_EXPORT DebugState { 52 CyclePhase phase; 53 QuicTime cycle_start_time = QuicTime::Zero(); 54 QuicTime phase_start_time = QuicTime::Zero(); 55 }; 56 57 DebugState ExportDebugState() const; 58 59 private: 60 const Bbr2Params& Params() const; 61 float PacingGainForPhase(CyclePhase phase) const; 62 63 void UpdateProbeUp(QuicByteCount prior_in_flight, 64 const Bbr2CongestionEvent& congestion_event); 65 void UpdateProbeDown(QuicByteCount prior_in_flight, 66 const Bbr2CongestionEvent& congestion_event); 67 void UpdateProbeCruise(const Bbr2CongestionEvent& congestion_event); 68 void UpdateProbeRefill(const Bbr2CongestionEvent& congestion_event); 69 70 enum AdaptUpperBoundsResult : uint8_t { 71 ADAPTED_OK, 72 ADAPTED_PROBED_TOO_HIGH, 73 NOT_ADAPTED_INFLIGHT_HIGH_NOT_SET, 74 NOT_ADAPTED_INVALID_SAMPLE, 75 }; 76 77 // Return whether adapted inflight_hi. If inflight is too high, this function 78 // will not adapt inflight_hi and will return false. 79 AdaptUpperBoundsResult MaybeAdaptUpperBounds( 80 const Bbr2CongestionEvent& congestion_event); 81 82 void EnterProbeDown(bool probed_too_high, bool stopped_risky_probe, 83 QuicTime now); 84 void EnterProbeCruise(QuicTime now); 85 void EnterProbeRefill(uint64_t probe_up_rounds, QuicTime now); 86 void EnterProbeUp(QuicTime now); 87 88 // Call right before the exit of PROBE_DOWN. 89 void ExitProbeDown(); 90 91 float PercentTimeElapsedToProbeBandwidth( 92 const Bbr2CongestionEvent& congestion_event) const; 93 94 bool IsTimeToProbeBandwidth( 95 const Bbr2CongestionEvent& congestion_event) const; 96 bool HasStayedLongEnoughInProbeDown( 97 const Bbr2CongestionEvent& congestion_event) const; 98 bool HasCycleLasted(QuicTime::Delta duration, 99 const Bbr2CongestionEvent& congestion_event) const; 100 bool HasPhaseLasted(QuicTime::Delta duration, 101 const Bbr2CongestionEvent& congestion_event) const; 102 bool IsTimeToProbeForRenoCoexistence( 103 double probe_wait_fraction, 104 const Bbr2CongestionEvent& congestion_event) const; 105 106 void RaiseInflightHighSlope(); 107 void ProbeInflightHighUpward(const Bbr2CongestionEvent& congestion_event); 108 109 struct QUICHE_EXPORT Cycle { 110 QuicTime cycle_start_time = QuicTime::Zero(); 111 CyclePhase phase = CyclePhase::PROBE_NOT_STARTED; 112 uint64_t rounds_in_phase = 0; 113 QuicTime phase_start_time = QuicTime::Zero(); 114 QuicRoundTripCount rounds_since_probe = 0; 115 QuicTime::Delta probe_wait_time = QuicTime::Delta::Zero(); 116 uint64_t probe_up_rounds = 0; 117 QuicByteCount probe_up_bytes = std::numeric_limits<QuicByteCount>::max(); 118 QuicByteCount probe_up_acked = 0; 119 bool probe_up_app_limited_since_inflight_hi_limited_ = false; 120 // Whether max bandwidth filter window has advanced in this cycle. It is 121 // advanced once per cycle. 122 bool has_advanced_max_bw = false; 123 bool is_sample_from_probing = false; 124 } cycle_; 125 126 bool last_cycle_probed_too_high_; 127 bool last_cycle_stopped_risky_probe_; 128 }; 129 130 QUICHE_EXPORT std::ostream& operator<<( 131 std::ostream& os, const Bbr2ProbeBwMode::DebugState& state); 132 133 QUICHE_EXPORT std::ostream& operator<<(std::ostream& os, 134 const Bbr2ProbeBwMode::CyclePhase phase); 135 136 } // namespace quic 137 138 #endif // QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_PROBE_BW_H_ 139