1 // Copyright (c) 2015 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 // TCP cubic send side congestion algorithm, emulates the behavior of TCP cubic.
6 
7 #ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
8 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
9 
10 #include <cstdint>
11 #include <string>
12 
13 #include "quiche/quic/core/congestion_control/cubic_bytes.h"
14 #include "quiche/quic/core/congestion_control/hybrid_slow_start.h"
15 #include "quiche/quic/core/congestion_control/prr_sender.h"
16 #include "quiche/quic/core/congestion_control/send_algorithm_interface.h"
17 #include "quiche/quic/core/quic_bandwidth.h"
18 #include "quiche/quic/core/quic_connection_stats.h"
19 #include "quiche/quic/core/quic_packets.h"
20 #include "quiche/quic/core/quic_time.h"
21 #include "quiche/quic/platform/api/quic_export.h"
22 
23 namespace quic {
24 
25 class RttStats;
26 
27 // Maximum window to allow when doing bandwidth resumption.
28 inline constexpr QuicPacketCount kMaxResumptionCongestionWindow = 200;
29 
30 namespace test {
31 class TcpCubicSenderBytesPeer;
32 }  // namespace test
33 
34 class QUICHE_EXPORT TcpCubicSenderBytes : public SendAlgorithmInterface {
35  public:
36   TcpCubicSenderBytes(const QuicClock* clock, const RttStats* rtt_stats,
37                       bool reno, QuicPacketCount initial_tcp_congestion_window,
38                       QuicPacketCount max_congestion_window,
39                       QuicConnectionStats* stats);
40   TcpCubicSenderBytes(const TcpCubicSenderBytes&) = delete;
41   TcpCubicSenderBytes& operator=(const TcpCubicSenderBytes&) = delete;
42   ~TcpCubicSenderBytes() override;
43 
44   // Start implementation of SendAlgorithmInterface.
45   void SetFromConfig(const QuicConfig& config,
46                      Perspective perspective) override;
ApplyConnectionOptions(const QuicTagVector &)47   void ApplyConnectionOptions(
48       const QuicTagVector& /*connection_options*/) override {}
49   void AdjustNetworkParameters(const NetworkParams& params) override;
50   void SetNumEmulatedConnections(int num_connections);
51   void SetInitialCongestionWindowInPackets(
52       QuicPacketCount congestion_window) override;
53   void OnConnectionMigration() override;
54   void OnCongestionEvent(bool rtt_updated, QuicByteCount prior_in_flight,
55                          QuicTime event_time,
56                          const AckedPacketVector& acked_packets,
57                          const LostPacketVector& lost_packets,
58                          QuicPacketCount num_ect,
59                          QuicPacketCount num_ce) override;
60   void OnPacketSent(QuicTime sent_time, QuicByteCount bytes_in_flight,
61                     QuicPacketNumber packet_number, QuicByteCount bytes,
62                     HasRetransmittableData is_retransmittable) override;
OnPacketNeutered(QuicPacketNumber)63   void OnPacketNeutered(QuicPacketNumber /*packet_number*/) override {}
64   void OnRetransmissionTimeout(bool packets_retransmitted) override;
65   bool CanSend(QuicByteCount bytes_in_flight) override;
66   QuicBandwidth PacingRate(QuicByteCount bytes_in_flight) const override;
67   QuicBandwidth BandwidthEstimate() const override;
HasGoodBandwidthEstimateForResumption()68   bool HasGoodBandwidthEstimateForResumption() const override { return false; }
69   QuicByteCount GetCongestionWindow() const override;
70   QuicByteCount GetSlowStartThreshold() const override;
71   CongestionControlType GetCongestionControlType() const override;
72   bool InSlowStart() const override;
73   bool InRecovery() const override;
74   std::string GetDebugState() const override;
75   void OnApplicationLimited(QuicByteCount bytes_in_flight) override;
PopulateConnectionStats(QuicConnectionStats *)76   void PopulateConnectionStats(QuicConnectionStats* /*stats*/) const override {}
EnableECT0()77   bool EnableECT0() override { return false; }
EnableECT1()78   bool EnableECT1() override { return false; }
79   // End implementation of SendAlgorithmInterface.
80 
min_congestion_window()81   QuicByteCount min_congestion_window() const { return min_congestion_window_; }
82 
83  protected:
84   // Compute the TCP Reno beta based on the current number of connections.
85   float RenoBeta() const;
86 
87   bool IsCwndLimited(QuicByteCount bytes_in_flight) const;
88 
89   // TODO(ianswett): Remove these and migrate to OnCongestionEvent.
90   void OnPacketAcked(QuicPacketNumber acked_packet_number,
91                      QuicByteCount acked_bytes, QuicByteCount prior_in_flight,
92                      QuicTime event_time);
93   void SetCongestionWindowFromBandwidthAndRtt(QuicBandwidth bandwidth,
94                                               QuicTime::Delta rtt);
95   void SetMinCongestionWindowInPackets(QuicPacketCount congestion_window);
96   void ExitSlowstart();
97   void OnPacketLost(QuicPacketNumber packet_number, QuicByteCount lost_bytes,
98                     QuicByteCount prior_in_flight);
99   void MaybeIncreaseCwnd(QuicPacketNumber acked_packet_number,
100                          QuicByteCount acked_bytes,
101                          QuicByteCount prior_in_flight, QuicTime event_time);
102   void HandleRetransmissionTimeout();
103 
104  private:
105   friend class test::TcpCubicSenderBytesPeer;
106 
107   HybridSlowStart hybrid_slow_start_;
108   PrrSender prr_;
109   const RttStats* rtt_stats_;
110   QuicConnectionStats* stats_;
111 
112   // If true, Reno congestion control is used instead of Cubic.
113   const bool reno_;
114 
115   // Number of connections to simulate.
116   uint32_t num_connections_;
117 
118   // Track the largest packet that has been sent.
119   QuicPacketNumber largest_sent_packet_number_;
120 
121   // Track the largest packet that has been acked.
122   QuicPacketNumber largest_acked_packet_number_;
123 
124   // Track the largest packet number outstanding when a CWND cutback occurs.
125   QuicPacketNumber largest_sent_at_last_cutback_;
126 
127   // Whether to use 4 packets as the actual min, but pace lower.
128   bool min4_mode_;
129 
130   // Whether the last loss event caused us to exit slowstart.
131   // Used for stats collection of slowstart_packets_lost
132   bool last_cutback_exited_slowstart_;
133 
134   // When true, exit slow start with large cutback of congestion window.
135   bool slow_start_large_reduction_;
136 
137   // When true, use unity pacing instead of PRR.
138   bool no_prr_;
139 
140   CubicBytes cubic_;
141 
142   // ACK counter for the Reno implementation.
143   uint64_t num_acked_packets_;
144 
145   // Congestion window in bytes.
146   QuicByteCount congestion_window_;
147 
148   // Minimum congestion window in bytes.
149   QuicByteCount min_congestion_window_;
150 
151   // Maximum congestion window in bytes.
152   QuicByteCount max_congestion_window_;
153 
154   // Slow start congestion window in bytes, aka ssthresh.
155   QuicByteCount slowstart_threshold_;
156 
157   // Initial TCP congestion window in bytes. This variable can only be set when
158   // this algorithm is created.
159   const QuicByteCount initial_tcp_congestion_window_;
160 
161   // Initial maximum TCP congestion window in bytes. This variable can only be
162   // set when this algorithm is created.
163   const QuicByteCount initial_max_tcp_congestion_window_;
164 
165   // The minimum window when exiting slow start with large reduction.
166   QuicByteCount min_slow_start_exit_window_;
167 };
168 
169 }  // namespace quic
170 
171 #endif  // QUICHE_QUIC_CORE_CONGESTION_CONTROL_TCP_CUBIC_SENDER_BYTES_H_
172