-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathrtt.go
71 lines (60 loc) · 2.23 KB
/
rtt.go
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
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package quic
import (
"time"
)
type rttState struct {
minRTT time.Duration
latestRTT time.Duration
smoothedRTT time.Duration
rttvar time.Duration // RTT variation
firstSampleTime time.Time // time of first RTT sample
}
func (r *rttState) init() {
r.minRTT = -1 // -1 indicates the first sample has not been taken yet
// "[...] the initial RTT SHOULD be set to 333 milliseconds."
// https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.2-1
const initialRTT = 333 * time.Millisecond
// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-12
r.smoothedRTT = initialRTT
r.rttvar = initialRTT / 2
}
func (r *rttState) establishPersistentCongestion() {
// "Endpoints SHOULD set the min_rtt to the newest RTT sample
// after persistent congestion is established."
// https://www.rfc-editor.org/rfc/rfc9002#section-5.2-5
r.minRTT = r.latestRTT
}
// updateSample is called when we generate a new RTT sample.
// https://www.rfc-editor.org/rfc/rfc9002.html#section-5
func (r *rttState) updateSample(now time.Time, handshakeConfirmed bool, spaceID numberSpace, latestRTT, ackDelay, maxAckDelay time.Duration) {
r.latestRTT = latestRTT
if r.minRTT < 0 {
// First RTT sample.
// "min_rtt MUST be set to the latest_rtt on the first RTT sample."
// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.2-2
r.minRTT = latestRTT
// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-14
r.smoothedRTT = latestRTT
r.rttvar = latestRTT / 2
r.firstSampleTime = now
return
}
// "min_rtt MUST be set to the lesser of min_rtt and latest_rtt [...]
// on all other samples."
// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.2-2
r.minRTT = min(r.minRTT, latestRTT)
// https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-16
if handshakeConfirmed {
ackDelay = min(ackDelay, maxAckDelay)
}
adjustedRTT := latestRTT - ackDelay
if adjustedRTT < r.minRTT {
adjustedRTT = latestRTT
}
rttvarSample := abs(r.smoothedRTT - adjustedRTT)
r.rttvar = (3*r.rttvar + rttvarSample) / 4
r.smoothedRTT = ((7 * r.smoothedRTT) + adjustedRTT) / 8
}