github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/ackhandler/sent_packet_handler.go (about) 1 package ackhandler 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 "time" 8 9 congestionExt "github.com/metacubex/quic-go/congestion" 10 "github.com/metacubex/quic-go/internal/congestion" 11 "github.com/metacubex/quic-go/internal/protocol" 12 "github.com/metacubex/quic-go/internal/qerr" 13 "github.com/metacubex/quic-go/internal/utils" 14 "github.com/metacubex/quic-go/internal/wire" 15 "github.com/metacubex/quic-go/logging" 16 ) 17 18 const ( 19 // Maximum reordering in time space before time based loss detection considers a packet lost. 20 // Specified as an RTT multiplier. 21 timeThreshold = 9.0 / 8 22 // Maximum reordering in packets before packet threshold loss detection considers a packet lost. 23 packetThreshold = 3 24 // Before validating the client's address, the server won't send more than 3x bytes than it received. 25 amplificationFactor = 3 26 // We use Retry packets to derive an RTT estimate. Make sure we don't set the RTT to a super low value yet. 27 minRTTAfterRetry = 5 * time.Millisecond 28 // The PTO duration uses exponential backoff, but is truncated to a maximum value, as allowed by RFC 8961, section 4.4. 29 maxPTODuration = 60 * time.Second 30 ) 31 32 type packetNumberSpace struct { 33 history *sentPacketHistory 34 pns packetNumberGenerator 35 36 lossTime time.Time 37 lastAckElicitingPacketTime time.Time 38 39 largestAcked protocol.PacketNumber 40 largestSent protocol.PacketNumber 41 } 42 43 func newPacketNumberSpace(initialPN protocol.PacketNumber, skipPNs bool) *packetNumberSpace { 44 var pns packetNumberGenerator 45 if skipPNs { 46 pns = newSkippingPacketNumberGenerator(initialPN, protocol.SkipPacketInitialPeriod, protocol.SkipPacketMaxPeriod) 47 } else { 48 pns = newSequentialPacketNumberGenerator(initialPN) 49 } 50 return &packetNumberSpace{ 51 history: newSentPacketHistory(), 52 pns: pns, 53 largestSent: protocol.InvalidPacketNumber, 54 largestAcked: protocol.InvalidPacketNumber, 55 } 56 } 57 58 type sentPacketHandler struct { 59 initialPackets *packetNumberSpace 60 handshakePackets *packetNumberSpace 61 appDataPackets *packetNumberSpace 62 63 // Do we know that the peer completed address validation yet? 64 // Always true for the server. 65 peerCompletedAddressValidation bool 66 bytesReceived protocol.ByteCount 67 bytesSent protocol.ByteCount 68 // Have we validated the peer's address yet? 69 // Always true for the client. 70 peerAddressValidated bool 71 72 handshakeConfirmed bool 73 74 // lowestNotConfirmedAcked is the lowest packet number that we sent an ACK for, but haven't received confirmation, that this ACK actually arrived 75 // example: we send an ACK for packets 90-100 with packet number 20 76 // once we receive an ACK from the peer for packet 20, the lowestNotConfirmedAcked is 101 77 // Only applies to the application-data packet number space. 78 lowestNotConfirmedAcked protocol.PacketNumber 79 80 ackedPackets []*packet // to avoid allocations in detectAndRemoveAckedPackets 81 82 bytesInFlight protocol.ByteCount 83 84 congestion congestion.SendAlgorithmWithDebugInfos 85 congestionMutex sync.RWMutex 86 rttStats *utils.RTTStats 87 88 // The number of times a PTO has been sent without receiving an ack. 89 ptoCount uint32 90 ptoMode SendMode 91 // The number of PTO probe packets that should be sent. 92 // Only applies to the application-data packet number space. 93 numProbesToSend int 94 95 // The alarm timeout 96 alarm time.Time 97 98 enableECN bool 99 ecnTracker ecnHandler 100 101 perspective protocol.Perspective 102 103 tracer *logging.ConnectionTracer 104 logger utils.Logger 105 } 106 107 var ( 108 _ SentPacketHandler = &sentPacketHandler{} 109 _ sentPacketTracker = &sentPacketHandler{} 110 ) 111 112 // clientAddressValidated indicates whether the address was validated beforehand by an address validation token. 113 // If the address was validated, the amplification limit doesn't apply. It has no effect for a client. 114 func newSentPacketHandler( 115 initialPN protocol.PacketNumber, 116 initialMaxDatagramSize protocol.ByteCount, 117 rttStats *utils.RTTStats, 118 clientAddressValidated bool, 119 enableECN bool, 120 pers protocol.Perspective, 121 tracer *logging.ConnectionTracer, 122 logger utils.Logger, 123 ) *sentPacketHandler { 124 congestion := congestion.NewCubicSender( 125 congestion.DefaultClock{}, 126 rttStats, 127 initialMaxDatagramSize, 128 true, // use Reno 129 tracer, 130 ) 131 132 h := &sentPacketHandler{ 133 peerCompletedAddressValidation: pers == protocol.PerspectiveServer, 134 peerAddressValidated: pers == protocol.PerspectiveClient || clientAddressValidated, 135 initialPackets: newPacketNumberSpace(initialPN, false), 136 handshakePackets: newPacketNumberSpace(0, false), 137 appDataPackets: newPacketNumberSpace(0, true), 138 rttStats: rttStats, 139 congestion: congestion, 140 perspective: pers, 141 tracer: tracer, 142 logger: logger, 143 } 144 if enableECN { 145 h.enableECN = true 146 h.ecnTracker = newECNTracker(logger, tracer) 147 } 148 return h 149 } 150 151 func (h *sentPacketHandler) removeFromBytesInFlight(p *packet) { 152 if p.includedInBytesInFlight { 153 if p.Length > h.bytesInFlight { 154 panic("negative bytes_in_flight") 155 } 156 h.bytesInFlight -= p.Length 157 p.includedInBytesInFlight = false 158 } 159 } 160 161 func (h *sentPacketHandler) DropPackets(encLevel protocol.EncryptionLevel) { 162 // The server won't await address validation after the handshake is confirmed. 163 // This applies even if we didn't receive an ACK for a Handshake packet. 164 if h.perspective == protocol.PerspectiveClient && encLevel == protocol.EncryptionHandshake { 165 h.peerCompletedAddressValidation = true 166 } 167 // remove outstanding packets from bytes_in_flight 168 if encLevel == protocol.EncryptionInitial || encLevel == protocol.EncryptionHandshake { 169 pnSpace := h.getPacketNumberSpace(encLevel) 170 // We might already have dropped this packet number space. 171 if pnSpace == nil { 172 return 173 } 174 pnSpace.history.Iterate(func(p *packet) (bool, error) { 175 h.removeFromBytesInFlight(p) 176 return true, nil 177 }) 178 } 179 // drop the packet history 180 //nolint:exhaustive // Not every packet number space can be dropped. 181 switch encLevel { 182 case protocol.EncryptionInitial: 183 h.initialPackets = nil 184 case protocol.EncryptionHandshake: 185 h.handshakePackets = nil 186 case protocol.Encryption0RTT: 187 // This function is only called when 0-RTT is rejected, 188 // and not when the client drops 0-RTT keys when the handshake completes. 189 // When 0-RTT is rejected, all application data sent so far becomes invalid. 190 // Delete the packets from the history and remove them from bytes_in_flight. 191 h.appDataPackets.history.Iterate(func(p *packet) (bool, error) { 192 if p.EncryptionLevel != protocol.Encryption0RTT && !p.skippedPacket { 193 return false, nil 194 } 195 h.removeFromBytesInFlight(p) 196 h.appDataPackets.history.Remove(p.PacketNumber) 197 return true, nil 198 }) 199 default: 200 panic(fmt.Sprintf("Cannot drop keys for encryption level %s", encLevel)) 201 } 202 if h.tracer != nil && h.tracer.UpdatedPTOCount != nil && h.ptoCount != 0 { 203 h.tracer.UpdatedPTOCount(0) 204 } 205 h.ptoCount = 0 206 h.numProbesToSend = 0 207 h.ptoMode = SendNone 208 h.setLossDetectionTimer() 209 } 210 211 func (h *sentPacketHandler) ReceivedBytes(n protocol.ByteCount) { 212 wasAmplificationLimit := h.isAmplificationLimited() 213 h.bytesReceived += n 214 if wasAmplificationLimit && !h.isAmplificationLimited() { 215 h.setLossDetectionTimer() 216 } 217 } 218 219 func (h *sentPacketHandler) ReceivedPacket(l protocol.EncryptionLevel) { 220 if h.perspective == protocol.PerspectiveServer && l == protocol.EncryptionHandshake && !h.peerAddressValidated { 221 h.peerAddressValidated = true 222 h.setLossDetectionTimer() 223 } 224 } 225 226 func (h *sentPacketHandler) packetsInFlight() int { 227 packetsInFlight := h.appDataPackets.history.Len() 228 if h.handshakePackets != nil { 229 packetsInFlight += h.handshakePackets.history.Len() 230 } 231 if h.initialPackets != nil { 232 packetsInFlight += h.initialPackets.history.Len() 233 } 234 return packetsInFlight 235 } 236 237 func (h *sentPacketHandler) SentPacket( 238 t time.Time, 239 pn, largestAcked protocol.PacketNumber, 240 streamFrames []StreamFrame, 241 frames []Frame, 242 encLevel protocol.EncryptionLevel, 243 ecn protocol.ECN, 244 size protocol.ByteCount, 245 isPathMTUProbePacket bool, 246 ) { 247 h.bytesSent += size 248 249 pnSpace := h.getPacketNumberSpace(encLevel) 250 if h.logger.Debug() && pnSpace.history.HasOutstandingPackets() { 251 for p := utils.Max(0, pnSpace.largestSent+1); p < pn; p++ { 252 h.logger.Debugf("Skipping packet number %d", p) 253 } 254 } 255 256 pnSpace.largestSent = pn 257 isAckEliciting := len(streamFrames) > 0 || len(frames) > 0 258 259 if isAckEliciting { 260 pnSpace.lastAckElicitingPacketTime = t 261 h.bytesInFlight += size 262 if h.numProbesToSend > 0 { 263 h.numProbesToSend-- 264 } 265 } 266 cc := h.getCongestionControl() 267 cc.OnPacketSent(t, h.bytesInFlight, pn, size, isAckEliciting) 268 269 if encLevel == protocol.Encryption1RTT && h.ecnTracker != nil { 270 h.ecnTracker.SentPacket(pn, ecn) 271 } 272 273 if !isAckEliciting { 274 pnSpace.history.SentNonAckElicitingPacket(pn) 275 if !h.peerCompletedAddressValidation { 276 h.setLossDetectionTimer() 277 } 278 return 279 } 280 281 p := getPacket() 282 p.SendTime = t 283 p.PacketNumber = pn 284 p.EncryptionLevel = encLevel 285 p.Length = size 286 p.LargestAcked = largestAcked 287 p.StreamFrames = streamFrames 288 p.Frames = frames 289 p.IsPathMTUProbePacket = isPathMTUProbePacket 290 p.includedInBytesInFlight = true 291 292 pnSpace.history.SentAckElicitingPacket(p) 293 if h.tracer != nil && h.tracer.UpdatedMetrics != nil { 294 h.tracer.UpdatedMetrics(h.rttStats, cc.GetCongestionWindow(), h.bytesInFlight, h.packetsInFlight()) 295 } 296 h.setLossDetectionTimer() 297 } 298 299 func (h *sentPacketHandler) getPacketNumberSpace(encLevel protocol.EncryptionLevel) *packetNumberSpace { 300 switch encLevel { 301 case protocol.EncryptionInitial: 302 return h.initialPackets 303 case protocol.EncryptionHandshake: 304 return h.handshakePackets 305 case protocol.Encryption0RTT, protocol.Encryption1RTT: 306 return h.appDataPackets 307 default: 308 panic("invalid packet number space") 309 } 310 } 311 312 func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) (bool /* contained 1-RTT packet */, error) { 313 pnSpace := h.getPacketNumberSpace(encLevel) 314 315 largestAcked := ack.LargestAcked() 316 if largestAcked > pnSpace.largestSent { 317 return false, &qerr.TransportError{ 318 ErrorCode: qerr.ProtocolViolation, 319 ErrorMessage: "received ACK for an unsent packet", 320 } 321 } 322 323 // Servers complete address validation when a protected packet is received. 324 if h.perspective == protocol.PerspectiveClient && !h.peerCompletedAddressValidation && 325 (encLevel == protocol.EncryptionHandshake || encLevel == protocol.Encryption1RTT) { 326 h.peerCompletedAddressValidation = true 327 h.logger.Debugf("Peer doesn't await address validation any longer.") 328 // Make sure that the timer is reset, even if this ACK doesn't acknowledge any (ack-eliciting) packets. 329 h.setLossDetectionTimer() 330 } 331 332 priorInFlight := h.bytesInFlight 333 ackedPackets, err := h.detectAndRemoveAckedPackets(ack, encLevel) 334 if err != nil || len(ackedPackets) == 0 { 335 return false, err 336 } 337 338 cc := h.getCongestionControl() 339 340 // update the RTT, if the largest acked is newly acknowledged 341 if len(ackedPackets) > 0 { 342 if p := ackedPackets[len(ackedPackets)-1]; p.PacketNumber == ack.LargestAcked() { 343 // don't use the ack delay for Initial and Handshake packets 344 var ackDelay time.Duration 345 if encLevel == protocol.Encryption1RTT { 346 ackDelay = utils.Min(ack.DelayTime, h.rttStats.MaxAckDelay()) 347 } 348 h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay, rcvTime) 349 if h.logger.Debug() { 350 h.logger.Debugf("\tupdated RTT: %s (σ: %s)", h.rttStats.SmoothedRTT(), h.rttStats.MeanDeviation()) 351 } 352 cc.MaybeExitSlowStart() 353 } 354 } 355 356 ackedPacketsInfo := []congestionExt.AckedPacketInfo{} 357 lostPacketsInfo := []congestionExt.LostPacketInfo{} 358 359 // Only inform the ECN tracker about new 1-RTT ACKs if the ACK increases the largest acked. 360 if encLevel == protocol.Encryption1RTT && h.ecnTracker != nil && largestAcked > pnSpace.largestAcked { 361 congested := h.ecnTracker.HandleNewlyAcked(ackedPackets, int64(ack.ECT0), int64(ack.ECT1), int64(ack.ECNCE)) 362 if congested { 363 h.congestion.OnCongestionEvent(largestAcked, 0, priorInFlight) 364 } 365 } 366 367 pnSpace.largestAcked = utils.Max(pnSpace.largestAcked, largestAcked) 368 369 if lostPacketsInfo, err = h.detectLostPackets(rcvTime, encLevel); err != nil { 370 return false, err 371 } 372 var acked1RTTPacket bool 373 for _, p := range ackedPackets { 374 if p.includedInBytesInFlight && !p.declaredLost { 375 cc.OnPacketAcked(p.PacketNumber, p.Length, priorInFlight, rcvTime) 376 ackedPacketsInfo = append(ackedPacketsInfo, congestionExt.AckedPacketInfo{ 377 PacketNumber: congestionExt.PacketNumber(p.PacketNumber), 378 BytesAcked: congestionExt.ByteCount(p.Length), 379 }) 380 } 381 if p.EncryptionLevel == protocol.Encryption1RTT { 382 acked1RTTPacket = true 383 } 384 h.removeFromBytesInFlight(p) 385 putPacket(p) 386 } 387 388 if cex, ok := h.congestion.(congestion.SendAlgorithmEx); ok && 389 (len(ackedPacketsInfo) != 0 || len(lostPacketsInfo) != 0) { 390 cex.OnCongestionEventEx(priorInFlight, rcvTime, ackedPacketsInfo, lostPacketsInfo) 391 } 392 393 // After this point, we must not use ackedPackets any longer! 394 // We've already returned the buffers. 395 ackedPackets = nil //nolint:ineffassign // This is just to be on the safe side. 396 397 // Reset the pto_count unless the client is unsure if the server has validated the client's address. 398 if h.peerCompletedAddressValidation { 399 if h.tracer != nil && h.tracer.UpdatedPTOCount != nil && h.ptoCount != 0 { 400 h.tracer.UpdatedPTOCount(0) 401 } 402 h.ptoCount = 0 403 } 404 h.numProbesToSend = 0 405 406 if h.tracer != nil && h.tracer.UpdatedMetrics != nil { 407 h.tracer.UpdatedMetrics(h.rttStats, cc.GetCongestionWindow(), h.bytesInFlight, h.packetsInFlight()) 408 } 409 410 h.setLossDetectionTimer() 411 return acked1RTTPacket, nil 412 } 413 414 func (h *sentPacketHandler) GetLowestPacketNotConfirmedAcked() protocol.PacketNumber { 415 return h.lowestNotConfirmedAcked 416 } 417 418 // Packets are returned in ascending packet number order. 419 func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encLevel protocol.EncryptionLevel) ([]*packet, error) { 420 pnSpace := h.getPacketNumberSpace(encLevel) 421 h.ackedPackets = h.ackedPackets[:0] 422 ackRangeIndex := 0 423 lowestAcked := ack.LowestAcked() 424 largestAcked := ack.LargestAcked() 425 err := pnSpace.history.Iterate(func(p *packet) (bool, error) { 426 // Ignore packets below the lowest acked 427 if p.PacketNumber < lowestAcked { 428 return true, nil 429 } 430 // Break after largest acked is reached 431 if p.PacketNumber > largestAcked { 432 return false, nil 433 } 434 435 if ack.HasMissingRanges() { 436 ackRange := ack.AckRanges[len(ack.AckRanges)-1-ackRangeIndex] 437 438 for p.PacketNumber > ackRange.Largest && ackRangeIndex < len(ack.AckRanges)-1 { 439 ackRangeIndex++ 440 ackRange = ack.AckRanges[len(ack.AckRanges)-1-ackRangeIndex] 441 } 442 443 if p.PacketNumber < ackRange.Smallest { // packet not contained in ACK range 444 return true, nil 445 } 446 if p.PacketNumber > ackRange.Largest { 447 return false, fmt.Errorf("BUG: ackhandler would have acked wrong packet %d, while evaluating range %d -> %d", p.PacketNumber, ackRange.Smallest, ackRange.Largest) 448 } 449 } 450 if p.skippedPacket { 451 return false, &qerr.TransportError{ 452 ErrorCode: qerr.ProtocolViolation, 453 ErrorMessage: fmt.Sprintf("received an ACK for skipped packet number: %d (%s)", p.PacketNumber, encLevel), 454 } 455 } 456 h.ackedPackets = append(h.ackedPackets, p) 457 return true, nil 458 }) 459 if h.logger.Debug() && len(h.ackedPackets) > 0 { 460 pns := make([]protocol.PacketNumber, len(h.ackedPackets)) 461 for i, p := range h.ackedPackets { 462 pns[i] = p.PacketNumber 463 } 464 h.logger.Debugf("\tnewly acked packets (%d): %d", len(pns), pns) 465 } 466 467 for _, p := range h.ackedPackets { 468 if p.LargestAcked != protocol.InvalidPacketNumber && encLevel == protocol.Encryption1RTT { 469 h.lowestNotConfirmedAcked = utils.Max(h.lowestNotConfirmedAcked, p.LargestAcked+1) 470 } 471 472 for _, f := range p.Frames { 473 if f.Handler != nil { 474 f.Handler.OnAcked(f.Frame) 475 } 476 } 477 for _, f := range p.StreamFrames { 478 if f.Handler != nil { 479 f.Handler.OnAcked(f.Frame) 480 } 481 } 482 if err := pnSpace.history.Remove(p.PacketNumber); err != nil { 483 return nil, err 484 } 485 if h.tracer != nil && h.tracer.AcknowledgedPacket != nil { 486 h.tracer.AcknowledgedPacket(encLevel, p.PacketNumber) 487 } 488 } 489 490 return h.ackedPackets, err 491 } 492 493 func (h *sentPacketHandler) getLossTimeAndSpace() (time.Time, protocol.EncryptionLevel) { 494 var encLevel protocol.EncryptionLevel 495 var lossTime time.Time 496 497 if h.initialPackets != nil { 498 lossTime = h.initialPackets.lossTime 499 encLevel = protocol.EncryptionInitial 500 } 501 if h.handshakePackets != nil && (lossTime.IsZero() || (!h.handshakePackets.lossTime.IsZero() && h.handshakePackets.lossTime.Before(lossTime))) { 502 lossTime = h.handshakePackets.lossTime 503 encLevel = protocol.EncryptionHandshake 504 } 505 if lossTime.IsZero() || (!h.appDataPackets.lossTime.IsZero() && h.appDataPackets.lossTime.Before(lossTime)) { 506 lossTime = h.appDataPackets.lossTime 507 encLevel = protocol.Encryption1RTT 508 } 509 return lossTime, encLevel 510 } 511 512 func (h *sentPacketHandler) getScaledPTO(includeMaxAckDelay bool) time.Duration { 513 pto := h.rttStats.PTO(includeMaxAckDelay) << h.ptoCount 514 if pto > maxPTODuration || pto <= 0 { 515 return maxPTODuration 516 } 517 return pto 518 } 519 520 // same logic as getLossTimeAndSpace, but for lastAckElicitingPacketTime instead of lossTime 521 func (h *sentPacketHandler) getPTOTimeAndSpace() (pto time.Time, encLevel protocol.EncryptionLevel, ok bool) { 522 // We only send application data probe packets once the handshake is confirmed, 523 // because before that, we don't have the keys to decrypt ACKs sent in 1-RTT packets. 524 if !h.handshakeConfirmed && !h.hasOutstandingCryptoPackets() { 525 if h.peerCompletedAddressValidation { 526 return 527 } 528 t := time.Now().Add(h.getScaledPTO(false)) 529 if h.initialPackets != nil { 530 return t, protocol.EncryptionInitial, true 531 } 532 return t, protocol.EncryptionHandshake, true 533 } 534 535 if h.initialPackets != nil { 536 encLevel = protocol.EncryptionInitial 537 if t := h.initialPackets.lastAckElicitingPacketTime; !t.IsZero() { 538 pto = t.Add(h.getScaledPTO(false)) 539 } 540 } 541 if h.handshakePackets != nil && !h.handshakePackets.lastAckElicitingPacketTime.IsZero() { 542 t := h.handshakePackets.lastAckElicitingPacketTime.Add(h.getScaledPTO(false)) 543 if pto.IsZero() || (!t.IsZero() && t.Before(pto)) { 544 pto = t 545 encLevel = protocol.EncryptionHandshake 546 } 547 } 548 if h.handshakeConfirmed && !h.appDataPackets.lastAckElicitingPacketTime.IsZero() { 549 t := h.appDataPackets.lastAckElicitingPacketTime.Add(h.getScaledPTO(true)) 550 if pto.IsZero() || (!t.IsZero() && t.Before(pto)) { 551 pto = t 552 encLevel = protocol.Encryption1RTT 553 } 554 } 555 return pto, encLevel, true 556 } 557 558 func (h *sentPacketHandler) hasOutstandingCryptoPackets() bool { 559 if h.initialPackets != nil && h.initialPackets.history.HasOutstandingPackets() { 560 return true 561 } 562 if h.handshakePackets != nil && h.handshakePackets.history.HasOutstandingPackets() { 563 return true 564 } 565 return false 566 } 567 568 func (h *sentPacketHandler) hasOutstandingPackets() bool { 569 return h.appDataPackets.history.HasOutstandingPackets() || h.hasOutstandingCryptoPackets() 570 } 571 572 func (h *sentPacketHandler) setLossDetectionTimer() { 573 oldAlarm := h.alarm // only needed in case tracing is enabled 574 lossTime, encLevel := h.getLossTimeAndSpace() 575 if !lossTime.IsZero() { 576 // Early retransmit timer or time loss detection. 577 h.alarm = lossTime 578 if h.tracer != nil && h.tracer.SetLossTimer != nil && h.alarm != oldAlarm { 579 h.tracer.SetLossTimer(logging.TimerTypeACK, encLevel, h.alarm) 580 } 581 return 582 } 583 584 // Cancel the alarm if amplification limited. 585 if h.isAmplificationLimited() { 586 h.alarm = time.Time{} 587 if !oldAlarm.IsZero() { 588 h.logger.Debugf("Canceling loss detection timer. Amplification limited.") 589 if h.tracer != nil && h.tracer.LossTimerCanceled != nil { 590 h.tracer.LossTimerCanceled() 591 } 592 } 593 return 594 } 595 596 // Cancel the alarm if no packets are outstanding 597 if !h.hasOutstandingPackets() && h.peerCompletedAddressValidation { 598 h.alarm = time.Time{} 599 if !oldAlarm.IsZero() { 600 h.logger.Debugf("Canceling loss detection timer. No packets in flight.") 601 if h.tracer != nil && h.tracer.LossTimerCanceled != nil { 602 h.tracer.LossTimerCanceled() 603 } 604 } 605 return 606 } 607 608 // PTO alarm 609 ptoTime, encLevel, ok := h.getPTOTimeAndSpace() 610 if !ok { 611 if !oldAlarm.IsZero() { 612 h.alarm = time.Time{} 613 h.logger.Debugf("Canceling loss detection timer. No PTO needed..") 614 if h.tracer != nil && h.tracer.LossTimerCanceled != nil { 615 h.tracer.LossTimerCanceled() 616 } 617 } 618 return 619 } 620 h.alarm = ptoTime 621 if h.tracer != nil && h.tracer.SetLossTimer != nil && h.alarm != oldAlarm { 622 h.tracer.SetLossTimer(logging.TimerTypePTO, encLevel, h.alarm) 623 } 624 } 625 626 func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.EncryptionLevel) ([]congestionExt.LostPacketInfo, error) { 627 lostPackets := []congestionExt.LostPacketInfo{} 628 pnSpace := h.getPacketNumberSpace(encLevel) 629 pnSpace.lossTime = time.Time{} 630 631 maxRTT := float64(utils.Max(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT())) 632 lossDelay := time.Duration(timeThreshold * maxRTT) 633 634 // Minimum time of granularity before packets are deemed lost. 635 lossDelay = utils.Max(lossDelay, protocol.TimerGranularity) 636 637 // Packets sent before this time are deemed lost. 638 lostSendTime := now.Add(-lossDelay) 639 640 cc := h.getCongestionControl() 641 642 priorInFlight := h.bytesInFlight 643 err := pnSpace.history.Iterate(func(p *packet) (bool, error) { 644 if p.PacketNumber > pnSpace.largestAcked { 645 return false, nil 646 } 647 648 var packetLost bool 649 if p.SendTime.Before(lostSendTime) { 650 packetLost = true 651 if !p.skippedPacket { 652 if h.logger.Debug() { 653 h.logger.Debugf("\tlost packet %d (time threshold)", p.PacketNumber) 654 } 655 if h.tracer != nil && h.tracer.LostPacket != nil { 656 h.tracer.LostPacket(p.EncryptionLevel, p.PacketNumber, logging.PacketLossTimeThreshold) 657 } 658 } 659 } else if pnSpace.largestAcked >= p.PacketNumber+packetThreshold { 660 packetLost = true 661 if !p.skippedPacket { 662 if h.logger.Debug() { 663 h.logger.Debugf("\tlost packet %d (reordering threshold)", p.PacketNumber) 664 } 665 if h.tracer != nil && h.tracer.LostPacket != nil { 666 h.tracer.LostPacket(p.EncryptionLevel, p.PacketNumber, logging.PacketLossReorderingThreshold) 667 } 668 } 669 } else if pnSpace.lossTime.IsZero() { 670 // Note: This conditional is only entered once per call 671 lossTime := p.SendTime.Add(lossDelay) 672 if h.logger.Debug() { 673 h.logger.Debugf("\tsetting loss timer for packet %d (%s) to %s (in %s)", p.PacketNumber, encLevel, lossDelay, lossTime) 674 } 675 pnSpace.lossTime = lossTime 676 } 677 if packetLost { 678 pnSpace.history.DeclareLost(p.PacketNumber) 679 if !p.skippedPacket { 680 // the bytes in flight need to be reduced no matter if the frames in this packet will be retransmitted 681 h.removeFromBytesInFlight(p) 682 h.queueFramesForRetransmission(p) 683 if !p.IsPathMTUProbePacket { 684 cc.OnCongestionEvent(p.PacketNumber, p.Length, priorInFlight) 685 } 686 lostPackets = append(lostPackets, congestionExt.LostPacketInfo{ 687 PacketNumber: congestionExt.PacketNumber(p.PacketNumber), 688 BytesLost: congestionExt.ByteCount(p.Length), 689 }) 690 if encLevel == protocol.Encryption1RTT && h.ecnTracker != nil { 691 h.ecnTracker.LostPacket(p.PacketNumber) 692 } 693 } 694 } 695 return true, nil 696 }) 697 return lostPackets, err 698 } 699 700 func (h *sentPacketHandler) OnLossDetectionTimeout() error { 701 defer h.setLossDetectionTimer() 702 priorInFlight := h.bytesInFlight 703 earliestLossTime, encLevel := h.getLossTimeAndSpace() 704 if !earliestLossTime.IsZero() { 705 if h.logger.Debug() { 706 h.logger.Debugf("Loss detection alarm fired in loss timer mode. Loss time: %s", earliestLossTime) 707 } 708 if h.tracer != nil && h.tracer.LossTimerExpired != nil { 709 h.tracer.LossTimerExpired(logging.TimerTypeACK, encLevel) 710 } 711 // Early retransmit or time loss detection 712 lostPacketsInfo, err := h.detectLostPackets(time.Now(), encLevel) 713 714 if cex, ok := h.congestion.(congestion.SendAlgorithmEx); ok && 715 len(lostPacketsInfo) != 0 { 716 cex.OnCongestionEventEx(priorInFlight, time.Now(), nil, lostPacketsInfo) 717 } 718 719 return err 720 } 721 722 // PTO 723 // When all outstanding are acknowledged, the alarm is canceled in 724 // setLossDetectionTimer. This doesn't reset the timer in the session though. 725 // When OnAlarm is called, we therefore need to make sure that there are 726 // actually packets outstanding. 727 if h.bytesInFlight == 0 && !h.peerCompletedAddressValidation { 728 h.ptoCount++ 729 h.numProbesToSend++ 730 if h.initialPackets != nil { 731 h.ptoMode = SendPTOInitial 732 } else if h.handshakePackets != nil { 733 h.ptoMode = SendPTOHandshake 734 } else { 735 return errors.New("sentPacketHandler BUG: PTO fired, but bytes_in_flight is 0 and Initial and Handshake already dropped") 736 } 737 return nil 738 } 739 740 _, encLevel, ok := h.getPTOTimeAndSpace() 741 if !ok { 742 return nil 743 } 744 if ps := h.getPacketNumberSpace(encLevel); !ps.history.HasOutstandingPackets() && !h.peerCompletedAddressValidation { 745 return nil 746 } 747 h.ptoCount++ 748 if h.logger.Debug() { 749 h.logger.Debugf("Loss detection alarm for %s fired in PTO mode. PTO count: %d", encLevel, h.ptoCount) 750 } 751 if h.tracer != nil { 752 if h.tracer.LossTimerExpired != nil { 753 h.tracer.LossTimerExpired(logging.TimerTypePTO, encLevel) 754 } 755 if h.tracer.UpdatedPTOCount != nil { 756 h.tracer.UpdatedPTOCount(h.ptoCount) 757 } 758 } 759 h.numProbesToSend += 2 760 //nolint:exhaustive // We never arm a PTO timer for 0-RTT packets. 761 switch encLevel { 762 case protocol.EncryptionInitial: 763 h.ptoMode = SendPTOInitial 764 case protocol.EncryptionHandshake: 765 h.ptoMode = SendPTOHandshake 766 case protocol.Encryption1RTT: 767 // skip a packet number in order to elicit an immediate ACK 768 pn := h.PopPacketNumber(protocol.Encryption1RTT) 769 h.getPacketNumberSpace(protocol.Encryption1RTT).history.SkippedPacket(pn) 770 h.ptoMode = SendPTOAppData 771 default: 772 return fmt.Errorf("PTO timer in unexpected encryption level: %s", encLevel) 773 } 774 return nil 775 } 776 777 func (h *sentPacketHandler) GetLossDetectionTimeout() time.Time { 778 return h.alarm 779 } 780 781 func (h *sentPacketHandler) ECNMode(isShortHeaderPacket bool) protocol.ECN { 782 if !h.enableECN { 783 return protocol.ECNUnsupported 784 } 785 if !isShortHeaderPacket { 786 return protocol.ECNNon 787 } 788 return h.ecnTracker.Mode() 789 } 790 791 func (h *sentPacketHandler) PeekPacketNumber(encLevel protocol.EncryptionLevel) (protocol.PacketNumber, protocol.PacketNumberLen) { 792 pnSpace := h.getPacketNumberSpace(encLevel) 793 pn := pnSpace.pns.Peek() 794 // See section 17.1 of RFC 9000. 795 return pn, protocol.GetPacketNumberLengthForHeader(pn, pnSpace.largestAcked) 796 } 797 798 func (h *sentPacketHandler) PopPacketNumber(encLevel protocol.EncryptionLevel) protocol.PacketNumber { 799 pnSpace := h.getPacketNumberSpace(encLevel) 800 skipped, pn := pnSpace.pns.Pop() 801 if skipped { 802 skippedPN := pn - 1 803 pnSpace.history.SkippedPacket(skippedPN) 804 if h.logger.Debug() { 805 h.logger.Debugf("Skipping packet number %d", skippedPN) 806 } 807 } 808 return pn 809 } 810 811 func (h *sentPacketHandler) SendMode(now time.Time) SendMode { 812 numTrackedPackets := h.appDataPackets.history.Len() 813 if h.initialPackets != nil { 814 numTrackedPackets += h.initialPackets.history.Len() 815 } 816 if h.handshakePackets != nil { 817 numTrackedPackets += h.handshakePackets.history.Len() 818 } 819 820 if h.isAmplificationLimited() { 821 h.logger.Debugf("Amplification window limited. Received %d bytes, already sent out %d bytes", h.bytesReceived, h.bytesSent) 822 return SendNone 823 } 824 // Don't send any packets if we're keeping track of the maximum number of packets. 825 // Note that since MaxOutstandingSentPackets is smaller than MaxTrackedSentPackets, 826 // we will stop sending out new data when reaching MaxOutstandingSentPackets, 827 // but still allow sending of retransmissions and ACKs. 828 if numTrackedPackets >= protocol.MaxTrackedSentPackets { 829 if h.logger.Debug() { 830 h.logger.Debugf("Limited by the number of tracked packets: tracking %d packets, maximum %d", numTrackedPackets, protocol.MaxTrackedSentPackets) 831 } 832 return SendNone 833 } 834 if h.numProbesToSend > 0 { 835 return h.ptoMode 836 } 837 // Only send ACKs if we're congestion limited. 838 cc := h.getCongestionControl() 839 if !cc.CanSend(h.bytesInFlight) { 840 if h.logger.Debug() { 841 h.logger.Debugf("Congestion limited: bytes in flight %d, window %d", h.bytesInFlight, cc.GetCongestionWindow()) 842 } 843 return SendAck 844 } 845 if numTrackedPackets >= protocol.MaxOutstandingSentPackets { 846 if h.logger.Debug() { 847 h.logger.Debugf("Max outstanding limited: tracking %d packets, maximum: %d", numTrackedPackets, protocol.MaxOutstandingSentPackets) 848 } 849 return SendAck 850 } 851 if !h.getCongestionControl().HasPacingBudget(now) { 852 return SendPacingLimited 853 } 854 return SendAny 855 } 856 857 func (h *sentPacketHandler) TimeUntilSend() time.Time { 858 return h.getCongestionControl().TimeUntilSend(h.bytesInFlight) 859 } 860 861 func (h *sentPacketHandler) SetMaxDatagramSize(s protocol.ByteCount) { 862 h.getCongestionControl().SetMaxDatagramSize(s) 863 } 864 865 func (h *sentPacketHandler) isAmplificationLimited() bool { 866 if h.peerAddressValidated { 867 return false 868 } 869 return h.bytesSent >= amplificationFactor*h.bytesReceived 870 } 871 872 func (h *sentPacketHandler) QueueProbePacket(encLevel protocol.EncryptionLevel) bool { 873 pnSpace := h.getPacketNumberSpace(encLevel) 874 p := pnSpace.history.FirstOutstanding() 875 if p == nil { 876 return false 877 } 878 h.queueFramesForRetransmission(p) 879 // TODO: don't declare the packet lost here. 880 // Keep track of acknowledged frames instead. 881 h.removeFromBytesInFlight(p) 882 pnSpace.history.DeclareLost(p.PacketNumber) 883 return true 884 } 885 886 func (h *sentPacketHandler) queueFramesForRetransmission(p *packet) { 887 if len(p.Frames) == 0 && len(p.StreamFrames) == 0 { 888 panic("no frames") 889 } 890 for _, f := range p.Frames { 891 if f.Handler != nil { 892 f.Handler.OnLost(f.Frame) 893 } 894 } 895 for _, f := range p.StreamFrames { 896 if f.Handler != nil { 897 f.Handler.OnLost(f.Frame) 898 } 899 } 900 p.StreamFrames = nil 901 p.Frames = nil 902 } 903 904 func (h *sentPacketHandler) ResetForRetry(now time.Time) error { 905 h.bytesInFlight = 0 906 var firstPacketSendTime time.Time 907 h.initialPackets.history.Iterate(func(p *packet) (bool, error) { 908 if firstPacketSendTime.IsZero() { 909 firstPacketSendTime = p.SendTime 910 } 911 if p.declaredLost || p.skippedPacket { 912 return true, nil 913 } 914 h.queueFramesForRetransmission(p) 915 return true, nil 916 }) 917 // All application data packets sent at this point are 0-RTT packets. 918 // In the case of a Retry, we can assume that the server dropped all of them. 919 h.appDataPackets.history.Iterate(func(p *packet) (bool, error) { 920 if !p.declaredLost && !p.skippedPacket { 921 h.queueFramesForRetransmission(p) 922 } 923 return true, nil 924 }) 925 926 // Only use the Retry to estimate the RTT if we didn't send any retransmission for the Initial. 927 // Otherwise, we don't know which Initial the Retry was sent in response to. 928 if h.ptoCount == 0 { 929 // Don't set the RTT to a value lower than 5ms here. 930 h.rttStats.UpdateRTT(utils.Max(minRTTAfterRetry, now.Sub(firstPacketSendTime)), 0, now) 931 if h.logger.Debug() { 932 h.logger.Debugf("\tupdated RTT: %s (σ: %s)", h.rttStats.SmoothedRTT(), h.rttStats.MeanDeviation()) 933 } 934 if h.tracer != nil && h.tracer.UpdatedMetrics != nil { 935 cc := h.getCongestionControl() 936 h.tracer.UpdatedMetrics(h.rttStats, cc.GetCongestionWindow(), h.bytesInFlight, h.packetsInFlight()) 937 } 938 } 939 h.initialPackets = newPacketNumberSpace(h.initialPackets.pns.Peek(), false) 940 h.appDataPackets = newPacketNumberSpace(h.appDataPackets.pns.Peek(), true) 941 oldAlarm := h.alarm 942 h.alarm = time.Time{} 943 if h.tracer != nil { 944 if h.tracer.UpdatedPTOCount != nil { 945 h.tracer.UpdatedPTOCount(0) 946 } 947 if !oldAlarm.IsZero() && h.tracer.LossTimerCanceled != nil { 948 h.tracer.LossTimerCanceled() 949 } 950 } 951 h.ptoCount = 0 952 return nil 953 } 954 955 func (h *sentPacketHandler) SetHandshakeConfirmed() { 956 if h.initialPackets != nil { 957 panic("didn't drop initial correctly") 958 } 959 if h.handshakePackets != nil { 960 panic("didn't drop handshake correctly") 961 } 962 h.handshakeConfirmed = true 963 // We don't send PTOs for application data packets before the handshake completes. 964 // Make sure the timer is armed now, if necessary. 965 h.setLossDetectionTimer() 966 } 967 968 func (h *sentPacketHandler) getCongestionControl() congestion.SendAlgorithmWithDebugInfos { 969 h.congestionMutex.RLock() 970 cc := h.congestion 971 h.congestionMutex.RUnlock() 972 return cc 973 } 974 975 func (h *sentPacketHandler) SetCongestionControl(cc congestionExt.CongestionControl) { 976 h.congestionMutex.Lock() 977 cc.SetRTTStatsProvider(h.rttStats) 978 if ccEx, isEx := cc.(congestionExt.CongestionControlEx); isEx { 979 h.congestion = &ccAdapterEx{ccEx} 980 } else { 981 h.congestion = &ccAdapter{cc} 982 } 983 h.congestionMutex.Unlock() 984 }