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