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