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  }