mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-04-22 16:17:16 +08:00
fix: BBR scale window for datagram size
https://github.com/apernet/hysteria/commit/61c75a260f935a6c5adf2f3ce0441f117c65fcbb
This commit is contained in:
@@ -27,16 +27,13 @@ const (
|
||||
|
||||
invalidPacketNumber = -1
|
||||
initialCongestionWindowPackets = 32
|
||||
minCongestionWindowPackets = 4
|
||||
|
||||
// Constants based on TCP defaults.
|
||||
// The minimum CWND to ensure delayed acks don't reduce bandwidth measurements.
|
||||
// Does not inflate the pacing rate.
|
||||
defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize)
|
||||
|
||||
// The gain used for the STARTUP, equal to 2/ln(2).
|
||||
defaultHighGain = 2.885
|
||||
// The newly derived gain for STARTUP, equal to 4 * ln(2)
|
||||
derivedHighGain = 2.773
|
||||
// The newly derived CWND gain for STARTUP, 2.
|
||||
derivedHighCWNDGain = 2.0
|
||||
)
|
||||
@@ -63,7 +60,6 @@ const (
|
||||
// Flag.
|
||||
defaultStartupFullLossCount = 8
|
||||
quicBbr2DefaultLossThreshold = 0.02
|
||||
maxBbrBurstPackets = 10
|
||||
)
|
||||
|
||||
type bbrMode int
|
||||
@@ -267,7 +263,7 @@ func newBbrSender(
|
||||
congestionWindow: initialCongestionWindow,
|
||||
initialCongestionWindow: initialCongestionWindow,
|
||||
maxCongestionWindow: initialMaxCongestionWindow,
|
||||
minCongestionWindow: defaultMinimumCongestionWindow,
|
||||
minCongestionWindow: minCongestionWindowForMaxDatagramSize(initialMaxDatagramSize),
|
||||
highGain: defaultHighGain,
|
||||
highCwndGain: defaultHighGain,
|
||||
drainGain: 1.0 / defaultHighGain,
|
||||
@@ -285,19 +281,37 @@ func newBbrSender(
|
||||
}
|
||||
b.pacer = NewPacer(b.bandwidthForPacer)
|
||||
|
||||
/*
|
||||
if b.tracer != nil {
|
||||
b.lastState = logging.CongestionStateStartup
|
||||
b.tracer.UpdatedCongestionState(logging.CongestionStateStartup)
|
||||
}
|
||||
*/
|
||||
|
||||
b.enterStartupMode()
|
||||
b.setHighCwndGain(derivedHighCWNDGain)
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func minCongestionWindowForMaxDatagramSize(maxDatagramSize congestion.ByteCount) congestion.ByteCount {
|
||||
return minCongestionWindowPackets * maxDatagramSize
|
||||
}
|
||||
|
||||
func scaleByteWindowForDatagramSize(window, oldMaxDatagramSize, newMaxDatagramSize congestion.ByteCount) congestion.ByteCount {
|
||||
if oldMaxDatagramSize == newMaxDatagramSize {
|
||||
return window
|
||||
}
|
||||
return congestion.ByteCount(uint64(window) * uint64(newMaxDatagramSize) / uint64(oldMaxDatagramSize))
|
||||
}
|
||||
|
||||
func (b *bbrSender) rescalePacketSizedWindows(maxDatagramSize congestion.ByteCount) {
|
||||
oldMaxDatagramSize := b.maxDatagramSize
|
||||
b.maxDatagramSize = maxDatagramSize
|
||||
b.initialCongestionWindow = scaleByteWindowForDatagramSize(b.initialCongestionWindow, oldMaxDatagramSize, maxDatagramSize)
|
||||
b.maxCongestionWindow = scaleByteWindowForDatagramSize(b.maxCongestionWindow, oldMaxDatagramSize, maxDatagramSize)
|
||||
b.minCongestionWindow = minCongestionWindowForMaxDatagramSize(maxDatagramSize)
|
||||
b.cwndToCalculateMinPacingRate = scaleByteWindowForDatagramSize(b.cwndToCalculateMinPacingRate, oldMaxDatagramSize, maxDatagramSize)
|
||||
b.maxCongestionWindowWithNetworkParametersAdjusted = scaleByteWindowForDatagramSize(
|
||||
b.maxCongestionWindowWithNetworkParametersAdjusted,
|
||||
oldMaxDatagramSize,
|
||||
maxDatagramSize,
|
||||
)
|
||||
}
|
||||
|
||||
func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) {
|
||||
b.rttStats = provider
|
||||
}
|
||||
@@ -330,8 +344,6 @@ func (b *bbrSender) OnPacketSent(
|
||||
}
|
||||
|
||||
b.sampler.OnPacketSent(sentTime, packetNumber, bytes, bytesInFlight, isRetransmittable)
|
||||
|
||||
b.maybeAppLimited(bytesInFlight)
|
||||
}
|
||||
|
||||
// CanSend implements the SendAlgorithm interface.
|
||||
@@ -364,11 +376,18 @@ func (b *bbrSender) SetMaxDatagramSize(s congestion.ByteCount) {
|
||||
if s < b.maxDatagramSize {
|
||||
panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", b.maxDatagramSize, s))
|
||||
}
|
||||
cwndIsMinCwnd := b.congestionWindow == b.minCongestionWindow
|
||||
b.maxDatagramSize = s
|
||||
if cwndIsMinCwnd {
|
||||
oldMinCongestionWindow := b.minCongestionWindow
|
||||
oldInitialCongestionWindow := b.initialCongestionWindow
|
||||
b.rescalePacketSizedWindows(s)
|
||||
switch b.congestionWindow {
|
||||
case oldMinCongestionWindow:
|
||||
b.congestionWindow = b.minCongestionWindow
|
||||
case oldInitialCongestionWindow:
|
||||
b.congestionWindow = b.initialCongestionWindow
|
||||
default:
|
||||
b.congestionWindow = Min(b.maxCongestionWindow, Max(b.congestionWindow, b.minCongestionWindow))
|
||||
}
|
||||
b.recoveryWindow = Min(b.maxCongestionWindow, Max(b.recoveryWindow, b.minCongestionWindow))
|
||||
b.pacer.SetMaxDatagramSize(s)
|
||||
}
|
||||
|
||||
@@ -411,6 +430,8 @@ func (b *bbrSender) OnCongestionEventEx(priorInFlight congestion.ByteCount, even
|
||||
// packet in lost_packets.
|
||||
var lastPacketSendState sendTimeState
|
||||
|
||||
b.maybeAppLimited(priorInFlight)
|
||||
|
||||
// Update bytesInFlight
|
||||
b.bytesInFlight = priorInFlight
|
||||
for _, p := range ackedPackets {
|
||||
@@ -508,22 +529,6 @@ func (b *bbrSender) PacingRate() Bandwidth {
|
||||
return b.pacingRate
|
||||
}
|
||||
|
||||
func (b *bbrSender) hasGoodBandwidthEstimateForResumption() bool {
|
||||
return b.hasNonAppLimitedSample()
|
||||
}
|
||||
|
||||
func (b *bbrSender) hasNonAppLimitedSample() bool {
|
||||
return b.hasNoAppLimitedSample
|
||||
}
|
||||
|
||||
// Sets the pacing gain used in STARTUP. Must be greater than 1.
|
||||
func (b *bbrSender) setHighGain(highGain float64) {
|
||||
b.highGain = highGain
|
||||
if b.mode == bbrModeStartup {
|
||||
b.pacingGain = highGain
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the CWND gain used in STARTUP. Must be greater than 1.
|
||||
func (b *bbrSender) setHighCwndGain(highCwndGain float64) {
|
||||
b.highCwndGain = highCwndGain
|
||||
@@ -532,11 +537,6 @@ func (b *bbrSender) setHighCwndGain(highCwndGain float64) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the gain used in DRAIN. Must be less than 1.
|
||||
func (b *bbrSender) setDrainGain(drainGain float64) {
|
||||
b.drainGain = drainGain
|
||||
}
|
||||
|
||||
// Get the current bandwidth estimate. Note that Bandwidth is in bits per second.
|
||||
func (b *bbrSender) bandwidthEstimate() Bandwidth {
|
||||
return b.maxBandwidth.GetBest()
|
||||
@@ -697,12 +697,7 @@ func (b *bbrSender) checkIfFullBandwidthReached(lastPacketSendState *sendTimeSta
|
||||
}
|
||||
|
||||
func (b *bbrSender) maybeAppLimited(bytesInFlight congestion.ByteCount) {
|
||||
congestionWindow := b.GetCongestionWindow()
|
||||
if bytesInFlight >= congestionWindow {
|
||||
return
|
||||
}
|
||||
availableBytes := congestionWindow - bytesInFlight
|
||||
if availableBytes > maxBbrBurstPackets*b.maxDatagramSize {
|
||||
if bytesInFlight < b.getTargetCongestionWindow(1) {
|
||||
b.sampler.OnAppLimited()
|
||||
}
|
||||
}
|
||||
@@ -729,7 +724,7 @@ func (b *bbrSender) maybeEnterOrExitProbeRtt(now monotime.Time, isRoundStart, mi
|
||||
b.pacingGain = 1.0
|
||||
// Do not decide on the time to exit PROBE_RTT until the |bytes_in_flight|
|
||||
// is at the target small value.
|
||||
b.exitProbeRttAt = monotime.Time(0)
|
||||
b.exitProbeRttAt = 0
|
||||
}
|
||||
|
||||
if b.mode == bbrModeProbeRtt {
|
||||
|
||||
Reference in New Issue
Block a user