github.com/metacubex/mihomo@v1.18.5/transport/tuic/congestion_v2/bandwidth_sampler.go (about) 1 package congestion 2 3 import ( 4 "math" 5 "time" 6 7 "github.com/metacubex/quic-go/congestion" 8 ) 9 10 const ( 11 infRTT = time.Duration(math.MaxInt64) 12 defaultConnectionStateMapQueueSize = 256 13 defaultCandidatesBufferSize = 256 14 ) 15 16 type roundTripCount uint64 17 18 // SendTimeState is a subset of ConnectionStateOnSentPacket which is returned 19 // to the caller when the packet is acked or lost. 20 type sendTimeState struct { 21 // Whether other states in this object is valid. 22 isValid bool 23 // Whether the sender is app limited at the time the packet was sent. 24 // App limited bandwidth sample might be artificially low because the sender 25 // did not have enough data to send in order to saturate the link. 26 isAppLimited bool 27 // Total number of sent bytes at the time the packet was sent. 28 // Includes the packet itself. 29 totalBytesSent congestion.ByteCount 30 // Total number of acked bytes at the time the packet was sent. 31 totalBytesAcked congestion.ByteCount 32 // Total number of lost bytes at the time the packet was sent. 33 totalBytesLost congestion.ByteCount 34 // Total number of inflight bytes at the time the packet was sent. 35 // Includes the packet itself. 36 // It should be equal to |total_bytes_sent| minus the sum of 37 // |total_bytes_acked|, |total_bytes_lost| and total neutered bytes. 38 bytesInFlight congestion.ByteCount 39 } 40 41 func newSendTimeState( 42 isAppLimited bool, 43 totalBytesSent congestion.ByteCount, 44 totalBytesAcked congestion.ByteCount, 45 totalBytesLost congestion.ByteCount, 46 bytesInFlight congestion.ByteCount, 47 ) *sendTimeState { 48 return &sendTimeState{ 49 isValid: true, 50 isAppLimited: isAppLimited, 51 totalBytesSent: totalBytesSent, 52 totalBytesAcked: totalBytesAcked, 53 totalBytesLost: totalBytesLost, 54 bytesInFlight: bytesInFlight, 55 } 56 } 57 58 type extraAckedEvent struct { 59 // The excess bytes acknowlwedged in the time delta for this event. 60 extraAcked congestion.ByteCount 61 62 // The bytes acknowledged and time delta from the event. 63 bytesAcked congestion.ByteCount 64 timeDelta time.Duration 65 // The round trip of the event. 66 round roundTripCount 67 } 68 69 func maxExtraAckedEventFunc(a, b extraAckedEvent) int { 70 if a.extraAcked > b.extraAcked { 71 return 1 72 } else if a.extraAcked < b.extraAcked { 73 return -1 74 } 75 return 0 76 } 77 78 // BandwidthSample 79 type bandwidthSample struct { 80 // The bandwidth at that particular sample. Zero if no valid bandwidth sample 81 // is available. 82 bandwidth Bandwidth 83 // The RTT measurement at this particular sample. Zero if no RTT sample is 84 // available. Does not correct for delayed ack time. 85 rtt time.Duration 86 // |send_rate| is computed from the current packet being acked('P') and an 87 // earlier packet that is acked before P was sent. 88 sendRate Bandwidth 89 // States captured when the packet was sent. 90 stateAtSend sendTimeState 91 } 92 93 func newBandwidthSample() *bandwidthSample { 94 return &bandwidthSample{ 95 sendRate: infBandwidth, 96 } 97 } 98 99 // MaxAckHeightTracker is part of the BandwidthSampler. It is called after every 100 // ack event to keep track the degree of ack aggregation(a.k.a "ack height"). 101 type maxAckHeightTracker struct { 102 // Tracks the maximum number of bytes acked faster than the estimated 103 // bandwidth. 104 maxAckHeightFilter *WindowedFilter[extraAckedEvent, roundTripCount] 105 // The time this aggregation started and the number of bytes acked during it. 106 aggregationEpochStartTime time.Time 107 aggregationEpochBytes congestion.ByteCount 108 // The last sent packet number before the current aggregation epoch started. 109 lastSentPacketNumberBeforeEpoch congestion.PacketNumber 110 // The number of ack aggregation epochs ever started, including the ongoing 111 // one. Stats only. 112 numAckAggregationEpochs uint64 113 ackAggregationBandwidthThreshold float64 114 startNewAggregationEpochAfterFullRound bool 115 reduceExtraAckedOnBandwidthIncrease bool 116 } 117 118 func newMaxAckHeightTracker(windowLength roundTripCount) *maxAckHeightTracker { 119 return &maxAckHeightTracker{ 120 maxAckHeightFilter: NewWindowedFilter(windowLength, maxExtraAckedEventFunc), 121 lastSentPacketNumberBeforeEpoch: invalidPacketNumber, 122 ackAggregationBandwidthThreshold: 1.0, 123 } 124 } 125 126 func (m *maxAckHeightTracker) Get() congestion.ByteCount { 127 return m.maxAckHeightFilter.GetBest().extraAcked 128 } 129 130 func (m *maxAckHeightTracker) Update( 131 bandwidthEstimate Bandwidth, 132 isNewMaxBandwidth bool, 133 roundTripCount roundTripCount, 134 lastSentPacketNumber congestion.PacketNumber, 135 lastAckedPacketNumber congestion.PacketNumber, 136 ackTime time.Time, 137 bytesAcked congestion.ByteCount, 138 ) congestion.ByteCount { 139 forceNewEpoch := false 140 141 if m.reduceExtraAckedOnBandwidthIncrease && isNewMaxBandwidth { 142 // Save and clear existing entries. 143 best := m.maxAckHeightFilter.GetBest() 144 secondBest := m.maxAckHeightFilter.GetSecondBest() 145 thirdBest := m.maxAckHeightFilter.GetThirdBest() 146 m.maxAckHeightFilter.Clear() 147 148 // Reinsert the heights into the filter after recalculating. 149 expectedBytesAcked := bytesFromBandwidthAndTimeDelta(bandwidthEstimate, best.timeDelta) 150 if expectedBytesAcked < best.bytesAcked { 151 best.extraAcked = best.bytesAcked - expectedBytesAcked 152 m.maxAckHeightFilter.Update(best, best.round) 153 } 154 expectedBytesAcked = bytesFromBandwidthAndTimeDelta(bandwidthEstimate, secondBest.timeDelta) 155 if expectedBytesAcked < secondBest.bytesAcked { 156 secondBest.extraAcked = secondBest.bytesAcked - expectedBytesAcked 157 m.maxAckHeightFilter.Update(secondBest, secondBest.round) 158 } 159 expectedBytesAcked = bytesFromBandwidthAndTimeDelta(bandwidthEstimate, thirdBest.timeDelta) 160 if expectedBytesAcked < thirdBest.bytesAcked { 161 thirdBest.extraAcked = thirdBest.bytesAcked - expectedBytesAcked 162 m.maxAckHeightFilter.Update(thirdBest, thirdBest.round) 163 } 164 } 165 166 // If any packet sent after the start of the epoch has been acked, start a new 167 // epoch. 168 if m.startNewAggregationEpochAfterFullRound && 169 m.lastSentPacketNumberBeforeEpoch != invalidPacketNumber && 170 lastAckedPacketNumber != invalidPacketNumber && 171 lastAckedPacketNumber > m.lastSentPacketNumberBeforeEpoch { 172 forceNewEpoch = true 173 } 174 if m.aggregationEpochStartTime.IsZero() || forceNewEpoch { 175 m.aggregationEpochBytes = bytesAcked 176 m.aggregationEpochStartTime = ackTime 177 m.lastSentPacketNumberBeforeEpoch = lastSentPacketNumber 178 m.numAckAggregationEpochs++ 179 return 0 180 } 181 182 // Compute how many bytes are expected to be delivered, assuming max bandwidth 183 // is correct. 184 aggregationDelta := ackTime.Sub(m.aggregationEpochStartTime) 185 expectedBytesAcked := bytesFromBandwidthAndTimeDelta(bandwidthEstimate, aggregationDelta) 186 // Reset the current aggregation epoch as soon as the ack arrival rate is less 187 // than or equal to the max bandwidth. 188 if m.aggregationEpochBytes <= congestion.ByteCount(m.ackAggregationBandwidthThreshold*float64(expectedBytesAcked)) { 189 // Reset to start measuring a new aggregation epoch. 190 m.aggregationEpochBytes = bytesAcked 191 m.aggregationEpochStartTime = ackTime 192 m.lastSentPacketNumberBeforeEpoch = lastSentPacketNumber 193 m.numAckAggregationEpochs++ 194 return 0 195 } 196 197 m.aggregationEpochBytes += bytesAcked 198 199 // Compute how many extra bytes were delivered vs max bandwidth. 200 extraBytesAcked := m.aggregationEpochBytes - expectedBytesAcked 201 newEvent := extraAckedEvent{ 202 extraAcked: expectedBytesAcked, 203 bytesAcked: m.aggregationEpochBytes, 204 timeDelta: aggregationDelta, 205 } 206 m.maxAckHeightFilter.Update(newEvent, roundTripCount) 207 return extraBytesAcked 208 } 209 210 func (m *maxAckHeightTracker) SetFilterWindowLength(length roundTripCount) { 211 m.maxAckHeightFilter.SetWindowLength(length) 212 } 213 214 func (m *maxAckHeightTracker) Reset(newHeight congestion.ByteCount, newTime roundTripCount) { 215 newEvent := extraAckedEvent{ 216 extraAcked: newHeight, 217 round: newTime, 218 } 219 m.maxAckHeightFilter.Reset(newEvent, newTime) 220 } 221 222 func (m *maxAckHeightTracker) SetAckAggregationBandwidthThreshold(threshold float64) { 223 m.ackAggregationBandwidthThreshold = threshold 224 } 225 226 func (m *maxAckHeightTracker) SetStartNewAggregationEpochAfterFullRound(value bool) { 227 m.startNewAggregationEpochAfterFullRound = value 228 } 229 230 func (m *maxAckHeightTracker) SetReduceExtraAckedOnBandwidthIncrease(value bool) { 231 m.reduceExtraAckedOnBandwidthIncrease = value 232 } 233 234 func (m *maxAckHeightTracker) AckAggregationBandwidthThreshold() float64 { 235 return m.ackAggregationBandwidthThreshold 236 } 237 238 func (m *maxAckHeightTracker) NumAckAggregationEpochs() uint64 { 239 return m.numAckAggregationEpochs 240 } 241 242 // AckPoint represents a point on the ack line. 243 type ackPoint struct { 244 ackTime time.Time 245 totalBytesAcked congestion.ByteCount 246 } 247 248 // RecentAckPoints maintains the most recent 2 ack points at distinct times. 249 type recentAckPoints struct { 250 ackPoints [2]ackPoint 251 } 252 253 func (r *recentAckPoints) Update(ackTime time.Time, totalBytesAcked congestion.ByteCount) { 254 if ackTime.Before(r.ackPoints[1].ackTime) { 255 r.ackPoints[1].ackTime = ackTime 256 } else if ackTime.After(r.ackPoints[1].ackTime) { 257 r.ackPoints[0] = r.ackPoints[1] 258 r.ackPoints[1].ackTime = ackTime 259 } 260 261 r.ackPoints[1].totalBytesAcked = totalBytesAcked 262 } 263 264 func (r *recentAckPoints) Clear() { 265 r.ackPoints[0] = ackPoint{} 266 r.ackPoints[1] = ackPoint{} 267 } 268 269 func (r *recentAckPoints) MostRecentPoint() *ackPoint { 270 return &r.ackPoints[1] 271 } 272 273 func (r *recentAckPoints) LessRecentPoint() *ackPoint { 274 if r.ackPoints[0].totalBytesAcked != 0 { 275 return &r.ackPoints[0] 276 } 277 278 return &r.ackPoints[1] 279 } 280 281 // ConnectionStateOnSentPacket represents the information about a sent packet 282 // and the state of the connection at the moment the packet was sent, 283 // specifically the information about the most recently acknowledged packet at 284 // that moment. 285 type connectionStateOnSentPacket struct { 286 // Time at which the packet is sent. 287 sentTime time.Time 288 // Size of the packet. 289 size congestion.ByteCount 290 // The value of |totalBytesSentAtLastAckedPacket| at the time the 291 // packet was sent. 292 totalBytesSentAtLastAckedPacket congestion.ByteCount 293 // The value of |lastAckedPacketSentTime| at the time the packet was 294 // sent. 295 lastAckedPacketSentTime time.Time 296 // The value of |lastAckedPacketAckTime| at the time the packet was 297 // sent. 298 lastAckedPacketAckTime time.Time 299 // Send time states that are returned to the congestion controller when the 300 // packet is acked or lost. 301 sendTimeState sendTimeState 302 } 303 304 // Snapshot constructor. Records the current state of the bandwidth 305 // sampler. 306 // |bytes_in_flight| is the bytes in flight right after the packet is sent. 307 func newConnectionStateOnSentPacket( 308 sentTime time.Time, 309 size congestion.ByteCount, 310 bytesInFlight congestion.ByteCount, 311 sampler *bandwidthSampler, 312 ) *connectionStateOnSentPacket { 313 return &connectionStateOnSentPacket{ 314 sentTime: sentTime, 315 size: size, 316 totalBytesSentAtLastAckedPacket: sampler.totalBytesSentAtLastAckedPacket, 317 lastAckedPacketSentTime: sampler.lastAckedPacketSentTime, 318 lastAckedPacketAckTime: sampler.lastAckedPacketAckTime, 319 sendTimeState: *newSendTimeState( 320 sampler.isAppLimited, 321 sampler.totalBytesSent, 322 sampler.totalBytesAcked, 323 sampler.totalBytesLost, 324 bytesInFlight, 325 ), 326 } 327 } 328 329 // BandwidthSampler keeps track of sent and acknowledged packets and outputs a 330 // bandwidth sample for every packet acknowledged. The samples are taken for 331 // individual packets, and are not filtered; the consumer has to filter the 332 // bandwidth samples itself. In certain cases, the sampler will locally severely 333 // underestimate the bandwidth, hence a maximum filter with a size of at least 334 // one RTT is recommended. 335 // 336 // This class bases its samples on the slope of two curves: the number of bytes 337 // sent over time, and the number of bytes acknowledged as received over time. 338 // It produces a sample of both slopes for every packet that gets acknowledged, 339 // based on a slope between two points on each of the corresponding curves. Note 340 // that due to the packet loss, the number of bytes on each curve might get 341 // further and further away from each other, meaning that it is not feasible to 342 // compare byte values coming from different curves with each other. 343 // 344 // The obvious points for measuring slope sample are the ones corresponding to 345 // the packet that was just acknowledged. Let us denote them as S_1 (point at 346 // which the current packet was sent) and A_1 (point at which the current packet 347 // was acknowledged). However, taking a slope requires two points on each line, 348 // so estimating bandwidth requires picking a packet in the past with respect to 349 // which the slope is measured. 350 // 351 // For that purpose, BandwidthSampler always keeps track of the most recently 352 // acknowledged packet, and records it together with every outgoing packet. 353 // When a packet gets acknowledged (A_1), it has not only information about when 354 // it itself was sent (S_1), but also the information about the latest 355 // acknowledged packet right before it was sent (S_0 and A_0). 356 // 357 // Based on that data, send and ack rate are estimated as: 358 // 359 // send_rate = (bytes(S_1) - bytes(S_0)) / (time(S_1) - time(S_0)) 360 // ack_rate = (bytes(A_1) - bytes(A_0)) / (time(A_1) - time(A_0)) 361 // 362 // Here, the ack rate is intuitively the rate we want to treat as bandwidth. 363 // However, in certain cases (e.g. ack compression) the ack rate at a point may 364 // end up higher than the rate at which the data was originally sent, which is 365 // not indicative of the real bandwidth. Hence, we use the send rate as an upper 366 // bound, and the sample value is 367 // 368 // rate_sample = Min(send_rate, ack_rate) 369 // 370 // An important edge case handled by the sampler is tracking the app-limited 371 // samples. There are multiple meaning of "app-limited" used interchangeably, 372 // hence it is important to understand and to be able to distinguish between 373 // them. 374 // 375 // Meaning 1: connection state. The connection is said to be app-limited when 376 // there is no outstanding data to send. This means that certain bandwidth 377 // samples in the future would not be an accurate indication of the link 378 // capacity, and it is important to inform consumer about that. Whenever 379 // connection becomes app-limited, the sampler is notified via OnAppLimited() 380 // method. 381 // 382 // Meaning 2: a phase in the bandwidth sampler. As soon as the bandwidth 383 // sampler becomes notified about the connection being app-limited, it enters 384 // app-limited phase. In that phase, all *sent* packets are marked as 385 // app-limited. Note that the connection itself does not have to be 386 // app-limited during the app-limited phase, and in fact it will not be 387 // (otherwise how would it send packets?). The boolean flag below indicates 388 // whether the sampler is in that phase. 389 // 390 // Meaning 3: a flag on the sent packet and on the sample. If a sent packet is 391 // sent during the app-limited phase, the resulting sample related to the 392 // packet will be marked as app-limited. 393 // 394 // With the terminology issue out of the way, let us consider the question of 395 // what kind of situation it addresses. 396 // 397 // Consider a scenario where we first send packets 1 to 20 at a regular 398 // bandwidth, and then immediately run out of data. After a few seconds, we send 399 // packets 21 to 60, and only receive ack for 21 between sending packets 40 and 400 // 41. In this case, when we sample bandwidth for packets 21 to 40, the S_0/A_0 401 // we use to compute the slope is going to be packet 20, a few seconds apart 402 // from the current packet, hence the resulting estimate would be extremely low 403 // and not indicative of anything. Only at packet 41 the S_0/A_0 will become 21, 404 // meaning that the bandwidth sample would exclude the quiescence. 405 // 406 // Based on the analysis of that scenario, we implement the following rule: once 407 // OnAppLimited() is called, all sent packets will produce app-limited samples 408 // up until an ack for a packet that was sent after OnAppLimited() was called. 409 // Note that while the scenario above is not the only scenario when the 410 // connection is app-limited, the approach works in other cases too. 411 412 type congestionEventSample struct { 413 // The maximum bandwidth sample from all acked packets. 414 // QuicBandwidth::Zero() if no samples are available. 415 sampleMaxBandwidth Bandwidth 416 // Whether |sample_max_bandwidth| is from a app-limited sample. 417 sampleIsAppLimited bool 418 // The minimum rtt sample from all acked packets. 419 // QuicTime::Delta::Infinite() if no samples are available. 420 sampleRtt time.Duration 421 // For each packet p in acked packets, this is the max value of INFLIGHT(p), 422 // where INFLIGHT(p) is the number of bytes acked while p is inflight. 423 sampleMaxInflight congestion.ByteCount 424 // The send state of the largest packet in acked_packets, unless it is 425 // empty. If acked_packets is empty, it's the send state of the largest 426 // packet in lost_packets. 427 lastPacketSendState sendTimeState 428 // The number of extra bytes acked from this ack event, compared to what is 429 // expected from the flow's bandwidth. Larger value means more ack 430 // aggregation. 431 extraAcked congestion.ByteCount 432 } 433 434 func newCongestionEventSample() *congestionEventSample { 435 return &congestionEventSample{ 436 sampleRtt: infRTT, 437 } 438 } 439 440 type bandwidthSampler struct { 441 // The total number of congestion controlled bytes sent during the connection. 442 totalBytesSent congestion.ByteCount 443 444 // The total number of congestion controlled bytes which were acknowledged. 445 totalBytesAcked congestion.ByteCount 446 447 // The total number of congestion controlled bytes which were lost. 448 totalBytesLost congestion.ByteCount 449 450 // The total number of congestion controlled bytes which have been neutered. 451 totalBytesNeutered congestion.ByteCount 452 453 // The value of |total_bytes_sent_| at the time the last acknowledged packet 454 // was sent. Valid only when |last_acked_packet_sent_time_| is valid. 455 totalBytesSentAtLastAckedPacket congestion.ByteCount 456 457 // The time at which the last acknowledged packet was sent. Set to 458 // QuicTime::Zero() if no valid timestamp is available. 459 lastAckedPacketSentTime time.Time 460 461 // The time at which the most recent packet was acknowledged. 462 lastAckedPacketAckTime time.Time 463 464 // The most recently sent packet. 465 lastSentPacket congestion.PacketNumber 466 467 // The most recently acked packet. 468 lastAckedPacket congestion.PacketNumber 469 470 // Indicates whether the bandwidth sampler is currently in an app-limited 471 // phase. 472 isAppLimited bool 473 474 // The packet that will be acknowledged after this one will cause the sampler 475 // to exit the app-limited phase. 476 endOfAppLimitedPhase congestion.PacketNumber 477 478 // Record of the connection state at the point where each packet in flight was 479 // sent, indexed by the packet number. 480 connectionStateMap *packetNumberIndexedQueue[connectionStateOnSentPacket] 481 482 recentAckPoints recentAckPoints 483 a0Candidates RingBuffer[ackPoint] 484 485 // Maximum number of tracked packets. 486 maxTrackedPackets congestion.ByteCount 487 488 maxAckHeightTracker *maxAckHeightTracker 489 totalBytesAckedAfterLastAckEvent congestion.ByteCount 490 491 // True if connection option 'BSAO' is set. 492 overestimateAvoidance bool 493 494 // True if connection option 'BBRB' is set. 495 limitMaxAckHeightTrackerBySendRate bool 496 } 497 498 func newBandwidthSampler(maxAckHeightTrackerWindowLength roundTripCount) *bandwidthSampler { 499 b := &bandwidthSampler{ 500 maxAckHeightTracker: newMaxAckHeightTracker(maxAckHeightTrackerWindowLength), 501 connectionStateMap: newPacketNumberIndexedQueue[connectionStateOnSentPacket](defaultConnectionStateMapQueueSize), 502 lastSentPacket: invalidPacketNumber, 503 lastAckedPacket: invalidPacketNumber, 504 endOfAppLimitedPhase: invalidPacketNumber, 505 } 506 507 b.a0Candidates.Init(defaultCandidatesBufferSize) 508 509 return b 510 } 511 512 func (b *bandwidthSampler) MaxAckHeight() congestion.ByteCount { 513 return b.maxAckHeightTracker.Get() 514 } 515 516 func (b *bandwidthSampler) NumAckAggregationEpochs() uint64 { 517 return b.maxAckHeightTracker.NumAckAggregationEpochs() 518 } 519 520 func (b *bandwidthSampler) SetMaxAckHeightTrackerWindowLength(length roundTripCount) { 521 b.maxAckHeightTracker.SetFilterWindowLength(length) 522 } 523 524 func (b *bandwidthSampler) ResetMaxAckHeightTracker(newHeight congestion.ByteCount, newTime roundTripCount) { 525 b.maxAckHeightTracker.Reset(newHeight, newTime) 526 } 527 528 func (b *bandwidthSampler) SetStartNewAggregationEpochAfterFullRound(value bool) { 529 b.maxAckHeightTracker.SetStartNewAggregationEpochAfterFullRound(value) 530 } 531 532 func (b *bandwidthSampler) SetLimitMaxAckHeightTrackerBySendRate(value bool) { 533 b.limitMaxAckHeightTrackerBySendRate = value 534 } 535 536 func (b *bandwidthSampler) SetReduceExtraAckedOnBandwidthIncrease(value bool) { 537 b.maxAckHeightTracker.SetReduceExtraAckedOnBandwidthIncrease(value) 538 } 539 540 func (b *bandwidthSampler) EnableOverestimateAvoidance() { 541 if b.overestimateAvoidance { 542 return 543 } 544 545 b.overestimateAvoidance = true 546 b.maxAckHeightTracker.SetAckAggregationBandwidthThreshold(2.0) 547 } 548 549 func (b *bandwidthSampler) IsOverestimateAvoidanceEnabled() bool { 550 return b.overestimateAvoidance 551 } 552 553 func (b *bandwidthSampler) OnPacketSent( 554 sentTime time.Time, 555 packetNumber congestion.PacketNumber, 556 bytes congestion.ByteCount, 557 bytesInFlight congestion.ByteCount, 558 isRetransmittable bool, 559 ) { 560 b.lastSentPacket = packetNumber 561 562 if !isRetransmittable { 563 return 564 } 565 566 b.totalBytesSent += bytes 567 568 // If there are no packets in flight, the time at which the new transmission 569 // opens can be treated as the A_0 point for the purpose of bandwidth 570 // sampling. This underestimates bandwidth to some extent, and produces some 571 // artificially low samples for most packets in flight, but it provides with 572 // samples at important points where we would not have them otherwise, most 573 // importantly at the beginning of the connection. 574 if bytesInFlight == 0 { 575 b.lastAckedPacketAckTime = sentTime 576 if b.overestimateAvoidance { 577 b.recentAckPoints.Clear() 578 b.recentAckPoints.Update(sentTime, b.totalBytesAcked) 579 b.a0Candidates.Clear() 580 b.a0Candidates.PushBack(*b.recentAckPoints.MostRecentPoint()) 581 } 582 b.totalBytesSentAtLastAckedPacket = b.totalBytesSent 583 584 // In this situation ack compression is not a concern, set send rate to 585 // effectively infinite. 586 b.lastAckedPacketSentTime = sentTime 587 } 588 589 b.connectionStateMap.Emplace(packetNumber, newConnectionStateOnSentPacket( 590 sentTime, 591 bytes, 592 bytesInFlight+bytes, 593 b, 594 )) 595 } 596 597 func (b *bandwidthSampler) OnCongestionEvent( 598 ackTime time.Time, 599 ackedPackets []congestion.AckedPacketInfo, 600 lostPackets []congestion.LostPacketInfo, 601 maxBandwidth Bandwidth, 602 estBandwidthUpperBound Bandwidth, 603 roundTripCount roundTripCount, 604 ) congestionEventSample { 605 eventSample := newCongestionEventSample() 606 607 var lastLostPacketSendState sendTimeState 608 609 for _, p := range lostPackets { 610 sendState := b.OnPacketLost(p.PacketNumber, p.BytesLost) 611 if sendState.isValid { 612 lastLostPacketSendState = sendState 613 } 614 } 615 616 if len(ackedPackets) == 0 { 617 // Only populate send state for a loss-only event. 618 eventSample.lastPacketSendState = lastLostPacketSendState 619 return *eventSample 620 } 621 622 var lastAckedPacketSendState sendTimeState 623 var maxSendRate Bandwidth 624 625 for _, p := range ackedPackets { 626 sample := b.onPacketAcknowledged(ackTime, p.PacketNumber) 627 if !sample.stateAtSend.isValid { 628 continue 629 } 630 631 lastAckedPacketSendState = sample.stateAtSend 632 633 if sample.rtt != 0 { 634 eventSample.sampleRtt = Min(eventSample.sampleRtt, sample.rtt) 635 } 636 if sample.bandwidth > eventSample.sampleMaxBandwidth { 637 eventSample.sampleMaxBandwidth = sample.bandwidth 638 eventSample.sampleIsAppLimited = sample.stateAtSend.isAppLimited 639 } 640 if sample.sendRate != infBandwidth { 641 maxSendRate = Max(maxSendRate, sample.sendRate) 642 } 643 inflightSample := b.totalBytesAcked - lastAckedPacketSendState.totalBytesAcked 644 if inflightSample > eventSample.sampleMaxInflight { 645 eventSample.sampleMaxInflight = inflightSample 646 } 647 } 648 649 if !lastLostPacketSendState.isValid { 650 eventSample.lastPacketSendState = lastAckedPacketSendState 651 } else if !lastAckedPacketSendState.isValid { 652 eventSample.lastPacketSendState = lastLostPacketSendState 653 } else { 654 // If two packets are inflight and an alarm is armed to lose a packet and it 655 // wakes up late, then the first of two in flight packets could have been 656 // acknowledged before the wakeup, which re-evaluates loss detection, and 657 // could declare the later of the two lost. 658 if lostPackets[len(lostPackets)-1].PacketNumber > ackedPackets[len(ackedPackets)-1].PacketNumber { 659 eventSample.lastPacketSendState = lastLostPacketSendState 660 } else { 661 eventSample.lastPacketSendState = lastAckedPacketSendState 662 } 663 } 664 665 isNewMaxBandwidth := eventSample.sampleMaxBandwidth > maxBandwidth 666 maxBandwidth = Max(maxBandwidth, eventSample.sampleMaxBandwidth) 667 if b.limitMaxAckHeightTrackerBySendRate { 668 maxBandwidth = Max(maxBandwidth, maxSendRate) 669 } 670 671 eventSample.extraAcked = b.onAckEventEnd(Min(estBandwidthUpperBound, maxBandwidth), isNewMaxBandwidth, roundTripCount) 672 673 return *eventSample 674 } 675 676 func (b *bandwidthSampler) OnPacketLost(packetNumber congestion.PacketNumber, bytesLost congestion.ByteCount) (s sendTimeState) { 677 b.totalBytesLost += bytesLost 678 if sentPacketPointer := b.connectionStateMap.GetEntry(packetNumber); sentPacketPointer != nil { 679 sentPacketToSendTimeState(sentPacketPointer, &s) 680 } 681 return s 682 } 683 684 func (b *bandwidthSampler) OnPacketNeutered(packetNumber congestion.PacketNumber) { 685 b.connectionStateMap.Remove(packetNumber, func(sentPacket connectionStateOnSentPacket) { 686 b.totalBytesNeutered += sentPacket.size 687 }) 688 } 689 690 func (b *bandwidthSampler) OnAppLimited() { 691 b.isAppLimited = true 692 b.endOfAppLimitedPhase = b.lastSentPacket 693 } 694 695 func (b *bandwidthSampler) RemoveObsoletePackets(leastUnacked congestion.PacketNumber) { 696 // A packet can become obsolete when it is removed from QuicUnackedPacketMap's 697 // view of inflight before it is acked or marked as lost. For example, when 698 // QuicSentPacketManager::RetransmitCryptoPackets retransmits a crypto packet, 699 // the packet is removed from QuicUnackedPacketMap's inflight, but is not 700 // marked as acked or lost in the BandwidthSampler. 701 b.connectionStateMap.RemoveUpTo(leastUnacked) 702 } 703 704 func (b *bandwidthSampler) TotalBytesSent() congestion.ByteCount { 705 return b.totalBytesSent 706 } 707 708 func (b *bandwidthSampler) TotalBytesLost() congestion.ByteCount { 709 return b.totalBytesLost 710 } 711 712 func (b *bandwidthSampler) TotalBytesAcked() congestion.ByteCount { 713 return b.totalBytesAcked 714 } 715 716 func (b *bandwidthSampler) TotalBytesNeutered() congestion.ByteCount { 717 return b.totalBytesNeutered 718 } 719 720 func (b *bandwidthSampler) IsAppLimited() bool { 721 return b.isAppLimited 722 } 723 724 func (b *bandwidthSampler) EndOfAppLimitedPhase() congestion.PacketNumber { 725 return b.endOfAppLimitedPhase 726 } 727 728 func (b *bandwidthSampler) max_ack_height() congestion.ByteCount { 729 return b.maxAckHeightTracker.Get() 730 } 731 732 func (b *bandwidthSampler) chooseA0Point(totalBytesAcked congestion.ByteCount, a0 *ackPoint) bool { 733 if b.a0Candidates.Empty() { 734 return false 735 } 736 737 if b.a0Candidates.Len() == 1 { 738 *a0 = *b.a0Candidates.Front() 739 return true 740 } 741 742 for i := 1; i < b.a0Candidates.Len(); i++ { 743 if b.a0Candidates.Offset(i).totalBytesAcked > totalBytesAcked { 744 *a0 = *b.a0Candidates.Offset(i - 1) 745 if i > 1 { 746 for j := 0; j < i-1; j++ { 747 b.a0Candidates.PopFront() 748 } 749 } 750 return true 751 } 752 } 753 754 *a0 = *b.a0Candidates.Back() 755 for k := 0; k < b.a0Candidates.Len()-1; k++ { 756 b.a0Candidates.PopFront() 757 } 758 return true 759 } 760 761 func (b *bandwidthSampler) onPacketAcknowledged(ackTime time.Time, packetNumber congestion.PacketNumber) bandwidthSample { 762 sample := newBandwidthSample() 763 b.lastAckedPacket = packetNumber 764 sentPacketPointer := b.connectionStateMap.GetEntry(packetNumber) 765 if sentPacketPointer == nil { 766 return *sample 767 } 768 769 // OnPacketAcknowledgedInner 770 b.totalBytesAcked += sentPacketPointer.size 771 b.totalBytesSentAtLastAckedPacket = sentPacketPointer.sendTimeState.totalBytesSent 772 b.lastAckedPacketSentTime = sentPacketPointer.sentTime 773 b.lastAckedPacketAckTime = ackTime 774 if b.overestimateAvoidance { 775 b.recentAckPoints.Update(ackTime, b.totalBytesAcked) 776 } 777 778 if b.isAppLimited { 779 // Exit app-limited phase in two cases: 780 // (1) end_of_app_limited_phase_ is not initialized, i.e., so far all 781 // packets are sent while there are buffered packets or pending data. 782 // (2) The current acked packet is after the sent packet marked as the end 783 // of the app limit phase. 784 if b.endOfAppLimitedPhase == invalidPacketNumber || 785 packetNumber > b.endOfAppLimitedPhase { 786 b.isAppLimited = false 787 } 788 } 789 790 // There might have been no packets acknowledged at the moment when the 791 // current packet was sent. In that case, there is no bandwidth sample to 792 // make. 793 if sentPacketPointer.lastAckedPacketSentTime.IsZero() { 794 return *sample 795 } 796 797 // Infinite rate indicates that the sampler is supposed to discard the 798 // current send rate sample and use only the ack rate. 799 sendRate := infBandwidth 800 if sentPacketPointer.sentTime.After(sentPacketPointer.lastAckedPacketSentTime) { 801 sendRate = BandwidthFromDelta( 802 sentPacketPointer.sendTimeState.totalBytesSent-sentPacketPointer.totalBytesSentAtLastAckedPacket, 803 sentPacketPointer.sentTime.Sub(sentPacketPointer.lastAckedPacketSentTime)) 804 } 805 806 var a0 ackPoint 807 if b.overestimateAvoidance && b.chooseA0Point(sentPacketPointer.sendTimeState.totalBytesAcked, &a0) { 808 } else { 809 a0.ackTime = sentPacketPointer.lastAckedPacketAckTime 810 a0.totalBytesAcked = sentPacketPointer.sendTimeState.totalBytesAcked 811 } 812 813 // During the slope calculation, ensure that ack time of the current packet is 814 // always larger than the time of the previous packet, otherwise division by 815 // zero or integer underflow can occur. 816 if ackTime.Sub(a0.ackTime) <= 0 { 817 return *sample 818 } 819 820 ackRate := BandwidthFromDelta(b.totalBytesAcked-a0.totalBytesAcked, ackTime.Sub(a0.ackTime)) 821 822 sample.bandwidth = Min(sendRate, ackRate) 823 // Note: this sample does not account for delayed acknowledgement time. This 824 // means that the RTT measurements here can be artificially high, especially 825 // on low bandwidth connections. 826 sample.rtt = ackTime.Sub(sentPacketPointer.sentTime) 827 sample.sendRate = sendRate 828 sentPacketToSendTimeState(sentPacketPointer, &sample.stateAtSend) 829 830 return *sample 831 } 832 833 func (b *bandwidthSampler) onAckEventEnd( 834 bandwidthEstimate Bandwidth, 835 isNewMaxBandwidth bool, 836 roundTripCount roundTripCount, 837 ) congestion.ByteCount { 838 newlyAckedBytes := b.totalBytesAcked - b.totalBytesAckedAfterLastAckEvent 839 if newlyAckedBytes == 0 { 840 return 0 841 } 842 b.totalBytesAckedAfterLastAckEvent = b.totalBytesAcked 843 extraAcked := b.maxAckHeightTracker.Update( 844 bandwidthEstimate, 845 isNewMaxBandwidth, 846 roundTripCount, 847 b.lastSentPacket, 848 b.lastAckedPacket, 849 b.lastAckedPacketAckTime, 850 newlyAckedBytes) 851 // If |extra_acked| is zero, i.e. this ack event marks the start of a new ack 852 // aggregation epoch, save LessRecentPoint, which is the last ack point of the 853 // previous epoch, as a A0 candidate. 854 if b.overestimateAvoidance && extraAcked == 0 { 855 b.a0Candidates.PushBack(*b.recentAckPoints.LessRecentPoint()) 856 } 857 return extraAcked 858 } 859 860 func sentPacketToSendTimeState(sentPacket *connectionStateOnSentPacket, sendTimeState *sendTimeState) { 861 *sendTimeState = sentPacket.sendTimeState 862 sendTimeState.isValid = true 863 } 864 865 // BytesFromBandwidthAndTimeDelta calculates the bytes 866 // from a bandwidth(bits per second) and a time delta 867 func bytesFromBandwidthAndTimeDelta(bandwidth Bandwidth, delta time.Duration) congestion.ByteCount { 868 return (congestion.ByteCount(bandwidth) * congestion.ByteCount(delta)) / 869 (congestion.ByteCount(time.Second) * 8) 870 } 871 872 func timeDeltaFromBytesAndBandwidth(bytes congestion.ByteCount, bandwidth Bandwidth) time.Duration { 873 return time.Duration(bytes*8) * time.Second / time.Duration(bandwidth) 874 }