File: rtt.go

package info (click to toggle)
golang-golang-x-net 1%3A0.27.0-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 8,636 kB
  • sloc: asm: 18; makefile: 12; sh: 7
file content (73 lines) | stat: -rw-r--r-- 2,303 bytes parent folder | download | duplicates (4)
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
// 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.

//go:build go1.21

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
}

// updateRTTSample 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
}