Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
rtt_estimator.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
6
7#include <algorithm>
8#include <cmath>
9
11{
12
14 : smoothed_rtt_(kInitialRtt)
15 , rttvar_(kInitialRtt / 2)
16 , min_rtt_(std::chrono::microseconds::max())
17 , latest_rtt_(std::chrono::microseconds{0})
18 , max_ack_delay_(kDefaultMaxAckDelay)
19 , initial_rtt_(kInitialRtt)
20 , first_sample_(true)
21{
22}
23
24rtt_estimator::rtt_estimator(std::chrono::microseconds initial_rtt,
25 std::chrono::microseconds max_ack_delay)
26 : smoothed_rtt_(initial_rtt)
27 , rttvar_(initial_rtt / 2)
28 , min_rtt_(std::chrono::microseconds::max())
29 , latest_rtt_(std::chrono::microseconds{0})
30 , max_ack_delay_(max_ack_delay)
31 , initial_rtt_(initial_rtt)
32 , first_sample_(true)
33{
34}
35
36auto rtt_estimator::update(std::chrono::microseconds latest_rtt,
37 std::chrono::microseconds ack_delay,
38 bool is_handshake_confirmed) -> void
39{
40 latest_rtt_ = latest_rtt;
41
42 // Update min_rtt (RFC 9002 Section 5.2)
43 if (latest_rtt < min_rtt_)
44 {
45 min_rtt_ = latest_rtt;
46 }
47
48 // Adjust RTT sample by subtracting ACK delay (RFC 9002 Section 5.3)
49 auto adjusted_rtt = latest_rtt;
50 if (is_handshake_confirmed)
51 {
52 // Only subtract ACK delay for handshake-confirmed samples
53 // and only up to max_ack_delay
54 auto effective_ack_delay = std::min(ack_delay, max_ack_delay_);
55
56 // Don't adjust RTT below min_rtt
57 if (adjusted_rtt > min_rtt_ + effective_ack_delay)
58 {
59 adjusted_rtt -= effective_ack_delay;
60 }
61 else if (adjusted_rtt > min_rtt_)
62 {
63 adjusted_rtt = min_rtt_;
64 }
65 }
66
67 if (first_sample_)
68 {
69 // First RTT sample (RFC 9002 Section 5.3)
70 smoothed_rtt_ = adjusted_rtt;
71 rttvar_ = adjusted_rtt / 2;
72 first_sample_ = false;
73 }
74 else
75 {
76 // Subsequent RTT samples (RFC 9002 Section 5.3)
77 // rttvar = 3/4 * rttvar + 1/4 * |smoothed_rtt - adjusted_rtt|
78 auto rtt_diff = smoothed_rtt_ > adjusted_rtt
79 ? smoothed_rtt_ - adjusted_rtt
80 : adjusted_rtt - smoothed_rtt_;
81
82 rttvar_ = std::chrono::microseconds{
83 (3 * rttvar_.count() + rtt_diff.count()) / 4};
84
85 // smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt
86 smoothed_rtt_ = std::chrono::microseconds{
87 (7 * smoothed_rtt_.count() + adjusted_rtt.count()) / 8};
88 }
89}
90
91auto rtt_estimator::pto() const noexcept -> std::chrono::microseconds
92{
93 // PTO = smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay
94 // (RFC 9002 Section 6.2.1)
95 auto granularity_us = std::chrono::duration_cast<std::chrono::microseconds>(kGranularity);
96 auto four_rttvar = std::chrono::microseconds{4 * rttvar_.count()};
97 auto pto_value = smoothed_rtt_ + std::max(four_rttvar, granularity_us) + max_ack_delay_;
98
99 return pto_value;
100}
101
103{
104 smoothed_rtt_ = initial_rtt_;
105 rttvar_ = initial_rtt_ / 2;
106 min_rtt_ = std::chrono::microseconds::max();
107 latest_rtt_ = std::chrono::microseconds{0};
108 first_sample_ = true;
109}
110
111} // namespace kcenon::network::protocols::quic
std::chrono::microseconds rttvar_
RTT variance (RFC 9002 Section 5.3)
auto update(std::chrono::microseconds latest_rtt, std::chrono::microseconds ack_delay, bool is_handshake_confirmed=true) -> void
Update RTT estimate from an ACK (RFC 9002 Section 5.3)
auto pto() const noexcept -> std::chrono::microseconds
Calculate probe timeout duration (RFC 9002 Section 6.2.1)
std::chrono::microseconds smoothed_rtt_
Smoothed RTT (RFC 9002 Section 5.3)
std::chrono::microseconds max_ack_delay_
Maximum ACK delay (from transport parameters)
auto reset() -> void
Reset RTT estimator to initial state.
static constexpr auto kGranularity
Timer granularity (RFC 9002 Section 6.1.2)