golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/loss_test.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 7 package quic 8 9 import ( 10 "fmt" 11 "testing" 12 "time" 13 ) 14 15 func TestLossAntiAmplificationLimit(t *testing.T) { 16 test := newLossTest(t, serverSide, lossTestOpts{}) 17 test.datagramReceived(1200) 18 t.Logf("# consume anti-amplification capacity in a mix of packets") 19 test.send(initialSpace, 0, sentPacket{ 20 size: 1200, 21 ackEliciting: true, 22 inFlight: true, 23 }) 24 test.send(initialSpace, 1, sentPacket{ 25 size: 1200, 26 ackEliciting: false, 27 inFlight: false, 28 }) 29 test.send(initialSpace, 2, sentPacket{ 30 size: 1200, 31 ackEliciting: false, 32 inFlight: true, 33 }) 34 t.Logf("# send blocked by anti-amplification limit") 35 test.wantSendLimit(ccBlocked) 36 37 t.Logf("# receiving a datagram unblocks server") 38 test.datagramReceived(100) 39 test.wantSendLimit(ccOK) 40 41 t.Logf("# validating client address removes anti-amplification limit") 42 test.validateClientAddress() 43 test.wantSendLimit(ccOK) 44 } 45 46 func TestLossRTTSampleNotGenerated(t *testing.T) { 47 test := newLossTest(t, clientSide, lossTestOpts{}) 48 test.send(initialSpace, 0, 1) 49 test.send(initialSpace, 2, sentPacket{ 50 ackEliciting: false, 51 inFlight: false, 52 }) 53 test.advance(10 * time.Millisecond) 54 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 55 test.wantAck(initialSpace, 1) 56 test.wantVar("latest_rtt", 10*time.Millisecond) 57 t.Logf("# smoothed_rtt = latest_rtt") 58 test.wantVar("smoothed_rtt", 10*time.Millisecond) 59 t.Logf("# rttvar = latest_rtt / 2") 60 test.wantVar("rttvar", 5*time.Millisecond) 61 62 // "...an ACK frame SHOULD NOT be used to update RTT estimates if 63 // it does not newly acknowledge the largest acknowledged packet." 64 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.1-6 65 t.Logf("# acks for older packets do not generate an RTT sample") 66 test.advance(1 * time.Millisecond) 67 test.ack(initialSpace, 1*time.Millisecond, i64range[packetNumber]{0, 2}) 68 test.wantAck(initialSpace, 0) 69 test.wantVar("smoothed_rtt", 10*time.Millisecond) 70 71 // "An RTT sample MUST NOT be generated on receiving an ACK frame 72 // that does not newly acknowledge at least one ack-eliciting packet." 73 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.1-7 74 t.Logf("# acks for non-ack-eliciting packets do not generate an RTT sample") 75 test.advance(1 * time.Millisecond) 76 test.ack(initialSpace, 1*time.Millisecond, i64range[packetNumber]{0, 3}) 77 test.wantAck(initialSpace, 2) 78 test.wantVar("smoothed_rtt", 10*time.Millisecond) 79 } 80 81 func TestLossMinRTT(t *testing.T) { 82 test := newLossTest(t, clientSide, lossTestOpts{}) 83 84 // "min_rtt MUST be set to the latest_rtt on the first RTT sample." 85 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.2-2 86 t.Logf("# min_rtt set on first sample") 87 test.send(initialSpace, 0) 88 test.advance(10 * time.Millisecond) 89 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 90 test.wantAck(initialSpace, 0) 91 test.wantVar("min_rtt", 10*time.Millisecond) 92 93 // "min_rtt MUST be set to the lesser of min_rtt and latest_rtt [...] 94 // on all other samples." 95 t.Logf("# min_rtt does not increase") 96 test.send(initialSpace, 1) 97 test.advance(20 * time.Millisecond) 98 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 2}) 99 test.wantAck(initialSpace, 1) 100 test.wantVar("min_rtt", 10*time.Millisecond) 101 102 t.Logf("# min_rtt decreases") 103 test.send(initialSpace, 2) 104 test.advance(5 * time.Millisecond) 105 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 3}) 106 test.wantAck(initialSpace, 2) 107 test.wantVar("min_rtt", 5*time.Millisecond) 108 } 109 110 func TestLossMinRTTAfterCongestion(t *testing.T) { 111 // "Endpoints SHOULD set the min_rtt to the newest RTT sample 112 // after persistent congestion is established." 113 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.2-5 114 test := newLossTest(t, clientSide, lossTestOpts{ 115 maxDatagramSize: 1200, 116 }) 117 t.Logf("# establish initial RTT sample") 118 test.send(initialSpace, 0, testSentPacketSize(1200)) 119 test.advance(10 * time.Millisecond) 120 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 121 test.wantAck(initialSpace, 0) 122 test.wantVar("min_rtt", 10*time.Millisecond) 123 124 t.Logf("# send two packets spanning persistent congestion duration") 125 test.send(initialSpace, 1, testSentPacketSize(1200)) 126 t.Logf("# 2000ms >> persistent congestion duration") 127 test.advance(2000 * time.Millisecond) 128 test.wantPTOExpired() 129 test.send(initialSpace, 2, testSentPacketSize(1200)) 130 131 t.Logf("# trigger loss of previous packets") 132 test.advance(10 * time.Millisecond) 133 test.send(initialSpace, 3, testSentPacketSize(1200)) 134 test.advance(20 * time.Millisecond) 135 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{3, 4}) 136 test.wantAck(initialSpace, 3) 137 test.wantLoss(initialSpace, 1, 2) 138 t.Logf("# persistent congestion detected") 139 140 test.send(initialSpace, 4, testSentPacketSize(1200)) 141 test.advance(20 * time.Millisecond) 142 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{4, 5}) 143 test.wantAck(initialSpace, 4) 144 145 t.Logf("# min_rtt set from first sample after persistent congestion") 146 test.wantVar("min_rtt", 20*time.Millisecond) 147 } 148 149 func TestLossInitialRTTSample(t *testing.T) { 150 test := newLossTest(t, clientSide, lossTestOpts{}) 151 test.setMaxAckDelay(2 * time.Millisecond) 152 t.Logf("# initial smoothed_rtt and rtt values") 153 test.wantVar("smoothed_rtt", 333*time.Millisecond) 154 test.wantVar("rttvar", 333*time.Millisecond/2) 155 156 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-11 157 t.Logf("# first RTT sample") 158 test.send(initialSpace, 0) 159 test.advance(10 * time.Millisecond) 160 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 161 test.wantAck(initialSpace, 0) 162 test.wantVar("latest_rtt", 10*time.Millisecond) 163 t.Logf("# smoothed_rtt = latest_rtt") 164 test.wantVar("smoothed_rtt", 10*time.Millisecond) 165 t.Logf("# rttvar = latest_rtt / 2") 166 test.wantVar("rttvar", 5*time.Millisecond) 167 } 168 169 func TestLossSmoothedRTTIgnoresMaxAckDelayBeforeHandshakeConfirmed(t *testing.T) { 170 test := newLossTest(t, clientSide, lossTestOpts{}) 171 test.setMaxAckDelay(1 * time.Millisecond) 172 test.send(initialSpace, 0) 173 test.advance(10 * time.Millisecond) 174 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 175 test.wantAck(initialSpace, 0) 176 smoothedRTT := 10 * time.Millisecond 177 rttvar := 5 * time.Millisecond 178 179 // "[...] an endpoint [...] SHOULD ignore the peer's max_ack_delay 180 // until the handshake is confirmed [...]" 181 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-7.2 182 t.Logf("# subsequent RTT sample") 183 test.send(handshakeSpace, 0) 184 test.advance(20 * time.Millisecond) 185 test.ack(handshakeSpace, 10*time.Millisecond, i64range[packetNumber]{0, 1}) 186 test.wantAck(handshakeSpace, 0) 187 test.wantVar("latest_rtt", 20*time.Millisecond) 188 t.Logf("# ack_delay > max_ack_delay") 189 t.Logf("# handshake not confirmed, so ignore max_ack_delay") 190 t.Logf("# adjusted_rtt = latest_rtt - ackDelay") 191 adjustedRTT := 10 * time.Millisecond 192 t.Logf("# smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt") 193 smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8 194 test.wantVar("smoothed_rtt", smoothedRTT) 195 rttvarSample := abs(smoothedRTT - adjustedRTT) 196 t.Logf("# rttvar_sample = abs(smoothed_rtt - adjusted_rtt) = %v", rttvarSample) 197 t.Logf("# rttvar = 3/4 * rttvar + 1/4 * rttvar_sample") 198 rttvar = (3*rttvar + rttvarSample) / 4 199 test.wantVar("rttvar", rttvar) 200 } 201 202 func TestLossSmoothedRTTUsesMaxAckDelayAfterHandshakeConfirmed(t *testing.T) { 203 test := newLossTest(t, clientSide, lossTestOpts{}) 204 test.setMaxAckDelay(25 * time.Millisecond) 205 test.send(initialSpace, 0) 206 test.advance(10 * time.Millisecond) 207 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 208 test.wantAck(initialSpace, 0) 209 smoothedRTT := 10 * time.Millisecond 210 rttvar := 5 * time.Millisecond 211 212 test.confirmHandshake() 213 214 // "[...] an endpoint [...] MUST use the lesser of the acknowledgment 215 // delay and the peer's max_ack_delay after the handshake is confirmed [...]" 216 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-7.3 217 t.Logf("# subsequent RTT sample") 218 test.send(handshakeSpace, 0) 219 test.advance(50 * time.Millisecond) 220 test.ack(handshakeSpace, 40*time.Millisecond, i64range[packetNumber]{0, 1}) 221 test.wantAck(handshakeSpace, 0) 222 test.wantVar("latest_rtt", 50*time.Millisecond) 223 t.Logf("# ack_delay > max_ack_delay") 224 t.Logf("# handshake confirmed, so adjusted_rtt clamps to max_ack_delay") 225 t.Logf("# adjusted_rtt = max_ack_delay") 226 adjustedRTT := 25 * time.Millisecond 227 rttvarSample := abs(smoothedRTT - adjustedRTT) 228 t.Logf("# rttvar_sample = abs(smoothed_rtt - adjusted_rtt) = %v", rttvarSample) 229 t.Logf("# rttvar = 3/4 * rttvar + 1/4 * rttvar_sample") 230 rttvar = (3*rttvar + rttvarSample) / 4 231 test.wantVar("rttvar", rttvar) 232 t.Logf("# smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt") 233 smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8 234 test.wantVar("smoothed_rtt", smoothedRTT) 235 } 236 237 func TestLossAckDelayReducesRTTBelowMinRTT(t *testing.T) { 238 test := newLossTest(t, clientSide, lossTestOpts{}) 239 test.send(initialSpace, 0) 240 test.advance(10 * time.Millisecond) 241 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 242 test.wantAck(initialSpace, 0) 243 smoothedRTT := 10 * time.Millisecond 244 rttvar := 5 * time.Millisecond 245 246 // "[...] an endpoint [...] MUST NOT subtract the acknowledgment delay 247 // from the RTT sample if the resulting value is smaller than the min_rtt." 248 // https://www.rfc-editor.org/rfc/rfc9002.html#section-5.3-7.4 249 t.Logf("# subsequent RTT sample") 250 test.send(handshakeSpace, 0) 251 test.advance(12 * time.Millisecond) 252 test.ack(handshakeSpace, 4*time.Millisecond, i64range[packetNumber]{0, 1}) 253 test.wantAck(handshakeSpace, 0) 254 test.wantVar("latest_rtt", 12*time.Millisecond) 255 t.Logf("# latest_rtt - ack_delay < min_rtt, so adjusted_rtt = latest_rtt") 256 adjustedRTT := 12 * time.Millisecond 257 rttvarSample := abs(smoothedRTT - adjustedRTT) 258 t.Logf("# rttvar_sample = abs(smoothed_rtt - adjusted_rtt) = %v", rttvarSample) 259 t.Logf("# rttvar = 3/4 * rttvar + 1/4 * rttvar_sample") 260 rttvar = (3*rttvar + rttvarSample) / 4 261 test.wantVar("rttvar", rttvar) 262 t.Logf("# smoothed_rtt = 7/8 * smoothed_rtt + 1/8 * adjusted_rtt") 263 smoothedRTT = (7*smoothedRTT + adjustedRTT) / 8 264 test.wantVar("smoothed_rtt", smoothedRTT) 265 } 266 267 func TestLossPacketThreshold(t *testing.T) { 268 // "[...] the packet was sent kPacketThreshold packets before an 269 // acknowledged packet [...]" 270 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.1.1 271 test := newLossTest(t, clientSide, lossTestOpts{}) 272 t.Logf("# acking a packet triggers loss of packets sent kPacketThreshold earlier") 273 test.send(appDataSpace, 0, 1, 2, 3, 4, 5, 6) 274 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{4, 5}) 275 test.wantAck(appDataSpace, 4) 276 test.wantLoss(appDataSpace, 0, 1) 277 } 278 279 func TestLossOutOfOrderAcks(t *testing.T) { 280 test := newLossTest(t, clientSide, lossTestOpts{}) 281 t.Logf("# out of order acks, no loss") 282 test.send(appDataSpace, 0, 1, 2) 283 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{2, 3}) 284 test.wantAck(appDataSpace, 2) 285 286 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 287 test.wantAck(appDataSpace, 1) 288 289 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 290 test.wantAck(appDataSpace, 0) 291 } 292 293 func TestLossSendAndAck(t *testing.T) { 294 test := newLossTest(t, clientSide, lossTestOpts{}) 295 test.send(appDataSpace, 0, 1, 2) 296 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{0, 3}) 297 test.wantAck(appDataSpace, 0, 1, 2) 298 // Redundant ACK doesn't trigger more ACK events. 299 // (If we did get an extra ACK, the test cleanup would notice and complain.) 300 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{0, 3}) 301 } 302 303 func TestLossAckEveryOtherPacket(t *testing.T) { 304 test := newLossTest(t, clientSide, lossTestOpts{}) 305 test.send(appDataSpace, 0, 1, 2, 3, 4, 5, 6) 306 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 307 test.wantAck(appDataSpace, 0) 308 309 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{2, 3}) 310 test.wantAck(appDataSpace, 2) 311 312 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{4, 5}) 313 test.wantAck(appDataSpace, 4) 314 test.wantLoss(appDataSpace, 1) 315 316 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{6, 7}) 317 test.wantAck(appDataSpace, 6) 318 test.wantLoss(appDataSpace, 3) 319 } 320 321 func TestLossMultipleSpaces(t *testing.T) { 322 // "Loss detection is separate per packet number space [...]" 323 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6-3 324 test := newLossTest(t, clientSide, lossTestOpts{}) 325 t.Logf("# send packets in different spaces") 326 test.send(initialSpace, 0, 1, 2) 327 test.send(handshakeSpace, 0, 1, 2) 328 test.send(appDataSpace, 0, 1, 2) 329 330 t.Logf("# ack one packet in each space") 331 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 332 test.wantAck(initialSpace, 1) 333 334 test.ack(handshakeSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 335 test.wantAck(handshakeSpace, 1) 336 337 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 338 test.wantAck(appDataSpace, 1) 339 340 t.Logf("# send more packets") 341 test.send(initialSpace, 3, 4, 5) 342 test.send(handshakeSpace, 3, 4, 5) 343 test.send(appDataSpace, 3, 4, 5) 344 345 t.Logf("# ack the last packet, triggering loss") 346 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{5, 6}) 347 test.wantAck(initialSpace, 5) 348 test.wantLoss(initialSpace, 0, 2) 349 350 test.ack(handshakeSpace, 0*time.Millisecond, i64range[packetNumber]{5, 6}) 351 test.wantAck(handshakeSpace, 5) 352 test.wantLoss(handshakeSpace, 0, 2) 353 354 test.ack(appDataSpace, 0*time.Millisecond, i64range[packetNumber]{5, 6}) 355 test.wantAck(appDataSpace, 5) 356 test.wantLoss(appDataSpace, 0, 2) 357 } 358 359 func TestLossTimeThresholdFirstPacketLost(t *testing.T) { 360 // "[...] the packet [...] was sent long enough in the past." 361 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.1-3.2 362 test := newLossTest(t, clientSide, lossTestOpts{}) 363 t.Logf("# packet 0 lost after time threshold passes") 364 test.send(initialSpace, 0, 1) 365 test.advance(10 * time.Millisecond) 366 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 367 test.wantAck(initialSpace, 1) 368 369 t.Logf("# latest_rtt == smoothed_rtt") 370 test.wantVar("smoothed_rtt", 10*time.Millisecond) 371 test.wantVar("latest_rtt", 10*time.Millisecond) 372 t.Logf("# timeout = 9/8 * max(smoothed_rtt, latest_rtt) - time_since_packet_sent") 373 test.wantTimeout(((10 * time.Millisecond * 9) / 8) - 10*time.Millisecond) 374 375 test.advanceToLossTimer() 376 test.wantLoss(initialSpace, 0) 377 } 378 379 func TestLossTimeThreshold(t *testing.T) { 380 // "The time threshold is: 381 // max(kTimeThreshold * max(smoothed_rtt, latest_rtt), kGranularity)" 382 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.1.2-2 383 for _, tc := range []struct { 384 name string 385 initialRTT time.Duration 386 latestRTT time.Duration 387 wantTimeout time.Duration 388 }{{ 389 name: "rtt increasing", 390 initialRTT: 10 * time.Millisecond, 391 latestRTT: 20 * time.Millisecond, 392 wantTimeout: 20 * time.Millisecond * 9 / 8, 393 }, { 394 name: "rtt decreasing", 395 initialRTT: 10 * time.Millisecond, 396 latestRTT: 5 * time.Millisecond, 397 wantTimeout: ((7*10*time.Millisecond + 5*time.Millisecond) / 8) * 9 / 8, 398 }, { 399 name: "rtt less than timer granularity", 400 initialRTT: 500 * time.Microsecond, 401 latestRTT: 500 * time.Microsecond, 402 wantTimeout: 1 * time.Millisecond, 403 }} { 404 t.Run(tc.name, func(t *testing.T) { 405 test := newLossTest(t, clientSide, lossTestOpts{}) 406 t.Logf("# first ack establishes smoothed_rtt") 407 test.send(initialSpace, 0) 408 test.advance(tc.initialRTT) 409 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 410 test.wantAck(initialSpace, 0) 411 412 t.Logf("# ack of packet 2 starts loss timer for packet 1") 413 test.send(initialSpace, 1, 2) 414 test.advance(tc.latestRTT) 415 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{2, 3}) 416 test.wantAck(initialSpace, 2) 417 418 t.Logf("# smoothed_rtt = %v", test.c.rtt.smoothedRTT) 419 t.Logf("# latest_rtt = %v", test.c.rtt.latestRTT) 420 t.Logf("# timeout = max(9/8 * max(smoothed_rtt, latest_rtt), 1ms)") 421 t.Logf("# (measured since packet 1 sent)") 422 test.wantTimeout(tc.wantTimeout - tc.latestRTT) 423 424 t.Logf("# advancing to the loss time causes loss of packet 1") 425 test.advanceToLossTimer() 426 test.wantLoss(initialSpace, 1) 427 }) 428 } 429 } 430 431 func TestLossPTONotAckEliciting(t *testing.T) { 432 // "When an ack-eliciting packet is transmitted, 433 // the sender schedules a timer for the PTO period [...]" 434 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-1 435 test := newLossTest(t, clientSide, lossTestOpts{}) 436 t.Logf("# PTO timer for first packet") 437 test.send(initialSpace, 0) 438 test.wantVar("smoothed_rtt", 333*time.Millisecond) // initial value 439 test.wantVar("rttvar", 333*time.Millisecond/2) // initial value 440 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 441 test.wantTimeout(999 * time.Millisecond) 442 443 t.Logf("# sending a non-ack-eliciting packet doesn't adjust PTO") 444 test.advance(333 * time.Millisecond) 445 test.send(initialSpace, 1, sentPacket{ 446 ackEliciting: false, 447 }) 448 test.wantVar("smoothed_rtt", 333*time.Millisecond) // unchanged 449 test.wantVar("rttvar", 333*time.Millisecond/2) // unchanged 450 test.wantTimeout(666 * time.Millisecond) 451 } 452 453 func TestLossPTOMaxAckDelay(t *testing.T) { 454 // "When the PTO is armed for Initial or Handshake packet number spaces, 455 // the max_ack_delay in the PTO period computation is set to 0 [...]" 456 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-4 457 test := newLossTest(t, clientSide, lossTestOpts{}) 458 t.Logf("# PTO timer for first packet") 459 test.send(initialSpace, 0) 460 test.wantVar("smoothed_rtt", 333*time.Millisecond) // initial value 461 test.wantVar("rttvar", 333*time.Millisecond/2) // initial value 462 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 463 test.wantTimeout(999 * time.Millisecond) 464 465 test.advance(10 * time.Millisecond) 466 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 467 test.wantAck(initialSpace, 0) 468 469 t.Logf("# PTO timer for handshake packet") 470 test.send(handshakeSpace, 0) 471 test.wantVar("smoothed_rtt", 10*time.Millisecond) 472 test.wantVar("rttvar", 5*time.Millisecond) 473 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 474 test.wantTimeout(30 * time.Millisecond) 475 476 test.advance(10 * time.Millisecond) 477 test.ack(handshakeSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 478 test.wantAck(handshakeSpace, 0) 479 test.confirmHandshake() 480 481 t.Logf("# PTO timer for appdata packet") 482 test.send(appDataSpace, 0) 483 test.wantVar("smoothed_rtt", 10*time.Millisecond) 484 test.wantVar("rttvar", 3750*time.Microsecond) 485 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms) + max_ack_delay (25ms)") 486 test.wantTimeout(50 * time.Millisecond) 487 } 488 489 func TestLossPTOUnderTimerGranularity(t *testing.T) { 490 // "The PTO period MUST be at least kGranularity [...]" 491 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-5 492 test := newLossTest(t, clientSide, lossTestOpts{}) 493 test.send(initialSpace, 0) 494 test.advance(10 * time.Microsecond) 495 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 496 test.wantAck(initialSpace, 0) 497 498 test.send(initialSpace, 1) 499 test.wantVar("smoothed_rtt", 10*time.Microsecond) 500 test.wantVar("rttvar", 5*time.Microsecond) 501 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 502 test.wantTimeout(10*time.Microsecond + 1*time.Millisecond) 503 } 504 505 func TestLossPTOMultipleSpaces(t *testing.T) { 506 // "[...] the timer MUST be set to the earlier value of the Initial and Handshake 507 // packet number spaces." 508 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-6 509 test := newLossTest(t, clientSide, lossTestOpts{}) 510 t.Logf("# PTO timer for first packet") 511 test.send(initialSpace, 0) 512 test.wantVar("smoothed_rtt", 333*time.Millisecond) // initial value 513 test.wantVar("rttvar", 333*time.Millisecond/2) // initial value 514 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 515 test.wantTimeout(999 * time.Millisecond) 516 517 t.Logf("# Initial and Handshake packets in flight, first takes precedence") 518 test.advance(333 * time.Millisecond) 519 test.send(handshakeSpace, 0) 520 test.wantTimeout(666 * time.Millisecond) 521 522 t.Logf("# Initial packet acked, Handshake PTO timer armed") 523 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 524 test.wantAck(initialSpace, 0) 525 test.wantTimeout(999 * time.Millisecond) 526 527 t.Logf("# send Initial, earlier Handshake PTO takes precedence") 528 test.advance(333 * time.Millisecond) 529 test.send(initialSpace, 1) 530 test.wantTimeout(666 * time.Millisecond) 531 } 532 533 func TestLossPTOHandshakeConfirmation(t *testing.T) { 534 // "An endpoint MUST NOT set its PTO timer for the Application Data 535 // packet number space until the handshake is confirmed." 536 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-7 537 test := newLossTest(t, clientSide, lossTestOpts{}) 538 test.send(initialSpace, 0) 539 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 540 test.wantAck(initialSpace, 0) 541 542 test.send(handshakeSpace, 0) 543 test.ack(handshakeSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 544 test.wantAck(handshakeSpace, 0) 545 546 test.send(appDataSpace, 0) 547 test.wantNoTimeout() 548 } 549 550 func TestLossPTOBackoffDoubles(t *testing.T) { 551 // "When a PTO timer expires, the PTO backoff MUST be increased, 552 // resulting in the PTO period being set to twice its current value." 553 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-9 554 test := newLossTest(t, serverSide, lossTestOpts{}) 555 test.datagramReceived(1200) 556 test.send(initialSpace, 0) 557 test.wantVar("smoothed_rtt", 333*time.Millisecond) // initial value 558 test.wantVar("rttvar", 333*time.Millisecond/2) // initial value 559 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 560 test.wantTimeout(999 * time.Millisecond) 561 562 t.Logf("# wait for PTO timer expiration") 563 test.advanceToLossTimer() 564 test.wantPTOExpired() 565 test.wantNoTimeout() 566 567 t.Logf("# PTO timer doubles") 568 test.send(initialSpace, 1) 569 test.wantTimeout(2 * 999 * time.Millisecond) 570 test.advanceToLossTimer() 571 test.wantPTOExpired() 572 test.wantNoTimeout() 573 574 t.Logf("# PTO timer doubles again") 575 test.send(initialSpace, 2) 576 test.wantTimeout(4 * 999 * time.Millisecond) 577 test.advanceToLossTimer() 578 test.wantPTOExpired() 579 test.wantNoTimeout() 580 } 581 582 func TestLossPTOBackoffResetOnAck(t *testing.T) { 583 // "The PTO backoff factor is reset when an acknowledgment is received [...]" 584 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-9 585 test := newLossTest(t, serverSide, lossTestOpts{}) 586 test.datagramReceived(1200) 587 588 t.Logf("# first ack establishes smoothed_rtt = 10ms") 589 test.send(initialSpace, 0) 590 test.advance(10 * time.Millisecond) 591 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 592 test.wantAck(initialSpace, 0) 593 t.Logf("# set rttvar for simplicity") 594 test.setRTTVar(0) 595 596 t.Logf("# send packet 1 and wait for PTO") 597 test.send(initialSpace, 1) 598 test.wantTimeout(11 * time.Millisecond) 599 test.advanceToLossTimer() 600 test.wantPTOExpired() 601 test.wantNoTimeout() 602 603 t.Logf("# send packet 2 & 3, PTO doubles") 604 test.send(initialSpace, 2, 3) 605 test.wantTimeout(22 * time.Millisecond) 606 607 test.advance(10 * time.Millisecond) 608 t.Logf("# check remaining PTO (22ms - 10ms elapsed)") 609 test.wantTimeout(12 * time.Millisecond) 610 611 t.Logf("# ACK to packet 2 resets PTO") 612 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 3}) 613 test.wantAck(initialSpace, 1) 614 test.wantAck(initialSpace, 2) 615 616 t.Logf("# check remaining PTO (11ms - 10ms elapsed)") 617 test.wantTimeout(1 * time.Millisecond) 618 } 619 620 func TestLossPTOBackoffNotResetOnClientInitialAck(t *testing.T) { 621 // "[...] a client does not reset the PTO backoff factor on 622 // receiving acknowledgments in Initial packets." 623 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-9 624 test := newLossTest(t, clientSide, lossTestOpts{}) 625 626 t.Logf("# first ack establishes smoothed_rtt = 10ms") 627 test.send(initialSpace, 0) 628 test.advance(10 * time.Millisecond) 629 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 630 test.wantAck(initialSpace, 0) 631 t.Logf("# set rttvar for simplicity") 632 test.setRTTVar(0) 633 634 t.Logf("# send packet 1 and wait for PTO") 635 test.send(initialSpace, 1) 636 test.wantTimeout(11 * time.Millisecond) 637 test.advanceToLossTimer() 638 test.wantPTOExpired() 639 test.wantNoTimeout() 640 641 t.Logf("# send more packets, PTO doubles") 642 test.send(initialSpace, 2, 3) 643 test.send(handshakeSpace, 0) 644 test.wantTimeout(22 * time.Millisecond) 645 646 test.advance(10 * time.Millisecond) 647 t.Logf("# check remaining PTO (22ms - 10ms elapsed)") 648 test.wantTimeout(12 * time.Millisecond) 649 650 // TODO: Is this right? 6.2.1-9 says we don't reset the PTO *backoff*, not the PTO. 651 // 6.2.1-8 says we reset the PTO timer when an ack-eliciting packet is sent *or 652 // acknowledged*, but the pseudocode in appendix A doesn't appear to do the latter. 653 t.Logf("# ACK to Initial packet does not reset PTO for client") 654 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 3}) 655 test.wantAck(initialSpace, 1) 656 test.wantAck(initialSpace, 2) 657 t.Logf("# check remaining PTO (22ms - 10ms elapsed)") 658 test.wantTimeout(12 * time.Millisecond) 659 660 t.Logf("# ACK to handshake packet does reset PTO") 661 test.ack(handshakeSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 662 test.wantAck(handshakeSpace, 0) 663 t.Logf("# check remaining PTO (12ms - 10ms elapsed)") 664 test.wantTimeout(1 * time.Millisecond) 665 } 666 667 func TestLossPTONotSetWhenLossTimerSet(t *testing.T) { 668 // "The PTO timer MUST NOT be set if a timer is set 669 // for time threshold loss detection [...]" 670 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.1-12 671 test := newLossTest(t, serverSide, lossTestOpts{}) 672 test.datagramReceived(1200) 673 t.Logf("# PTO timer set for first packets sent") 674 test.send(initialSpace, 0, 1) 675 test.wantVar("smoothed_rtt", 333*time.Millisecond) // initial value 676 test.wantVar("rttvar", 333*time.Millisecond/2) // initial value 677 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 678 test.wantTimeout(999 * time.Millisecond) 679 680 t.Logf("# ack of packet 1 starts loss timer for 0, PTO overidden") 681 test.advance(333 * time.Millisecond) 682 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 683 test.wantAck(initialSpace, 1) 684 685 t.Logf("# latest_rtt == smoothed_rtt") 686 test.wantVar("smoothed_rtt", 333*time.Millisecond) 687 test.wantVar("latest_rtt", 333*time.Millisecond) 688 t.Logf("# timeout = 9/8 * max(smoothed_rtt, latest_rtt) - time_since_packet_sent") 689 test.wantTimeout(((333 * time.Millisecond * 9) / 8) - 333*time.Millisecond) 690 } 691 692 func TestLossDiscardingKeysResetsTimers(t *testing.T) { 693 // "When Initial or Handshake keys are discarded, 694 // the PTO and loss detection timers MUST be reset" 695 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.2-3 696 test := newLossTest(t, clientSide, lossTestOpts{}) 697 698 t.Logf("# handshake packet sent 1ms after initial") 699 test.send(initialSpace, 0, 1) 700 test.advance(1 * time.Millisecond) 701 test.send(handshakeSpace, 0, 1) 702 test.advance(9 * time.Millisecond) 703 704 t.Logf("# ack of Initial packet 2 starts loss timer for packet 1") 705 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 706 test.wantAck(initialSpace, 1) 707 708 test.advance(1 * time.Millisecond) 709 t.Logf("# smoothed_rtt = %v", 10*time.Millisecond) 710 t.Logf("# latest_rtt = %v", 10*time.Millisecond) 711 t.Logf("# timeout = max(9/8 * max(smoothed_rtt, latest_rtt), 1ms)") 712 t.Logf("# (measured since Initial packet 1 sent)") 713 test.wantTimeout((10 * time.Millisecond * 9 / 8) - 11*time.Millisecond) 714 715 t.Logf("# ack of Handshake packet 2 starts loss timer for packet 1") 716 test.ack(handshakeSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 717 test.wantAck(handshakeSpace, 1) 718 719 t.Logf("# dropping Initial keys sets timer to Handshake timeout") 720 test.discardKeys(initialSpace) 721 test.wantTimeout((10 * time.Millisecond * 9 / 8) - 10*time.Millisecond) 722 } 723 724 func TestLossNoPTOAtAntiAmplificationLimit(t *testing.T) { 725 // "If no additional data can be sent [because the server is at the 726 // anti-amplification limit], the server's PTO timer MUST NOT be armed [...]" 727 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.2.1-1 728 test := newLossTest(t, serverSide, lossTestOpts{ 729 maxDatagramSize: 1 << 20, // large initial congestion window 730 }) 731 test.datagramReceived(1200) 732 test.send(initialSpace, 0, sentPacket{ 733 ackEliciting: true, 734 inFlight: true, 735 size: 1200, 736 }) 737 test.wantTimeout(999 * time.Millisecond) 738 739 t.Logf("PTO timer should be disabled when at the anti-amplification limit") 740 test.send(initialSpace, 1, sentPacket{ 741 ackEliciting: false, 742 inFlight: true, 743 size: 2 * 1200, 744 }) 745 test.wantNoTimeout() 746 747 // "When the server receives a datagram from the client, the amplification 748 // limit is increased and the server resets the PTO timer." 749 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.2.1-2 750 t.Logf("PTO timer should be reset when datagrams are received") 751 test.datagramReceived(1200) 752 test.wantTimeout(999 * time.Millisecond) 753 754 // "If the PTO timer is then set to a time in the past, it is executed immediately." 755 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.2.1-2 756 test.send(initialSpace, 2, sentPacket{ 757 ackEliciting: true, 758 inFlight: true, 759 size: 3 * 1200, 760 }) 761 test.wantNoTimeout() 762 t.Logf("resetting expired PTO timer should exeute immediately") 763 test.advance(1000 * time.Millisecond) 764 test.datagramReceived(1200) 765 test.wantPTOExpired() 766 test.wantNoTimeout() 767 } 768 769 func TestLossClientSetsPTOWhenHandshakeUnacked(t *testing.T) { 770 // "[...] the client MUST set the PTO timer if the client has not 771 // received an acknowledgment for any of its Handshake packets and 772 // the handshake is not confirmed [...]" 773 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.2.2.1-3 774 test := newLossTest(t, clientSide, lossTestOpts{}) 775 test.send(initialSpace, 0) 776 777 test.wantVar("smoothed_rtt", 333*time.Millisecond) // initial value 778 test.wantVar("rttvar", 333*time.Millisecond/2) // initial value 779 t.Logf("# PTO = smoothed_rtt + max(4*rttvar, 1ms)") 780 test.wantTimeout(999 * time.Millisecond) 781 782 test.advance(333 * time.Millisecond) 783 test.wantTimeout(666 * time.Millisecond) 784 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 785 test.wantAck(initialSpace, 0) 786 t.Logf("# PTO timer set for a client before handshake ack even if no packets in flight") 787 test.wantTimeout(999 * time.Millisecond) 788 789 test.advance(333 * time.Millisecond) 790 test.wantTimeout(666 * time.Millisecond) 791 } 792 793 func TestLossKeysDiscarded(t *testing.T) { 794 // "The sender MUST discard all recovery state associated with 795 // [packets in number spaces with discarded keys] and MUST remove 796 // them from the count of bytes in flight." 797 // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.4-1 798 test := newLossTest(t, clientSide, lossTestOpts{}) 799 test.send(initialSpace, 0, testSentPacketSize(1200)) 800 test.send(handshakeSpace, 0, testSentPacketSize(600)) 801 test.wantVar("bytes_in_flight", 1800) 802 803 test.discardKeys(initialSpace) 804 test.wantVar("bytes_in_flight", 600) 805 806 test.discardKeys(handshakeSpace) 807 test.wantVar("bytes_in_flight", 0) 808 } 809 810 func TestLossInitialCongestionWindow(t *testing.T) { 811 // "Endpoints SHOULD use an initial congestion window of [...]" 812 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.2-1 813 814 // "[...] 10 times the maximum datagram size [...]" 815 test := newLossTest(t, clientSide, lossTestOpts{ 816 maxDatagramSize: 1200, 817 }) 818 t.Logf("# congestion_window = 10*max_datagram_size (1200)") 819 test.wantVar("congestion_window", 12000) 820 821 // "[...] while limiting the window to the larger of 14720 bytes [...]" 822 test = newLossTest(t, clientSide, lossTestOpts{ 823 maxDatagramSize: 1500, 824 }) 825 t.Logf("# congestion_window limited to 14720 bytes") 826 test.wantVar("congestion_window", 14720) 827 828 // "[...] or twice the maximum datagram size." 829 test = newLossTest(t, clientSide, lossTestOpts{ 830 maxDatagramSize: 10000, 831 }) 832 t.Logf("# congestion_window limited to 2*max_datagram_size (10000)") 833 test.wantVar("congestion_window", 20000) 834 835 for _, tc := range []struct { 836 maxDatagramSize int 837 wantInitialBurst int 838 }{{ 839 // "[...] 10 times the maximum datagram size [...]" 840 maxDatagramSize: 1200, 841 wantInitialBurst: 12000, 842 }, { 843 // "[...] while limiting the window to the larger of 14720 bytes [...]" 844 maxDatagramSize: 1500, 845 wantInitialBurst: 14720, 846 }, { 847 // "[...] or twice the maximum datagram size." 848 maxDatagramSize: 10000, 849 wantInitialBurst: 20000, 850 }} { 851 t.Run(fmt.Sprintf("max_datagram_size=%v", tc.maxDatagramSize), func(t *testing.T) { 852 test := newLossTest(t, clientSide, lossTestOpts{ 853 maxDatagramSize: tc.maxDatagramSize, 854 }) 855 856 var num packetNumber 857 window := tc.wantInitialBurst 858 for window >= tc.maxDatagramSize { 859 t.Logf("# %v bytes of initial congestion window remain", window) 860 test.send(initialSpace, num, sentPacket{ 861 ackEliciting: true, 862 inFlight: true, 863 size: tc.maxDatagramSize, 864 }) 865 window -= tc.maxDatagramSize 866 num++ 867 } 868 t.Logf("# congestion window (%v) < max_datagram_size, congestion control blocks send", window) 869 test.wantSendLimit(ccLimited) 870 }) 871 } 872 } 873 874 func TestLossBytesInFlight(t *testing.T) { 875 test := newLossTest(t, clientSide, lossTestOpts{ 876 maxDatagramSize: 1200, 877 }) 878 t.Logf("# sent packets are added to bytes_in_flight") 879 test.wantVar("bytes_in_flight", 0) 880 test.send(initialSpace, 0, testSentPacketSize(1200)) 881 test.wantVar("bytes_in_flight", 1200) 882 test.send(initialSpace, 1, testSentPacketSize(800)) 883 test.wantVar("bytes_in_flight", 2000) 884 885 t.Logf("# acked packets are removed from bytes_in_flight") 886 test.advance(10 * time.Millisecond) 887 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{1, 2}) 888 test.wantAck(initialSpace, 1) 889 test.wantVar("bytes_in_flight", 1200) 890 891 t.Logf("# lost packets are removed from bytes_in_flight") 892 test.advanceToLossTimer() 893 test.wantLoss(initialSpace, 0) 894 test.wantVar("bytes_in_flight", 0) 895 } 896 897 func TestLossCongestionWindowLimit(t *testing.T) { 898 // "An endpoint MUST NOT send a packet if it would cause bytes_in_flight 899 // [...] to be larger than the congestion window [...]" 900 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7-7 901 test := newLossTest(t, clientSide, lossTestOpts{ 902 maxDatagramSize: 1200, 903 }) 904 t.Logf("# consume the initial congestion window") 905 test.send(initialSpace, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, testSentPacketSize(1200)) 906 test.wantSendLimit(ccLimited) 907 908 t.Logf("# give the pacer bucket time to refill") 909 test.advance(333 * time.Millisecond) // initial RTT 910 911 t.Logf("# sending limited by congestion window, not the pacer") 912 test.wantVar("congestion_window", 12000) 913 test.wantVar("bytes_in_flight", 12000) 914 test.wantVar("pacer_bucket", 12000) 915 test.wantSendLimit(ccLimited) 916 917 t.Logf("# receiving an ack opens up the congestion window") 918 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 919 test.wantAck(initialSpace, 0) 920 test.wantSendLimit(ccOK) 921 } 922 923 func TestLossCongestionStates(t *testing.T) { 924 test := newLossTest(t, clientSide, lossTestOpts{ 925 maxDatagramSize: 1200, 926 }) 927 t.Logf("# consume the initial congestion window") 928 test.send(initialSpace, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, testSentPacketSize(1200)) 929 test.wantSendLimit(ccLimited) 930 test.wantVar("congestion_window", 12000) 931 932 // "While a sender is in slow start, the congestion window 933 // increases by the number of bytes acknowledged [...]" 934 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.1-2 935 test.advance(333 * time.Millisecond) 936 t.Logf("# congestion window increases by number of bytes acked (1200)") 937 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 938 test.wantAck(initialSpace, 0) 939 test.wantVar("congestion_window", 13200) // 12000 + 1200 940 941 t.Logf("# congestion window increases by number of bytes acked (2400)") 942 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 3}) 943 test.wantAck(initialSpace, 1, 2) 944 test.wantVar("congestion_window", 15600) // 12000 + 3*1200 945 946 // TODO: ECN-CE count 947 948 // "The sender MUST exit slow start and enter a recovery period 949 // when a packet is lost [...]" 950 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.1-3 951 t.Logf("# loss of a packet triggers entry to a recovery period") 952 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{6, 7}) 953 test.wantAck(initialSpace, 6) 954 test.wantLoss(initialSpace, 3) 955 956 // "On entering a recovery period, a sender MUST set the slow start 957 // threshold to half the value of the congestion window when loss is detected." 958 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.2-2 959 t.Logf("# slow_start_threshold = congestion_window / 2") 960 test.wantVar("slow_start_threshold", 7800) // 15600/2 961 962 // "[...] a single packet can be sent prior to reduction [of the congestion window]." 963 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.2-3 964 test.send(initialSpace, 10, testSentPacketSize(1200)) 965 966 // "The congestion window MUST be set to the reduced value of the slow start 967 // threshold before exiting the recovery period." 968 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.2-2 969 t.Logf("# congestion window reduced to slow start threshold") 970 test.wantVar("congestion_window", 7800) 971 972 t.Logf("# acks for packets sent before recovery started do not affect congestion") 973 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 10}) 974 test.wantAck(initialSpace, 4, 5, 7, 8, 9) 975 test.wantVar("slow_start_threshold", 7800) 976 test.wantVar("congestion_window", 7800) 977 978 // "A recovery period ends and the sender enters congestion avoidance when 979 // a packet sent during the recovery period is acknowledged." 980 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.2-5 981 t.Logf("# recovery ends and congestion avoidance begins when packet 10 is acked") 982 test.advance(333 * time.Millisecond) 983 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 11}) 984 test.wantAck(initialSpace, 10) 985 986 // "[...] limit the increase to the congestion window to at most one 987 // maximum datagram size for each congestion window that is acknowledged." 988 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.3-2 989 t.Logf("# after processing acks for one congestion window's worth of data...") 990 test.send(initialSpace, 11, 12, 13, 14, 15, 16, testSentPacketSize(1200)) 991 test.advance(333 * time.Millisecond) 992 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 17}) 993 test.wantAck(initialSpace, 11, 12, 13, 14, 15, 16) 994 t.Logf("# ...congestion window increases by max_datagram_size") 995 test.wantVar("congestion_window", 9000) // 7800 + 1200 996 997 // "The sender exits congestion avoidance and enters a recovery period 998 // when a packet is lost [...]" 999 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.3-3 1000 test.send(initialSpace, 17, 18, 19, 20, 21, testSentPacketSize(1200)) 1001 test.advance(333 * time.Millisecond) 1002 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{18, 21}) 1003 test.wantAck(initialSpace, 18, 19, 20) 1004 test.wantLoss(initialSpace, 17) 1005 t.Logf("# slow_start_threshold = congestion_window / 2") 1006 test.wantVar("slow_start_threshold", 4500) 1007 } 1008 1009 func TestLossMinimumCongestionWindow(t *testing.T) { 1010 // "The RECOMMENDED [minimum congestion window] is 2 * max_datagram_size." 1011 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.2-4 1012 test := newLossTest(t, clientSide, lossTestOpts{ 1013 maxDatagramSize: 1200, 1014 }) 1015 test.send(initialSpace, 0, 1, 2, 3, testSentPacketSize(1200)) 1016 test.wantVar("congestion_window", 12000) 1017 1018 t.Logf("# enter recovery") 1019 test.advance(333 * time.Millisecond) 1020 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{3, 4}) 1021 test.wantAck(initialSpace, 3) 1022 test.wantLoss(initialSpace, 0) 1023 test.wantVar("congestion_window", 6000) 1024 1025 t.Logf("# enter congestion avoidance and return to recovery") 1026 test.send(initialSpace, 4, 5, 6, 7) 1027 test.advance(333 * time.Millisecond) 1028 test.wantLoss(initialSpace, 1, 2) 1029 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{7, 8}) 1030 test.wantAck(initialSpace, 7) 1031 test.wantLoss(initialSpace, 4) 1032 test.wantVar("congestion_window", 3000) 1033 1034 t.Logf("# enter congestion avoidance and return to recovery") 1035 test.send(initialSpace, 8, 9, 10, 11) 1036 test.advance(333 * time.Millisecond) 1037 test.wantLoss(initialSpace, 5, 6) 1038 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{11, 12}) 1039 test.wantAck(initialSpace, 11) 1040 test.wantLoss(initialSpace, 8) 1041 t.Logf("# congestion window does not fall below 2*max_datagram_size") 1042 test.wantVar("congestion_window", 2400) 1043 1044 t.Logf("# enter congestion avoidance and return to recovery") 1045 test.send(initialSpace, 12, 13, 14, 15) 1046 test.advance(333 * time.Millisecond) 1047 test.wantLoss(initialSpace, 9, 10) 1048 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{15, 16}) 1049 test.wantAck(initialSpace, 15) 1050 test.wantLoss(initialSpace, 12) 1051 t.Logf("# congestion window does not fall below 2*max_datagram_size") 1052 test.wantVar("congestion_window", 2400) 1053 } 1054 1055 func TestLossPersistentCongestion(t *testing.T) { 1056 // "When persistent congestion is declared, the sender's congestion 1057 // window MUST be reduced to the minimum congestion window [...]" 1058 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.6.2-6 1059 test := newLossTest(t, clientSide, lossTestOpts{ 1060 maxDatagramSize: 1200, 1061 }) 1062 test.send(initialSpace, 0, testSentPacketSize(1200)) 1063 test.c.cc.setUnderutilized(nil, true) 1064 1065 test.advance(10 * time.Millisecond) 1066 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 1067 test.wantAck(initialSpace, 0) 1068 1069 t.Logf("# set rttvar for simplicity") 1070 test.setRTTVar(0) 1071 test.wantVar("smoothed_rtt", 10*time.Millisecond) 1072 t.Logf("# persistent congestion duration = 3*(smoothed_rtt + timerGranularity + max_ack_delay)") 1073 t.Logf("# persistent congestion duration = 108ms") 1074 1075 t.Logf("# sending packets 1-5 over 108ms") 1076 test.send(initialSpace, 1, testSentPacketSize(1200)) 1077 1078 test.advance(11 * time.Millisecond) // total 11ms 1079 test.wantPTOExpired() 1080 test.send(initialSpace, 2, testSentPacketSize(1200)) 1081 1082 test.advance(22 * time.Millisecond) // total 33ms 1083 test.wantPTOExpired() 1084 test.send(initialSpace, 3, testSentPacketSize(1200)) 1085 1086 test.advance(44 * time.Millisecond) // total 77ms 1087 test.wantPTOExpired() 1088 test.send(initialSpace, 4, testSentPacketSize(1200)) 1089 1090 test.advance(31 * time.Millisecond) // total 108ms 1091 test.send(initialSpace, 5, testSentPacketSize(1200)) 1092 t.Logf("# 108ms between packets 1-5") 1093 1094 test.wantVar("congestion_window", 12000) 1095 t.Logf("# triggering loss of packets 1-5") 1096 test.send(initialSpace, 6, 7, 8, testSentPacketSize(1200)) 1097 test.advance(10 * time.Millisecond) 1098 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{8, 9}) 1099 test.wantAck(initialSpace, 8) 1100 test.wantLoss(initialSpace, 1, 2, 3, 4, 5) 1101 1102 t.Logf("# lost packets spanning persistent congestion duration") 1103 t.Logf("# congestion_window = 2 * max_datagram_size (minimum)") 1104 test.wantVar("congestion_window", 2400) 1105 } 1106 1107 func TestLossSimplePersistentCongestion(t *testing.T) { 1108 // Simpler version of TestLossPersistentCongestion which acts as a 1109 // base for subsequent tests. 1110 test := newLossTest(t, clientSide, lossTestOpts{ 1111 maxDatagramSize: 1200, 1112 }) 1113 1114 t.Logf("# establish initial RTT sample") 1115 test.send(initialSpace, 0, testSentPacketSize(1200)) 1116 test.advance(10 * time.Millisecond) 1117 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 1118 test.wantAck(initialSpace, 0) 1119 1120 t.Logf("# send two packets spanning persistent congestion duration") 1121 test.send(initialSpace, 1, testSentPacketSize(1200)) 1122 t.Logf("# 2000ms >> persistent congestion duration") 1123 test.advance(2000 * time.Millisecond) 1124 test.wantPTOExpired() 1125 test.send(initialSpace, 2, testSentPacketSize(1200)) 1126 1127 t.Logf("# trigger loss of previous packets") 1128 test.advance(10 * time.Millisecond) 1129 test.send(initialSpace, 3, testSentPacketSize(1200)) 1130 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{3, 4}) 1131 test.wantAck(initialSpace, 3) 1132 test.wantLoss(initialSpace, 1, 2) 1133 1134 t.Logf("# persistent congestion detected") 1135 test.wantVar("congestion_window", 2400) 1136 } 1137 1138 func TestLossPersistentCongestionAckElicitingPackets(t *testing.T) { 1139 // "These two packets MUST be ack-eliciting [...]" 1140 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.6.2-3 1141 test := newLossTest(t, clientSide, lossTestOpts{ 1142 maxDatagramSize: 1200, 1143 }) 1144 1145 t.Logf("# establish initial RTT sample") 1146 test.send(initialSpace, 0, testSentPacketSize(1200)) 1147 test.advance(10 * time.Millisecond) 1148 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 1149 test.wantAck(initialSpace, 0) 1150 1151 t.Logf("# send two packets spanning persistent congestion duration") 1152 test.send(initialSpace, 1, testSentPacketSize(1200)) 1153 t.Logf("# 2000ms >> persistent congestion duration") 1154 test.advance(2000 * time.Millisecond) 1155 test.wantPTOExpired() 1156 test.send(initialSpace, 2, sentPacket{ 1157 inFlight: true, 1158 ackEliciting: false, 1159 size: 1200, 1160 }) 1161 test.send(initialSpace, 3, testSentPacketSize(1200)) // PTO probe 1162 1163 t.Logf("# trigger loss of previous packets") 1164 test.advance(10 * time.Millisecond) 1165 test.send(initialSpace, 4, testSentPacketSize(1200)) 1166 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{3, 5}) 1167 test.wantAck(initialSpace, 3) 1168 test.wantAck(initialSpace, 4) 1169 test.wantLoss(initialSpace, 1, 2) 1170 1171 t.Logf("# persistent congestion not detected: packet 2 is not ack-eliciting") 1172 test.wantVar("congestion_window", (12000+1200+1200-1200)/2) 1173 } 1174 1175 func TestLossNoPersistentCongestionWithoutRTTSample(t *testing.T) { 1176 // "The persistent congestion period SHOULD NOT start until there 1177 // is at least one RTT sample." 1178 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.6.2-4 1179 test := newLossTest(t, clientSide, lossTestOpts{ 1180 maxDatagramSize: 1200, 1181 }) 1182 1183 t.Logf("# packets sent before initial RTT sample") 1184 test.send(initialSpace, 0, testSentPacketSize(1200)) 1185 test.advance(2000 * time.Millisecond) 1186 test.wantPTOExpired() 1187 test.send(initialSpace, 1, testSentPacketSize(1200)) 1188 1189 test.advance(10 * time.Millisecond) 1190 test.send(initialSpace, 2, testSentPacketSize(1200)) 1191 1192 t.Logf("# first ack establishes RTT sample") 1193 test.advance(10 * time.Millisecond) 1194 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{2, 3}) 1195 test.wantAck(initialSpace, 2) 1196 test.wantLoss(initialSpace, 0, 1) 1197 1198 t.Logf("# loss of packets before initial RTT sample does not cause persistent congestion") 1199 test.wantVar("congestion_window", 12000/2) 1200 } 1201 1202 func TestLossPacerRefillRate(t *testing.T) { 1203 // "A sender SHOULD pace sending of all in-flight packets based on 1204 // input from the congestion controller." 1205 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.7-1 1206 test := newLossTest(t, clientSide, lossTestOpts{ 1207 maxDatagramSize: 1200, 1208 }) 1209 t.Logf("# consume the initial congestion window") 1210 test.send(initialSpace, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, testSentPacketSize(1200)) 1211 test.wantSendLimit(ccLimited) 1212 test.wantVar("pacer_bucket", 0) 1213 test.wantVar("congestion_window", 12000) 1214 1215 t.Logf("# first RTT sample establishes smoothed_rtt") 1216 rtt := 100 * time.Millisecond 1217 test.advance(rtt) 1218 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 10}) 1219 test.wantAck(initialSpace, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 1220 test.wantVar("congestion_window", 24000) // 12000 + 10*1200 1221 test.wantVar("smoothed_rtt", rtt) 1222 1223 t.Logf("# advance 1 RTT to let the pacer bucket refill completely") 1224 test.advance(100 * time.Millisecond) 1225 t.Logf("# pacer_bucket = initial_congestion_window") 1226 test.wantVar("pacer_bucket", 12000) 1227 1228 t.Logf("# consume capacity from the pacer bucket") 1229 test.send(initialSpace, 10, testSentPacketSize(1200)) 1230 test.wantVar("pacer_bucket", 10800) // 12000 - 1200 1231 test.send(initialSpace, 11, testSentPacketSize(600)) 1232 test.wantVar("pacer_bucket", 10200) // 10800 - 600 1233 test.send(initialSpace, 12, testSentPacketSize(600)) 1234 test.wantVar("pacer_bucket", 9600) // 10200 - 600 1235 test.send(initialSpace, 13, 14, 15, 16, testSentPacketSize(1200)) 1236 test.wantVar("pacer_bucket", 4800) // 9600 - 4*1200 1237 1238 t.Logf("# advance 1/10 of an RTT, bucket refills") 1239 test.advance(rtt / 10) 1240 t.Logf("# pacer_bucket += 1.25 * (1/10) * congestion_window") 1241 t.Logf("# += 3000") 1242 test.wantVar("pacer_bucket", 7800) 1243 } 1244 1245 func TestLossPacerNextSendTime(t *testing.T) { 1246 test := newLossTest(t, clientSide, lossTestOpts{ 1247 maxDatagramSize: 1200, 1248 }) 1249 t.Logf("# consume the initial congestion window") 1250 test.send(initialSpace, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, testSentPacketSize(1200)) 1251 test.wantSendLimit(ccLimited) 1252 test.wantVar("pacer_bucket", 0) 1253 test.wantVar("congestion_window", 12000) 1254 1255 t.Logf("# first RTT sample establishes smoothed_rtt") 1256 rtt := 100 * time.Millisecond 1257 test.advance(rtt) 1258 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 10}) 1259 test.wantAck(initialSpace, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 1260 test.wantVar("congestion_window", 24000) // 12000 + 10*1200 1261 test.wantVar("smoothed_rtt", rtt) 1262 1263 t.Logf("# advance 1 RTT to let the pacer bucket refill completely") 1264 test.advance(100 * time.Millisecond) 1265 t.Logf("# pacer_bucket = initial_congestion_window") 1266 test.wantVar("pacer_bucket", 12000) 1267 1268 t.Logf("# consume the refilled pacer bucket") 1269 test.send(initialSpace, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, testSentPacketSize(1200)) 1270 test.wantSendLimit(ccPaced) 1271 1272 t.Logf("# refill rate = 1.25 * congestion_window / rtt") 1273 test.wantSendDelay(rtt / 25) // rtt / (1.25 * 24000 / 1200) 1274 1275 t.Logf("# no capacity available yet") 1276 test.advance(rtt / 50) 1277 test.wantVar("pacer_bucket", -600) 1278 test.wantSendLimit(ccPaced) 1279 1280 t.Logf("# capacity available") 1281 test.advance(rtt / 50) 1282 test.wantVar("pacer_bucket", 0) 1283 test.wantSendLimit(ccOK) 1284 } 1285 1286 func TestLossCongestionWindowUnderutilized(t *testing.T) { 1287 // "When bytes in flight is smaller than the congestion window 1288 // and sending is not pacing limited [...] the congestion window 1289 // SHOULD NOT be increased in either slow start or congestion avoidance." 1290 // https://www.rfc-editor.org/rfc/rfc9002.html#section-7.8-1 1291 test := newLossTest(t, clientSide, lossTestOpts{ 1292 maxDatagramSize: 1200, 1293 }) 1294 test.send(initialSpace, 0, testSentPacketSize(1200)) 1295 test.setUnderutilized(true) 1296 t.Logf("# underutilized: %v", test.c.cc.underutilized) 1297 test.wantVar("congestion_window", 12000) 1298 1299 test.advance(10 * time.Millisecond) 1300 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 1}) 1301 test.wantAck(initialSpace, 0) 1302 t.Logf("# congestion window does not increase, because window is underutilized") 1303 test.wantVar("congestion_window", 12000) 1304 1305 t.Logf("# refill pacer bucket") 1306 test.advance(10 * time.Millisecond) 1307 test.wantVar("pacer_bucket", 12000) 1308 1309 test.send(initialSpace, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, testSentPacketSize(1200)) 1310 test.setUnderutilized(false) 1311 test.advance(10 * time.Millisecond) 1312 test.ack(initialSpace, 0*time.Millisecond, i64range[packetNumber]{0, 11}) 1313 test.wantAck(initialSpace, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 1314 t.Logf("# congestion window increases") 1315 test.wantVar("congestion_window", 24000) 1316 } 1317 1318 type lossTest struct { 1319 t *testing.T 1320 c lossState 1321 now time.Time 1322 fates map[spaceNum]packetFate 1323 failed bool 1324 } 1325 1326 type lossTestOpts struct { 1327 maxDatagramSize int 1328 } 1329 1330 func newLossTest(t *testing.T, side connSide, opts lossTestOpts) *lossTest { 1331 c := &lossTest{ 1332 t: t, 1333 now: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), 1334 fates: make(map[spaceNum]packetFate), 1335 } 1336 maxDatagramSize := 1200 1337 if opts.maxDatagramSize != 0 { 1338 maxDatagramSize = opts.maxDatagramSize 1339 } 1340 c.c.init(side, maxDatagramSize, c.now) 1341 t.Cleanup(func() { 1342 if !c.failed { 1343 c.checkUnexpectedEvents() 1344 } 1345 }) 1346 return c 1347 } 1348 1349 type spaceNum struct { 1350 space numberSpace 1351 num packetNumber 1352 } 1353 1354 func (c *lossTest) checkUnexpectedEvents() { 1355 c.t.Helper() 1356 for sn, fate := range c.fates { 1357 c.t.Errorf("ERROR: unexpected %v: %v %v", fate, sn.space, sn.num) 1358 } 1359 if c.c.ptoExpired { 1360 c.t.Errorf("ERROR: PTO timer unexpectedly expired") 1361 } 1362 } 1363 1364 func (c *lossTest) setSmoothedRTT(d time.Duration) { 1365 c.t.Helper() 1366 c.checkUnexpectedEvents() 1367 c.t.Logf("set smoothed_rtt to %v", d) 1368 c.c.rtt.smoothedRTT = d 1369 } 1370 1371 func (c *lossTest) setRTTVar(d time.Duration) { 1372 c.t.Helper() 1373 c.checkUnexpectedEvents() 1374 c.t.Logf("set rttvar to %v", d) 1375 c.c.rtt.rttvar = d 1376 } 1377 1378 func (c *lossTest) setUnderutilized(v bool) { 1379 c.t.Logf("set congestion window underutilized: %v", v) 1380 c.c.cc.setUnderutilized(nil, v) 1381 } 1382 1383 func (c *lossTest) advance(d time.Duration) { 1384 c.t.Helper() 1385 c.checkUnexpectedEvents() 1386 c.t.Logf("advance time %v", d) 1387 c.now = c.now.Add(d) 1388 c.c.advance(c.now, c.onAckOrLoss) 1389 } 1390 1391 func (c *lossTest) advanceToLossTimer() { 1392 c.t.Helper() 1393 c.checkUnexpectedEvents() 1394 d := c.c.timer.Sub(c.now) 1395 c.t.Logf("advance time %v (up to loss timer)", d) 1396 if d < 0 { 1397 c.t.Fatalf("loss timer is in the past") 1398 } 1399 c.now = c.c.timer 1400 c.c.advance(c.now, c.onAckOrLoss) 1401 } 1402 1403 type testSentPacketSize int 1404 1405 func (c *lossTest) send(spaceID numberSpace, opts ...any) { 1406 c.t.Helper() 1407 c.checkUnexpectedEvents() 1408 var nums []packetNumber 1409 prototype := sentPacket{ 1410 ackEliciting: true, 1411 inFlight: true, 1412 } 1413 for _, o := range opts { 1414 switch o := o.(type) { 1415 case sentPacket: 1416 prototype = o 1417 case testSentPacketSize: 1418 prototype.size = int(o) 1419 case int: 1420 nums = append(nums, packetNumber(o)) 1421 case packetNumber: 1422 nums = append(nums, o) 1423 case i64range[packetNumber]: 1424 for num := o.start; num < o.end; num++ { 1425 nums = append(nums, num) 1426 } 1427 } 1428 } 1429 c.t.Logf("send %v %v", spaceID, nums) 1430 limit, _ := c.c.sendLimit(c.now) 1431 if prototype.inFlight && limit != ccOK { 1432 c.t.Fatalf("congestion control blocks sending packet") 1433 } 1434 if !prototype.inFlight && limit == ccBlocked { 1435 c.t.Fatalf("congestion control blocks sending packet") 1436 } 1437 for _, num := range nums { 1438 sent := &sentPacket{} 1439 *sent = prototype 1440 sent.num = num 1441 c.c.packetSent(c.now, nil, spaceID, sent) 1442 } 1443 } 1444 1445 func (c *lossTest) datagramReceived(size int) { 1446 c.t.Helper() 1447 c.checkUnexpectedEvents() 1448 c.t.Logf("receive %v-byte datagram", size) 1449 c.c.datagramReceived(c.now, size) 1450 } 1451 1452 func (c *lossTest) ack(spaceID numberSpace, ackDelay time.Duration, rs ...i64range[packetNumber]) { 1453 c.t.Helper() 1454 c.checkUnexpectedEvents() 1455 c.c.receiveAckStart() 1456 var acked rangeset[packetNumber] 1457 for _, r := range rs { 1458 c.t.Logf("ack %v delay=%v [%v,%v)", spaceID, ackDelay, r.start, r.end) 1459 acked.add(r.start, r.end) 1460 } 1461 for i, r := range rs { 1462 c.t.Logf("ack %v delay=%v [%v,%v)", spaceID, ackDelay, r.start, r.end) 1463 c.c.receiveAckRange(c.now, spaceID, i, r.start, r.end, c.onAckOrLoss) 1464 } 1465 c.c.receiveAckEnd(c.now, nil, spaceID, ackDelay, c.onAckOrLoss) 1466 } 1467 1468 func (c *lossTest) onAckOrLoss(space numberSpace, sent *sentPacket, fate packetFate) { 1469 c.t.Logf("%v %v %v", fate, space, sent.num) 1470 if _, ok := c.fates[spaceNum{space, sent.num}]; ok { 1471 c.t.Errorf("ERROR: duplicate %v for %v %v", fate, space, sent.num) 1472 } 1473 c.fates[spaceNum{space, sent.num}] = fate 1474 } 1475 1476 func (c *lossTest) confirmHandshake() { 1477 c.t.Helper() 1478 c.checkUnexpectedEvents() 1479 c.t.Logf("confirm handshake") 1480 c.c.confirmHandshake() 1481 } 1482 1483 func (c *lossTest) validateClientAddress() { 1484 c.t.Helper() 1485 c.checkUnexpectedEvents() 1486 c.t.Logf("validate client address") 1487 c.c.validateClientAddress() 1488 } 1489 1490 func (c *lossTest) discardKeys(spaceID numberSpace) { 1491 c.t.Helper() 1492 c.checkUnexpectedEvents() 1493 c.t.Logf("discard %s keys", spaceID) 1494 c.c.discardKeys(c.now, nil, spaceID) 1495 } 1496 1497 func (c *lossTest) setMaxAckDelay(d time.Duration) { 1498 c.t.Helper() 1499 c.checkUnexpectedEvents() 1500 c.t.Logf("set max_ack_delay = %v", d) 1501 c.c.setMaxAckDelay(d) 1502 } 1503 1504 func (c *lossTest) wantAck(spaceID numberSpace, nums ...packetNumber) { 1505 c.t.Helper() 1506 for _, num := range nums { 1507 if c.fates[spaceNum{spaceID, num}] != packetAcked { 1508 c.t.Fatalf("expected ack for %v %v\n", spaceID, num) 1509 } 1510 delete(c.fates, spaceNum{spaceID, num}) 1511 } 1512 } 1513 1514 func (c *lossTest) wantLoss(spaceID numberSpace, nums ...packetNumber) { 1515 c.t.Helper() 1516 for _, num := range nums { 1517 if c.fates[spaceNum{spaceID, num}] != packetLost { 1518 c.t.Fatalf("expected loss of %v %v\n", spaceID, num) 1519 } 1520 delete(c.fates, spaceNum{spaceID, num}) 1521 } 1522 } 1523 1524 func (c *lossTest) wantPTOExpired() { 1525 c.t.Helper() 1526 if !c.c.ptoExpired { 1527 c.t.Fatalf("expected PTO timer to expire") 1528 } else { 1529 c.t.Logf("PTO TIMER EXPIRED") 1530 } 1531 c.c.ptoExpired = false 1532 } 1533 1534 func (l ccLimit) String() string { 1535 switch l { 1536 case ccOK: 1537 return "ccOK" 1538 case ccBlocked: 1539 return "ccBlocked" 1540 case ccLimited: 1541 return "ccLimited" 1542 case ccPaced: 1543 return "ccPaced" 1544 } 1545 return "BUG" 1546 } 1547 1548 func (c *lossTest) wantSendLimit(want ccLimit) { 1549 c.t.Helper() 1550 if got, _ := c.c.sendLimit(c.now); got != want { 1551 c.t.Fatalf("congestion control send limit is %v, want %v", got, want) 1552 } 1553 } 1554 1555 func (c *lossTest) wantSendDelay(want time.Duration) { 1556 c.t.Helper() 1557 limit, next := c.c.sendLimit(c.now) 1558 if limit != ccPaced { 1559 c.t.Fatalf("congestion control limit is %v, want %v", limit, ccPaced) 1560 } 1561 got := next.Sub(c.now) 1562 if got != want { 1563 c.t.Fatalf("delay until next send is %v, want %v", got, want) 1564 } 1565 } 1566 1567 func (c *lossTest) wantVar(name string, want any) { 1568 c.t.Helper() 1569 var got any 1570 switch name { 1571 case "latest_rtt": 1572 got = c.c.rtt.latestRTT 1573 case "min_rtt": 1574 got = c.c.rtt.minRTT 1575 case "smoothed_rtt": 1576 got = c.c.rtt.smoothedRTT 1577 case "rttvar": 1578 got = c.c.rtt.rttvar 1579 case "congestion_window": 1580 got = c.c.cc.congestionWindow 1581 case "slow_start_threshold": 1582 got = c.c.cc.slowStartThreshold 1583 case "bytes_in_flight": 1584 got = c.c.cc.bytesInFlight 1585 case "pacer_bucket": 1586 got = c.c.pacer.bucket 1587 default: 1588 c.t.Fatalf("unknown var %q", name) 1589 } 1590 if got != want { 1591 c.t.Fatalf("%v = %v, want %v\n", name, got, want) 1592 } else { 1593 c.t.Logf("%v = %v", name, got) 1594 } 1595 } 1596 1597 func (c *lossTest) wantTimeout(want time.Duration) { 1598 c.t.Helper() 1599 if c.c.timer.IsZero() { 1600 c.t.Fatalf("loss detection timer is not set, want %v", want) 1601 } 1602 got := c.c.timer.Sub(c.now) 1603 if got != want { 1604 c.t.Fatalf("loss detection timer expires in %v, want %v", got, want) 1605 } 1606 c.t.Logf("loss detection timer expires in %v", got) 1607 } 1608 1609 func (c *lossTest) wantNoTimeout() { 1610 c.t.Helper() 1611 if !c.c.timer.IsZero() { 1612 d := c.c.timer.Sub(c.now) 1613 c.t.Fatalf("loss detection timer expires in %v, want not set", d) 1614 } 1615 c.t.Logf("loss detection timer is not set") 1616 } 1617 1618 func (f packetFate) String() string { 1619 switch f { 1620 case packetAcked: 1621 return "ACK" 1622 case packetLost: 1623 return "LOSS" 1624 default: 1625 panic("unknown packetFate") 1626 } 1627 }