c.config.EnableStreamResetPartialDelivery,
false, // ACK_FREQUENCY is not supported yet
)
- c.rttStats = &utils.RTTStats{}
+ c.rttStats = utils.NewRTTStats()
c.connFlowController = flowcontrol.NewConnectionFlowController(
protocol.ByteCount(c.config.InitialConnectionReceiveWindow),
protocol.ByteCount(c.config.MaxConnectionReceiveWindow),
}
func connectionOptRTT(rtt time.Duration) testConnectionOpt {
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(rtt, 0)
- return func(conn *Conn) { conn.rttStats = &rttStats }
+ return func(conn *Conn) { conn.rttStats = rttStats }
}
func connectionOptRetrySrcConnID(rcid protocol.ConnectionID) testConnectionOpt {
func TestConnectionHandleConnectionFlowControlFrames(t *testing.T) {
mockCtrl := gomock.NewController(t)
- connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, &utils.RTTStats{}, utils.DefaultLogger)
+ connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, utils.NewRTTStats(), utils.DefaultLogger)
require.Zero(t, connFC.SendWindowSize())
tc := newServerTestConnection(t, mockCtrl, nil, false, connectionOptConnFlowController(connFC))
now := monotime.Now()
func TestConnectionTransportParameters(t *testing.T) {
mockCtrl := gomock.NewController(t)
var eventRecorder events.Recorder
- connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, &utils.RTTStats{}, utils.DefaultLogger)
+ connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, utils.NewRTTStats(), utils.DefaultLogger)
require.Zero(t, connFC.SendWindowSize())
tc := newServerTestConnection(t,
mockCtrl,
func TestConnectionHandleMaxStreamsFrame(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
mockCtrl := gomock.NewController(t)
- connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, &utils.RTTStats{}, utils.DefaultLogger)
+ connFC := flowcontrol.NewConnectionFlowController(0, 0, nil, utils.NewRTTStats(), utils.DefaultLogger)
tc := newServerTestConnection(t, mockCtrl, nil, false, connectionOptConnFlowController(connFC))
tc.conn.handleTransportParameters(&wire.TransportParameters{})
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
false,
false,
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
false,
false,
}
func testSentPacketHandlerRTTs(t *testing.T, encLevel protocol.EncryptionLevel, usesAckDelay bool) {
- var expectedRTTStats utils.RTTStats
+ expectedRTTStats := utils.NewRTTStats()
expectedRTTStats.SetMaxAckDelay(time.Second)
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.SetMaxAckDelay(time.Second)
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
false,
false,
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
addressValidated,
false,
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
true,
false,
}
func TestSentPacketHandlerDelayBasedLossDetection(t *testing.T) {
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
}
func TestSentPacketHandlerPacketBasedLossDetection(t *testing.T) {
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
var packets packetTracker
var eventRecorder events.Recorder
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.SetMaxAckDelay(25 * time.Millisecond)
rttStats.UpdateRTT(500*time.Millisecond, 0)
rttStats.UpdateRTT(1000*time.Millisecond, 0)
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
}
func TestSentPacketHandlerPacketNumberSpacesPTO(t *testing.T) {
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
const rtt = time.Second
rttStats.UpdateRTT(rtt, 0)
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
true,
false,
func TestSentPacketHandlerCongestion(t *testing.T) {
mockCtrl := gomock.NewController(t)
cong := mocks.NewMockSendAlgorithmWithDebugInfos(mockCtrl)
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
func testSentPacketHandlerRetry(t *testing.T, rtt, expectedRTT time.Duration) {
var initialPackets, appDataPackets packetTracker
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
}
func TestSentPacketHandlerRetryAfterPTO(t *testing.T) {
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
require.Equal(t, []protocol.PacketNumber{pn1, pn2}, packets.Lost)
// no RTT measurement is taken, since the PTO timer fired
- require.Zero(t, rttStats.SmoothedRTT())
+ require.Equal(t, utils.DefaultInitialRTT, rttStats.SmoothedRTT())
}
func TestSentPacketHandlerECN(t *testing.T) {
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
true,
false,
func TestSentPacketHandlerPathProbe(t *testing.T) {
const rtt = 10 * time.Millisecond // RTT of the original path
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(rtt, 0)
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
packets.Lost = packets.Lost[:0]
sph.MigratedPath(now, 1200)
require.Zero(t, sph.getBytesInFlight())
- require.Zero(t, rttStats.SmoothedRTT())
+ require.Equal(t, utils.DefaultInitialRTT, rttStats.SmoothedRTT())
require.Equal(t, []protocol.PacketNumber{pn1, pn2}, packets.Lost)
}
func TestSentPacketHandlerPathProbeAckAndLoss(t *testing.T) {
const rtt = 10 * time.Millisecond // RTT of the original path
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(rtt, 0)
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
binary.BigEndian.PutUint64(b[:], seed)
r := rand.New(rand.NewChaCha8(b))
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rtt := []time.Duration{10 * time.Millisecond, 100 * time.Millisecond, 1000 * time.Millisecond}[r.IntN(3)]
t.Logf("rtt: %dms", rtt.Milliseconds())
rttStats.UpdateRTT(rtt, 0) // RTT of the original path
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
sph := newSentPacketHandler(
0,
1200,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
&utils.ConnectionStats{},
true,
false,
func benchmarkSendAndAcknowledge(b *testing.B, ackEvery, inFlight int) {
b.ReportAllocs()
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
sph := newSentPacketHandler(
0,
1200,
- &rttStats,
+ rttStats,
&utils.ConnectionStats{},
true,
false,
func (c *cubicSender) BandwidthEstimate() Bandwidth {
srtt := c.rttStats.SmoothedRTT()
if srtt == 0 {
- // If we haven't measured an rtt, the bandwidth estimate is unknown.
- return infBandwidth
+ // This should never happen, but if it does, avoid division by zero.
+ srtt = protocol.TimerGranularity
}
return BandwidthFromDelta(c.GetCongestionWindow(), srtt)
}
// At startup make sure we can send.
require.True(t, sender.sender.CanSend(0))
require.Zero(t, sender.sender.TimeUntilSend(0))
- require.Equal(t, infBandwidth, sender.sender.BandwidthEstimate())
const numberOfAcks = 20
for range numberOfAcks {
100, // initial receive window
100, // max receive window
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
require.False(t, fc.AddBytesRead(1))
func TestConnectionWindowAutoTuningNotAllowed(t *testing.T) {
// the RTT is 1 second
- rttStats := &utils.RTTStats{}
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(time.Second, 0)
require.Equal(t, time.Second, rttStats.SmoothedRTT())
}
func TestConnectionFlowControlViolation(t *testing.T) {
- fc := NewConnectionFlowController(100, 100, nil, &utils.RTTStats{}, utils.DefaultLogger)
+ fc := NewConnectionFlowController(100, 100, nil, utils.NewRTTStats(), utils.DefaultLogger)
require.NoError(t, fc.IncrementHighestReceived(40, monotime.Now()))
require.NoError(t, fc.IncrementHighestReceived(60, monotime.Now()))
err := fc.IncrementHighestReceived(1, monotime.Now())
}
func TestConnectionFlowControllerReset(t *testing.T) {
- fc := NewConnectionFlowController(0, 0, nil, &utils.RTTStats{}, utils.DefaultLogger)
+ fc := NewConnectionFlowController(0, 0, nil, utils.NewRTTStats(), utils.DefaultLogger)
fc.UpdateSendWindow(100)
fc.AddBytesSent(10)
require.Equal(t, protocol.ByteCount(90), fc.SendWindowSize())
}
func TestConnectionFlowControllerResetAfterReading(t *testing.T) {
- fc := NewConnectionFlowController(0, 0, nil, &utils.RTTStats{}, utils.DefaultLogger)
+ fc := NewConnectionFlowController(0, 0, nil, utils.NewRTTStats(), utils.DefaultLogger)
fc.AddBytesRead(1)
require.EqualError(t, fc.Reset(), "flow controller reset after reading data")
}
protocol.MaxByteCount,
protocol.MaxByteCount,
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
),
100,
protocol.MaxByteCount,
protocol.MaxByteCount,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
protocol.MaxByteCount,
protocol.MaxByteCount,
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
),
protocol.MaxByteCount,
protocol.MaxByteCount,
protocol.MaxByteCount,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
}
100,
protocol.MaxByteCount,
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
require.True(t, connFC.UpdateSendWindow(300))
60,
protocol.MaxByteCount,
100,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
protocol.MaxByteCount,
protocol.MaxByteCount,
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
require.True(t, connFC.UpdateSendWindow(300))
protocol.MaxByteCount,
protocol.MaxByteCount,
100,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
// first, we're limited by the stream flow controller
protocol.MaxByteCount,
protocol.MaxByteCount,
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
),
100,
100,
protocol.MaxByteCount,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
require.Zero(t, fc.GetWindowUpdate(monotime.Now()))
100,
protocol.MaxByteCount,
nil,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
fc := NewStreamFlowController(
1000,
protocol.MaxByteCount,
protocol.MaxByteCount,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
utils.DefaultLogger,
)
func TestStreamWindowAutoTuning(t *testing.T) {
// the RTT is 1 second
- rttStats := &utils.RTTStats{}
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(time.Second, 0)
require.Equal(t, time.Second, rttStats.SmoothedRTT())
&wire.TransportParameters{},
tlsConf,
false,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
nil,
utils.DefaultLogger.WithPrefix("client"),
protocol.Version1,
&wire.TransportParameters{StatelessResetToken: &token},
testdata.GetTLSConfig(),
false,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
nil,
utils.DefaultLogger.WithPrefix("server"),
protocol.Version1,
_, _, clientErr, _, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
_, _, clientErr, _, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
_, _, clientErr, _, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
cTransportParameters,
clientConf,
false,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
nil,
utils.DefaultLogger.WithPrefix("client"),
protocol.Version1,
sTransportParameters,
serverConf,
false,
- &utils.RTTStats{},
+ utils.NewRTTStats(),
nil,
utils.DefaultLogger.WithPrefix("server"),
protocol.Version1,
client, _, clientErr, _, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
client, _, clientErr, _, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
client, _, clientErr, server, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
require.False(t, server.ConnectionState().DidResume)
require.False(t, client.ConnectionState().DidResume)
- clientRTTStats := &utils.RTTStats{}
- serverRTTStats := &utils.RTTStats{}
+ clientRTTStats := utils.NewRTTStats()
+ serverRTTStats := utils.NewRTTStats()
client, _, clientErr, server, _, serverErr = handshakeWithTLSConf(
t,
clientConf, serverConf,
client, _, clientErr, server, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
client, _, clientErr, server, _, serverErr = handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2}, &wire.TransportParameters{ActiveConnectionIDLimit: 2},
false,
)
client, _, clientErr, server, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2},
&wire.TransportParameters{ActiveConnectionIDLimit: 2, InitialMaxData: initialMaxData},
true,
client, clientEvents, clientErr, server, serverEvents, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2},
&wire.TransportParameters{ActiveConnectionIDLimit: 2, InitialMaxData: initialMaxData},
true,
client, _, clientErr, server, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- &utils.RTTStats{}, &utils.RTTStats{},
+ utils.NewRTTStats(), utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2},
&wire.TransportParameters{ActiveConnectionIDLimit: 2, InitialMaxData: initialMaxData},
true,
require.False(t, server.ConnectionState().DidResume)
require.False(t, client.ConnectionState().DidResume)
- clientRTTStats := &utils.RTTStats{}
+ clientRTTStats := utils.NewRTTStats()
client, clientEvents, clientErr, server, _, serverErr := handshakeWithTLSConf(
t,
clientConf, serverConf,
- clientRTTStats, &utils.RTTStats{},
+ clientRTTStats, utils.NewRTTStats(),
&wire.TransportParameters{ActiveConnectionIDLimit: 2},
&wire.TransportParameters{ActiveConnectionIDLimit: 2, InitialMaxData: initialMaxData - 1},
true,
rand.Read(trafficSecret1)
rand.Read(trafficSecret2)
- client = newUpdatableAEAD(&utils.RTTStats{}, nil, utils.DefaultLogger, protocol.Version1)
+ client = newUpdatableAEAD(utils.NewRTTStats(), nil, utils.DefaultLogger, protocol.Version1)
server = newUpdatableAEAD(serverRTTStats, &eventRecorder, utils.DefaultLogger, protocol.Version1)
client.SetReadKey(cs, trafficSecret2)
client.SetWriteKey(cs, trafficSecret1)
for _, tc := range testCases {
t.Run(fmt.Sprintf("QUIC %s", tc.version), func(t *testing.T) {
secret := splitHexString(t, "9ac312a7f877468ebe69422748ad00a1 5443f18203a07d6060f688f30f21632b")
- aead := newUpdatableAEAD(&utils.RTTStats{}, nil, nil, tc.version)
+ aead := newUpdatableAEAD(utils.NewRTTStats(), nil, nil, tc.version)
chacha := cipherSuites[2]
require.Equal(t, tls.TLS_CHACHA20_POLY1305_SHA256, chacha.ID)
aead.SetWriteKey(chacha, secret)
rand.Read(trafficSecret1)
rand.Read(trafficSecret2)
- client := newUpdatableAEAD(&utils.RTTStats{}, nil, utils.DefaultLogger, v)
- server := newUpdatableAEAD(&utils.RTTStats{}, nil, utils.DefaultLogger, v)
+ client := newUpdatableAEAD(utils.NewRTTStats(), nil, utils.DefaultLogger, v)
+ server := newUpdatableAEAD(utils.NewRTTStats(), nil, utils.DefaultLogger, v)
client.SetReadKey(cs, trafficSecret2)
client.SetWriteKey(cs, trafficSecret1)
server.SetReadKey(cs, trafficSecret1)
}
func TestUpdatableAEADPacketNumbers(t *testing.T) {
- client, server, _ := setupEndpoints(t, &utils.RTTStats{})
+ client, server, _ := setupEndpoints(t, utils.NewRTTStats())
msg := []byte("Lorem ipsum")
ad := []byte("Donec in velit neque.")
}
func TestAEADLimitReached(t *testing.T) {
- client, _, _ := setupEndpoints(t, &utils.RTTStats{})
+ client, _, _ := setupEndpoints(t, utils.NewRTTStats())
client.invalidPacketLimit = 10
for i := 0; i < 9; i++ {
_, err := client.Open(nil, []byte("foobar"), monotime.Now(), protocol.PacketNumber(i), protocol.KeyPhaseZero, []byte("ad"))
}
func TestKeyUpdates(t *testing.T) {
- client, server, _ := setupEndpoints(t, &utils.RTTStats{})
+ client, server, _ := setupEndpoints(t, utils.NewRTTStats())
now := monotime.Now()
require.Equal(t, protocol.KeyPhaseZero, server.KeyPhase())
// }
func TestReorderedPacketAfterKeyUpdate(t *testing.T) {
- client, server, eventRecorder := setupEndpoints(t, &utils.RTTStats{})
+ client, server, eventRecorder := setupEndpoints(t, utils.NewRTTStats())
now := monotime.Now()
encrypted01 := client.Seal(nil, []byte(msg), 0x42, []byte(ad))
}
func TestDropsKeys3PTOsAfterKeyUpdate(t *testing.T) {
- var rttStats utils.RTTStats
- client, server, eventRecorder := setupEndpoints(t, &rttStats)
+ rttStats := utils.NewRTTStats()
+ client, server, eventRecorder := setupEndpoints(t, rttStats)
now := monotime.Now()
rttStats.UpdateRTT(10*time.Millisecond, 0)
}
func TestAllowsFirstKeyUpdateImmediately(t *testing.T) {
- client, server, serverTracer := setupEndpoints(t, &utils.RTTStats{})
+ client, server, serverTracer := setupEndpoints(t, utils.NewRTTStats())
client.rollKeys()
encrypted := client.Seal(nil, []byte(msg), 0x1337, []byte(ad))
}
func TestRejectFrequentKeyUpdates(t *testing.T) {
- client, server, _ := setupEndpoints(t, &utils.RTTStats{})
+ client, server, _ := setupEndpoints(t, utils.NewRTTStats())
server.rollKeys()
client.rollKeys()
const keyUpdateInterval = 20
setKeyUpdateIntervals(t, firstKeyUpdateInterval, keyUpdateInterval)
- client, server, eventRecorder := setupEndpoints(t, &utils.RTTStats{})
+ client, server, eventRecorder := setupEndpoints(t, utils.NewRTTStats())
server.SetHandshakeConfirmed()
var pn protocol.PacketNumber
const firstKeyUpdateInterval = 5
setKeyUpdateIntervals(t, firstKeyUpdateInterval, protocol.KeyUpdateInterval)
- _, server, eventRecorder := setupEndpoints(t, &utils.RTTStats{})
+ _, server, eventRecorder := setupEndpoints(t, utils.NewRTTStats())
server.SetHandshakeConfirmed()
// First make sure that we update our keys.
const keyUpdateInterval = 20
setKeyUpdateIntervals(t, firstKeyUpdateInterval, keyUpdateInterval)
- client, server, eventRecorder := setupEndpoints(t, &utils.RTTStats{})
+ client, server, eventRecorder := setupEndpoints(t, utils.NewRTTStats())
server.SetHandshakeConfirmed()
msg := []byte("message")
const keyUpdateInterval = 20
setKeyUpdateIntervals(t, firstKeyUpdateInterval, keyUpdateInterval)
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(10*time.Millisecond, 0)
- client, server, eventRecorder := setupEndpoints(t, &rttStats)
+ client, server, eventRecorder := setupEndpoints(t, rttStats)
server.SetHandshakeConfirmed()
now := monotime.Now()
const keyUpdateInterval = 20
setKeyUpdateIntervals(t, firstKeyUpdateInterval, keyUpdateInterval)
- client, server, eventRecorder := setupEndpoints(t, &utils.RTTStats{})
+ client, server, eventRecorder := setupEndpoints(t, utils.NewRTTStats())
server.SetHandshakeConfirmed()
var pn protocol.PacketNumber
const keyUpdateInterval = 20
setKeyUpdateIntervals(t, firstKeyUpdateInterval, keyUpdateInterval)
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(10*time.Millisecond, 0)
- client, server, eventRecorder := setupEndpoints(t, &rttStats)
+ client, server, eventRecorder := setupEndpoints(t, rttStats)
server.SetHandshakeConfirmed()
// send so many packets that we initiate the first key update
rand.Read(trafficSecret2)
cs := cipherSuites[0]
- var rttStats utils.RTTStats
- client = newUpdatableAEAD(&rttStats, nil, utils.DefaultLogger, protocol.Version1)
- server = newUpdatableAEAD(&rttStats, nil, utils.DefaultLogger, protocol.Version1)
+ rttStats := utils.NewRTTStats()
+ client = newUpdatableAEAD(rttStats, nil, utils.DefaultLogger, protocol.Version1)
+ server = newUpdatableAEAD(rttStats, nil, utils.DefaultLogger, protocol.Version1)
client.SetReadKey(cs, trafficSecret2)
client.SetWriteKey(cs, trafficSecret1)
server.SetReadKey(cs, trafficSecret1)
oneMinusAlpha = 1 - rttAlpha
rttBeta = 0.25
oneMinusBeta = 1 - rttBeta
- // The default RTT used before an RTT sample is taken.
- defaultInitialRTT = 100 * time.Millisecond
)
+// The default RTT used before an RTT sample is taken
+const DefaultInitialRTT = 100 * time.Millisecond
+
// RTTStats provides round-trip statistics
type RTTStats struct {
hasMeasurement bool
maxAckDelay atomic.Int64 // nanoseconds
}
+func NewRTTStats() *RTTStats {
+ var rttStats RTTStats
+ rttStats.minRTT.Store(DefaultInitialRTT.Nanoseconds())
+ rttStats.latestRTT.Store(DefaultInitialRTT.Nanoseconds())
+ rttStats.smoothedRTT.Store(DefaultInitialRTT.Nanoseconds())
+ return &rttStats
+}
+
// MinRTT Returns the minRTT for the entire connection.
// May return Zero if no valid updates have occurred.
func (r *RTTStats) MinRTT() time.Duration {
// PTO gets the probe timeout duration.
func (r *RTTStats) PTO(includeMaxAckDelay bool) time.Duration {
- if r.SmoothedRTT() == 0 {
- return 2 * defaultInitialRTT
+ if !r.hasMeasurement {
+ return 2 * DefaultInitialRTT
}
pto := r.SmoothedRTT() + max(4*r.MeanDeviation(), protocol.TimerGranularity)
if includeMaxAckDelay {
// the client may cause a high ackDelay to result in underestimation of the
// r.minRTT.
minRTT := time.Duration(r.minRTT.Load())
- if minRTT == 0 || minRTT > sendDelta {
+ if !r.hasMeasurement || minRTT > sendDelta {
minRTT = sendDelta
- r.minRTT.Store(int64(sendDelta))
+ r.minRTT.Store(sendDelta.Nanoseconds())
}
// Correct for ackDelay if information received from the peer results in a
if sample-minRTT >= ackDelay {
sample -= ackDelay
}
- r.latestRTT.Store(int64(sample))
+ r.latestRTT.Store(sample.Nanoseconds())
// First time call.
if !r.hasMeasurement {
r.hasMeasurement = true
- r.smoothedRTT.Store(int64(sample))
- r.meanDeviation.Store(int64(sample / 2))
+ r.smoothedRTT.Store(sample.Nanoseconds())
+ r.meanDeviation.Store(sample.Nanoseconds() / 2)
} else {
smoothedRTT := r.SmoothedRTT()
meanDev := time.Duration(oneMinusBeta*float32(r.MeanDeviation()/time.Microsecond)+rttBeta*float32((smoothedRTT-sample).Abs()/time.Microsecond)) * time.Microsecond
newSmoothedRTT := time.Duration((float32(smoothedRTT/time.Microsecond)*oneMinusAlpha)+(float32(sample/time.Microsecond)*rttAlpha)) * time.Microsecond
- r.meanDeviation.Store(int64(meanDev))
- r.smoothedRTT.Store(int64(newSmoothedRTT))
+ r.meanDeviation.Store(meanDev.Nanoseconds())
+ r.smoothedRTT.Store(newSmoothedRTT.Nanoseconds())
}
}
func (r *RTTStats) ResetForPathMigration() {
r.hasMeasurement = false
- r.minRTT.Store(0)
- r.latestRTT.Store(0)
- r.smoothedRTT.Store(0)
+ r.minRTT.Store(DefaultInitialRTT.Nanoseconds())
+ r.latestRTT.Store(DefaultInitialRTT.Nanoseconds())
+ r.smoothedRTT.Store(DefaultInitialRTT.Nanoseconds())
r.meanDeviation.Store(0)
// max_ack_delay remains valid
}
)
func TestRTTStatsDefaults(t *testing.T) {
- var rttStats RTTStats
- require.Zero(t, rttStats.MinRTT())
- require.Zero(t, rttStats.SmoothedRTT())
+ rttStats := NewRTTStats()
+ require.Equal(t, DefaultInitialRTT, rttStats.MinRTT())
+ require.Equal(t, DefaultInitialRTT, rttStats.SmoothedRTT())
}
func TestRTTStatsSmoothedRTT(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
// verify that ack_delay is ignored in the first measurement
rttStats.UpdateRTT(300*time.Millisecond, 100*time.Millisecond)
require.Equal(t, 300*time.Millisecond, rttStats.LatestRTT())
}
func TestRTTStatsMinRTT(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
rttStats.UpdateRTT(200*time.Millisecond, 0)
require.Equal(t, 200*time.Millisecond, rttStats.MinRTT())
rttStats.UpdateRTT(10*time.Millisecond, 0)
}
func TestRTTStatsMaxAckDelay(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
rttStats.SetMaxAckDelay(42 * time.Minute)
require.Equal(t, 42*time.Minute, rttStats.MaxAckDelay())
}
maxAckDelay = 42 * time.Minute
rtt = time.Second
)
- var rttStats RTTStats
+ rttStats := NewRTTStats()
rttStats.SetMaxAckDelay(maxAckDelay)
rttStats.UpdateRTT(rtt, 0)
require.Equal(t, rtt, rttStats.SmoothedRTT())
func TestRTTStatsPTOWithShortRTT(t *testing.T) {
const rtt = time.Microsecond
- var rttStats RTTStats
+ rttStats := NewRTTStats()
rttStats.UpdateRTT(rtt, 0)
require.Equal(t, rtt+protocol.TimerGranularity, rttStats.PTO(true))
}
func TestRTTStatsUpdateWithBadSendDeltas(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
const initialRtt = 10 * time.Millisecond
rttStats.UpdateRTT(initialRtt, 0)
require.Equal(t, initialRtt, rttStats.MinRTT())
}
func TestRTTStatsRestore(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
rttStats.SetInitialRTT(10 * time.Second)
require.Equal(t, 10*time.Second, rttStats.LatestRTT())
require.Equal(t, 10*time.Second, rttStats.SmoothedRTT())
}
func TestRTTMeasurementAfterRestore(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
const rtt = 10 * time.Millisecond
rttStats.UpdateRTT(rtt, 0)
require.Equal(t, rtt, rttStats.LatestRTT())
}
func TestRTTStatsResetForPathMigration(t *testing.T) {
- var rttStats RTTStats
+ rttStats := NewRTTStats()
rttStats.SetMaxAckDelay(42 * time.Millisecond)
rttStats.UpdateRTT(time.Second, 0)
rttStats.UpdateRTT(10*time.Second, 0)
require.NotZero(t, rttStats.SmoothedRTT())
rttStats.ResetForPathMigration()
- require.Zero(t, rttStats.MinRTT())
- require.Zero(t, rttStats.LatestRTT())
- require.Zero(t, rttStats.SmoothedRTT())
- require.Equal(t, 2*defaultInitialRTT, rttStats.PTO(false))
+ require.Equal(t, DefaultInitialRTT, rttStats.MinRTT())
+ require.Equal(t, DefaultInitialRTT, rttStats.LatestRTT())
+ require.Equal(t, DefaultInitialRTT, rttStats.SmoothedRTT())
+ require.Equal(t, 2*DefaultInitialRTT, rttStats.PTO(false))
// make sure that max_ack_delay was not reset
require.Equal(t, 42*time.Millisecond, rttStats.MaxAckDelay())
func TestMTUDiscovererTiming(t *testing.T) {
const rtt = 100 * time.Millisecond
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(rtt, 0)
- d := newMTUDiscoverer(&rttStats, 1000, 2000, nil)
+ d := newMTUDiscoverer(rttStats, 1000, 2000, nil)
now := monotime.Now()
require.False(t, d.ShouldSendProbe(now))
}
func TestMTUDiscovererAckAndLoss(t *testing.T) {
- d := newMTUDiscoverer(&utils.RTTStats{}, 1000, 2000, nil)
- // we use an RTT of 0 here, so we don't have to advance the timer on every step
+ const rtt = 200 * time.Millisecond
+ rttStats := utils.NewRTTStats()
+ rttStats.UpdateRTT(rtt, 0)
+ d := newMTUDiscoverer(rttStats, 1000, 2000, nil)
now := monotime.Now()
ping, size := d.GetPing(now)
require.Equal(t, protocol.ByteCount(1500), size)
ping.Handler.OnLost(ping.Frame)
require.Equal(t, protocol.ByteCount(1000), d.CurrentSize()) // no change to the MTU yet
+ now = now.Add(5 * rtt)
require.True(t, d.ShouldSendProbe(now))
ping, size = d.GetPing(now)
require.Equal(t, protocol.ByteCount(1250), size)
// Even though the 1500 byte MTU probe packet was lost, we try again with a higher MTU.
// This protects against regular (non-MTU-related) packet loss.
+ now = now.Add(5 * rtt)
require.True(t, d.ShouldSendProbe(now))
ping, size = d.GetPing(now)
require.Greater(t, size, protocol.ByteCount(1500))
// We continue probing until the MTU is close to the maximum.
var steps int
oldSize := size
+ now = now.Add(5 * rtt)
for d.ShouldSendProbe(now) {
ping, size = d.GetPing(now)
require.Greater(t, size, oldSize)
ping.Handler.OnAcked(ping.Frame)
steps++
require.Less(t, steps, 10)
+ now = now.Add(5 * rtt)
}
require.Less(t, 2000-maxMTUDiff, size)
}
const rtt = 100 * time.Millisecond
const startMTU protocol.ByteCount = 1000
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(rtt, 0)
maxMTU := protocol.ByteCount(rand.IntN(int(3000-startMTU))) + startMTU + 1
var eventRecorder events.Recorder
- d := newMTUDiscoverer(&rttStats, startMTU, maxMTU, &eventRecorder)
+ d := newMTUDiscoverer(rttStats, startMTU, maxMTU, &eventRecorder)
now := monotime.Now()
d.Start(now)
realMTU := protocol.ByteCount(rand.IntN(int(maxMTU-startMTU))) + startMTU
const startMTU protocol.ByteCount = 1000
const maxRandomLoss = maxLostMTUProbes - 1
- rttStats := &utils.RTTStats{}
+ rttStats := utils.NewRTTStats()
rttStats.SetInitialRTT(rtt)
require.Equal(t, rtt, rttStats.SmoothedRTT())
const maxMTU = 1400
const rtt = 100 * time.Millisecond
- rttStats := &utils.RTTStats{}
+ rttStats := utils.NewRTTStats()
rttStats.SetInitialRTT(rtt)
now := monotime.Now()
tracer := trace.AddProducer()
b.Cleanup(func() { tracer.Close() })
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(1337*time.Millisecond, 0)
rttStats.UpdateRTT(1000*time.Millisecond, 10*time.Millisecond)
rttStats.UpdateRTT(800*time.Millisecond, 100*time.Millisecond)
}
func TestMetricsUpdated(t *testing.T) {
- var rttStats utils.RTTStats
+ rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(15*time.Millisecond, 0)
rttStats.UpdateRTT(20*time.Millisecond, 0)
rttStats.UpdateRTT(25*time.Millisecond, 0)