summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h
blob: 45b5a73835e33764fa12b25fccde42b5a0fe5735 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_PROBE_BW_H_
#define QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_PROBE_BW_H_

#include <cstdint>

#include "net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"

namespace quic {

class Bbr2Sender;
class QUIC_EXPORT_PRIVATE Bbr2ProbeBwMode final : public Bbr2ModeBase {
 public:
  using Bbr2ModeBase::Bbr2ModeBase;

  void Enter(const Bbr2CongestionEvent& congestion_event) override;
  void Leave(const Bbr2CongestionEvent& /*congestion_event*/) override {}

  Bbr2Mode OnCongestionEvent(
      QuicByteCount prior_in_flight,
      QuicTime event_time,
      const AckedPacketVector& acked_packets,
      const LostPacketVector& lost_packets,
      const Bbr2CongestionEvent& congestion_event) override;

  Limits<QuicByteCount> GetCwndLimits() const override;

  bool IsProbingForBandwidth() const override;

  enum class CyclePhase : uint8_t {
    PROBE_NOT_STARTED,
    PROBE_UP,
    PROBE_DOWN,
    PROBE_CRUISE,
    PROBE_REFILL,
  };

  static const char* CyclePhaseToString(CyclePhase phase);

  struct QUIC_EXPORT_PRIVATE DebugState {
    CyclePhase phase;
    QuicTime cycle_start_time = QuicTime::Zero();
    QuicTime phase_start_time = QuicTime::Zero();
  };

  DebugState ExportDebugState() const;

 private:
  const Bbr2Params& Params() const;
  float PacingGainForPhase(CyclePhase phase) const;

  void UpdateProbeUp(QuicByteCount prior_in_flight,
                     const Bbr2CongestionEvent& congestion_event);
  void UpdateProbeDown(QuicByteCount prior_in_flight,
                       const Bbr2CongestionEvent& congestion_event);
  void UpdateProbeCruise(const Bbr2CongestionEvent& congestion_event);
  void UpdateProbeRefill(const Bbr2CongestionEvent& congestion_event);

  enum AdaptUpperBoundsResult : uint8_t {
    ADAPTED_OK,
    ADAPTED_PROBED_TOO_HIGH,
    NOT_ADAPTED_INFLIGHT_HIGH_NOT_SET,
    NOT_ADAPTED_INVALID_SAMPLE,
  };

  // Return whether adapted inflight_hi. If inflight is too high, this function
  // will not adapt inflight_hi and will return false.
  AdaptUpperBoundsResult MaybeAdaptUpperBounds(
      const Bbr2CongestionEvent& congestion_event);

  void EnterProbeDown(bool probed_too_high,
                      bool stopped_risky_probe,
                      const Bbr2CongestionEvent& congestion_event);
  void EnterProbeCruise(const Bbr2CongestionEvent& congestion_event);
  void EnterProbeRefill(uint64_t probe_up_rounds,
                        const Bbr2CongestionEvent& congestion_event);
  void EnterProbeUp(const Bbr2CongestionEvent& congestion_event);

  // Call right before the exit of PROBE_DOWN.
  void ExitProbeDown(const Bbr2CongestionEvent& congestion_event);

  float PercentTimeElapsedToProbeBandwidth(
      const Bbr2CongestionEvent& congestion_event) const;

  bool IsTimeToProbeBandwidth(
      const Bbr2CongestionEvent& congestion_event) const;
  bool HasStayedLongEnoughInProbeDown(
      const Bbr2CongestionEvent& congestion_event) const;
  bool HasCycleLasted(QuicTime::Delta duration,
                      const Bbr2CongestionEvent& congestion_event) const;
  bool HasPhaseLasted(QuicTime::Delta duration,
                      const Bbr2CongestionEvent& congestion_event) const;
  bool IsTimeToProbeForRenoCoexistence(
      double probe_wait_fraction,
      const Bbr2CongestionEvent& congestion_event) const;

  void RaiseInflightHighSlope();
  void ProbeInflightHighUpward(const Bbr2CongestionEvent& congestion_event);

  struct QUIC_EXPORT_PRIVATE Cycle {
    QuicTime cycle_start_time = QuicTime::Zero();
    CyclePhase phase = CyclePhase::PROBE_NOT_STARTED;
    uint64_t rounds_in_phase = 0;
    QuicTime phase_start_time = QuicTime::Zero();
    QuicRoundTripCount rounds_since_probe = 0;
    QuicTime::Delta probe_wait_time = QuicTime::Delta::Zero();
    uint64_t probe_up_rounds = 0;
    QuicByteCount probe_up_bytes = std::numeric_limits<QuicByteCount>::max();
    QuicByteCount probe_up_acked = 0;
    // Whether max bandwidth filter window has advanced in this cycle. It is
    // advanced once per cycle.
    bool has_advanced_max_bw = false;
    bool is_sample_from_probing = false;
  } cycle_;

  bool last_cycle_probed_too_high_;
  bool last_cycle_stopped_risky_probe_;

  // Latched value of --quic_bbr2_exit_probe_bw_down_after_one_rtt.
  const bool exit_probe_down_after_one_rtt_ =
      GetQuicReloadableFlag(quic_bbr2_exit_probe_bw_down_after_one_rtt);
};

QUIC_EXPORT_PRIVATE std::ostream& operator<<(
    std::ostream& os,
    const Bbr2ProbeBwMode::DebugState& state);

QUIC_EXPORT_PRIVATE std::ostream& operator<<(
    std::ostream& os,
    const Bbr2ProbeBwMode::CyclePhase phase);

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_CONGESTION_CONTROL_BBR2_PROBE_BW_H_