20 return "congestion_avoidance";
35 , max_datagram_size_(max_datagram_size)
36 , congestion_recovery_start_()
47 return bytes_in_flight_ < cwnd_;
49 return bytes_in_flight_ + bytes <= cwnd_;
63 bytes_in_flight_ += bytes;
67 std::chrono::steady_clock::time_point ack_time)
71 if (packet.in_flight && bytes_in_flight_ >= packet.sent_bytes)
73 bytes_in_flight_ -= packet.sent_bytes;
77 if (is_in_recovery(packet.sent_time))
92 cwnd_ += packet.sent_bytes;
95 if (cwnd_ >= ssthresh_)
104 auto increment = (max_datagram_size_ * packet.sent_bytes) / cwnd_;
116 if (packet.in_flight && bytes_in_flight_ >= packet.sent_bytes)
118 bytes_in_flight_ -= packet.sent_bytes;
122 on_congestion_event(packet.sent_time);
126 std::chrono::steady_clock::time_point sent_time) ->
void
129 if (is_in_recovery(sent_time))
135 congestion_recovery_start_ = std::chrono::steady_clock::now();
141 ssthresh_ =
static_cast<size_t>(
142 static_cast<double>(cwnd_) * kLossReductionFactor);
143 cwnd_ = std::max(ssthresh_, minimum_window_);
147 std::chrono::steady_clock::time_point sent_time) ->
void
154 if (is_in_recovery(sent_time))
160 congestion_recovery_start_ = std::chrono::steady_clock::now();
167 ssthresh_ =
static_cast<size_t>(
168 static_cast<double>(cwnd_) * kLossReductionFactor);
169 cwnd_ = std::max(ssthresh_, minimum_window_);
175 cwnd_ = minimum_window_;
178 congestion_recovery_start_ = std::chrono::steady_clock::time_point{};
182 std::chrono::steady_clock::time_point sent_time)
const noexcept ->
bool
190 return sent_time <= congestion_recovery_start_;
195 max_datagram_size_ = size;
196 initial_window_ = kInitialWindowPackets * max_datagram_size_;
197 minimum_window_ = kMinimumWindowPackets * max_datagram_size_;
200 cwnd_ = std::max(cwnd_, minimum_window_);
206 cwnd_ = initial_window_;
207 ssthresh_ = std::numeric_limits<size_t>::max();
208 bytes_in_flight_ = 0;
209 congestion_recovery_start_ = std::chrono::steady_clock::time_point{};
QUIC congestion control (RFC 9002 Section 7)
auto on_packet_acked(const sent_packet &packet, std::chrono::steady_clock::time_point ack_time) -> void
Handle packet acknowledgment (RFC 9002 Section 7.3)
auto set_max_datagram_size(size_t size) -> void
Set max datagram size.
auto on_packet_lost(const sent_packet &packet) -> void
Handle packet loss (RFC 9002 Section 7.3.2)
auto on_congestion_event(std::chrono::steady_clock::time_point sent_time) -> void
Handle congestion event (RFC 9002 Section 7.3.2)
auto on_persistent_congestion(const rtt_estimator &rtt) -> void
Handle persistent congestion detection (RFC 9002 Section 7.6)
congestion_controller()
Default constructor.
auto can_send(size_t bytes=0) const noexcept -> bool
Check if we can send more data.
auto available_window() const noexcept -> size_t
Get available congestion window.
auto on_packet_sent(size_t bytes) -> void
Record bytes sent.
static constexpr size_t kMinimumWindowPackets
Minimum window in packets.
size_t minimum_window_
Minimum window size.
size_t bytes_in_flight_
Bytes currently in flight.
auto reset() -> void
Reset congestion controller to initial state.
auto on_ecn_congestion(std::chrono::steady_clock::time_point sent_time) -> void
Handle ECN congestion signal (RFC 9002 Section 7.1)
size_t max_datagram_size_
Maximum datagram size.
auto is_in_recovery(std::chrono::steady_clock::time_point sent_time) const noexcept -> bool
Check if currently in recovery period.
static constexpr size_t kInitialWindowPackets
Number of datagrams for initial window.
size_t cwnd_
Congestion window in bytes.
size_t initial_window_
Initial window size (for reset)
RTT estimation for QUIC (RFC 9002 Section 5)
congestion_state
States of the congestion controller (RFC 9002 Section 7)
@ slow_start
Exponential growth of cwnd.
@ recovery
Congestion recovery after loss.
@ congestion_avoidance
Linear growth of cwnd.
auto congestion_state_to_string(congestion_state state) noexcept -> const char *
Convert congestion state to string.
Information about a sent packet for loss detection (RFC 9002 Section A.1.1)