chore: Update BBR config

chore: Adjust workflow
This commit is contained in:
Larvan2 2023-01-16 14:53:19 +08:00
parent bb79272020
commit f3b76df13b
3 changed files with 59 additions and 62 deletions

View File

@ -95,6 +95,7 @@ jobs:
with: with:
ndk-version: r25b ndk-version: r25b
add-to-path: false add-to-path: false
local-cache: true
- name: Build Android - name: Build Android
if: ${{ matrix.job.type=='WithCGO' && matrix.job.target=='android' }} if: ${{ matrix.job.type=='WithCGO' && matrix.job.target=='android' }}

View File

@ -13,16 +13,21 @@ import (
) )
const ( const (
MaxDatagramSize = 1252 // InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes.
DefaultBBRMaxCongestionWindow congestion.ByteCount = 2000 * MaxDatagramSize InitialMaxDatagramSize = 1252
InitialCongestionWindow congestion.ByteCount = 10 * MaxDatagramSize InitialCongestionWindow congestion.ByteCount = 10
MinInitialPacketSize = 1200
InitialPacketSizeIPv4 = 1252 InitialPacketSizeIPv4 = 1252
InitialPacketSizeIPv6 = 1232 InitialPacketSizeIPv6 = 1232
DefaultBBRMaxCongestionWindow congestion.ByteCount = 10000
) )
func GetMaxPacketSize(addr net.Addr) congestion.ByteCount { const (
maxSize := congestion.ByteCount(MinInitialPacketSize) initialMinCongestionWindow = 4
minInitialPacketSize = 1200
)
func GetInitialPacketSize(addr net.Addr) congestion.ByteCount {
maxSize := congestion.ByteCount(minInitialPacketSize)
// If this is not a UDP address, we don't know anything about the MTU. // If this is not a UDP address, we don't know anything about the MTU.
// Use the minimum size of an Initial packet as the max packet size. // Use the minimum size of an Initial packet as the max packet size.
if udpAddr, ok := addr.(*net.UDPAddr); ok { if udpAddr, ok := addr.(*net.UDPAddr); ok {
@ -35,41 +40,11 @@ func GetMaxPacketSize(addr net.Addr) congestion.ByteCount {
return maxSize return maxSize
} }
func GetMaxOutgoingPacketSize(addr net.Addr) congestion.ByteCount {
maxSize := congestion.ByteCount(MinInitialPacketSize)
// If this is not a UDP address, we don't know anything about the MTU.
// Use the minimum size of an Initial packet as the max packet size.
if udpAddr, ok := addr.(*net.UDPAddr); ok {
if udpAddr.IP.To4() != nil {
//The maximum packet size of any QUIC packet over IPv4. 1500(Ethernet) - 20(IPv4 header) - 8(UDP header) = 1472.
maxSize = congestion.ByteCount(1472)
} else {
// The maximum outgoing packet size allowed.
// The maximum packet size of any QUIC packet over IPv6, based on ethernet's max
// size, minus the IP and UDP headers. IPv6 has a 40 byte header, UDP adds an
// additional 8 bytes. This is a total overhead of 48 bytes. Ethernet's
// max packet size is 1500 bytes, 1500 - 48 = 1452.
maxSize = congestion.ByteCount(1452)
}
}
return maxSize
}
var ( var (
// Default maximum packet size used in the Linux TCP implementation.
// Used in QUIC for congestion window computations in bytes.
MaxSegmentSize = MaxDatagramSize
// Default initial rtt used before any samples are received. // Default initial rtt used before any samples are received.
InitialRtt = 100 * time.Millisecond InitialRtt = 100 * time.Millisecond
// 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 * MaxDatagramSize
// The gain used for the STARTUP, equal to 2/ln(2). // The gain used for the STARTUP, equal to 2/ln(2).
DefaultHighGain = 2.89 DefaultHighGain = 2.89
@ -174,9 +149,9 @@ type bbrSender struct {
// The initial value of the |congestion_window_|. // The initial value of the |congestion_window_|.
initialCongestionWindow congestion.ByteCount initialCongestionWindow congestion.ByteCount
// The largest value the |congestion_window_| can achieve. // The largest value the |congestion_window_| can achieve.
maxCongestionWindow congestion.ByteCount initialMaxCongestionWindow congestion.ByteCount
// The smallest value the |congestion_window_| can achieve. // The smallest value the |congestion_window_| can achieve.
minCongestionWindow congestion.ByteCount //minCongestionWindow congestion.ByteCount
// The pacing gain applied during the STARTUP phase. // The pacing gain applied during the STARTUP phase.
highGain float64 highGain float64
// The CWND gain applied during the STARTUP phase. // The CWND gain applied during the STARTUP phase.
@ -269,11 +244,14 @@ type bbrSender struct {
pacer *pacer pacer *pacer
maxDatagramSize congestion.ByteCount maxDatagramSize congestion.ByteCount
MaxOutgoingPacketSize congestion.ByteCount
} }
func NewBBRSender(clock Clock, initialMaxDatagramSize, initialCongestionWindow, initialMaxOutgoingPacketSize, maxCongestionWindow congestion.ByteCount) *bbrSender { func NewBBRSender(
clock Clock,
initialMaxDatagramSize,
initialCongestionWindow,
initialMaxCongestionWindow congestion.ByteCount,
) *bbrSender {
b := &bbrSender{ b := &bbrSender{
mode: STARTUP, mode: STARTUP,
clock: clock, clock: clock,
@ -282,8 +260,6 @@ func NewBBRSender(clock Clock, initialMaxDatagramSize, initialCongestionWindow,
maxAckHeight: NewWindowedFilter(int64(BandwidthWindowSize), MaxFilter), maxAckHeight: NewWindowedFilter(int64(BandwidthWindowSize), MaxFilter),
congestionWindow: initialCongestionWindow, congestionWindow: initialCongestionWindow,
initialCongestionWindow: initialCongestionWindow, initialCongestionWindow: initialCongestionWindow,
maxCongestionWindow: maxCongestionWindow,
minCongestionWindow: congestion.ByteCount(DefaultMinimumCongestionWindow),
highGain: DefaultHighGain, highGain: DefaultHighGain,
highCwndGain: DefaultHighGain, highCwndGain: DefaultHighGain,
drainGain: 1.0 / DefaultHighGain, drainGain: 1.0 / DefaultHighGain,
@ -292,15 +268,22 @@ func NewBBRSender(clock Clock, initialMaxDatagramSize, initialCongestionWindow,
congestionWindowGainConst: DefaultCongestionWindowGainConst, congestionWindowGainConst: DefaultCongestionWindowGainConst,
numStartupRtts: RoundTripsWithoutGrowthBeforeExitingStartup, numStartupRtts: RoundTripsWithoutGrowthBeforeExitingStartup,
recoveryState: NOT_IN_RECOVERY, recoveryState: NOT_IN_RECOVERY,
recoveryWindow: maxCongestionWindow, recoveryWindow: initialMaxCongestionWindow,
minRttSinceLastProbeRtt: InfiniteRTT, minRttSinceLastProbeRtt: InfiniteRTT,
MaxOutgoingPacketSize: initialMaxOutgoingPacketSize,
maxDatagramSize: initialMaxDatagramSize, maxDatagramSize: initialMaxDatagramSize,
} }
b.pacer = newPacer(b.BandwidthEstimate) b.pacer = newPacer(b.BandwidthEstimate)
return b return b
} }
func (b *bbrSender) maxCongestionWindow() congestion.ByteCount {
return b.maxDatagramSize * DefaultBBRMaxCongestionWindow
}
func (b *bbrSender) minCongestionWindow() congestion.ByteCount {
return b.maxDatagramSize * initialMinCongestionWindow
}
func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) { func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) {
b.rttStats = provider b.rttStats = provider
} }
@ -323,10 +306,10 @@ func (b *bbrSender) SetMaxDatagramSize(s congestion.ByteCount) {
if s < b.maxDatagramSize { if s < b.maxDatagramSize {
panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", b.maxDatagramSize, s)) panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", b.maxDatagramSize, s))
} }
cwndIsMinCwnd := b.congestionWindow == b.minCongestionWindow cwndIsMinCwnd := b.congestionWindow == b.minCongestionWindow()
b.maxDatagramSize = s b.maxDatagramSize = s
if cwndIsMinCwnd { if cwndIsMinCwnd {
b.congestionWindow = b.minCongestionWindow b.congestionWindow = b.minCongestionWindow()
} }
b.pacer.SetMaxDatagramSize(s) b.pacer.SetMaxDatagramSize(s)
} }
@ -393,6 +376,7 @@ func (b *bbrSender) OnPacketAcked(number congestion.PacketNumber, ackedBytes con
b.CalculatePacingRate() b.CalculatePacingRate()
b.CalculateCongestionWindow(bytesAcked, excessAcked) b.CalculateCongestionWindow(bytesAcked, excessAcked)
b.CalculateRecoveryWindow(bytesAcked, congestion.ByteCount(0)) b.CalculateRecoveryWindow(bytesAcked, congestion.ByteCount(0))
} }
func (b *bbrSender) OnPacketLost(number congestion.PacketNumber, lostBytes congestion.ByteCount, priorInFlight congestion.ByteCount) { func (b *bbrSender) OnPacketLost(number congestion.PacketNumber, lostBytes congestion.ByteCount, priorInFlight congestion.ByteCount) {
@ -491,8 +475,21 @@ func (b *bbrSender) OnRetransmissionTimeout(packetsRetransmitted bool) {
// //
//} //}
//func (b *bbrSender) BandwidthEstimate() Bandwidth {
// return Bandwidth(b.maxBandwidth.GetBest())
//}
// BandwidthEstimate returns the current bandwidth estimate
func (b *bbrSender) BandwidthEstimate() Bandwidth { func (b *bbrSender) BandwidthEstimate() Bandwidth {
return Bandwidth(b.maxBandwidth.GetBest()) if b.rttStats == nil {
return infBandwidth
}
srtt := b.rttStats.SmoothedRTT()
if srtt == 0 {
// If we haven't measured an rtt, the bandwidth estimate is unknown.
return infBandwidth
}
return BandwidthFromDelta(b.GetCongestionWindow(), srtt)
} }
//func (b *bbrSender) HybridSlowStart() *HybridSlowStart { //func (b *bbrSender) HybridSlowStart() *HybridSlowStart {
@ -740,7 +737,7 @@ func (b *bbrSender) GetTargetCongestionWindow(gain float64) congestion.ByteCount
congestionWindow = congestion.ByteCount(gain * float64(b.initialCongestionWindow)) congestionWindow = congestion.ByteCount(gain * float64(b.initialCongestionWindow))
} }
return maxByteCount(congestionWindow, b.minCongestionWindow) return maxByteCount(congestionWindow, b.minCongestionWindow())
} }
func (b *bbrSender) CheckIfFullBandwidthReached() { func (b *bbrSender) CheckIfFullBandwidthReached() {
@ -811,7 +808,7 @@ func (b *bbrSender) MaybeEnterOrExitProbeRtt(now time.Time, isRoundStart, minRtt
// PROBE_RTT. The CWND during PROBE_RTT is kMinimumCongestionWindow, but // PROBE_RTT. The CWND during PROBE_RTT is kMinimumCongestionWindow, but
// we allow an extra packet since QUIC checks CWND before sending a // we allow an extra packet since QUIC checks CWND before sending a
// packet. // packet.
if b.GetBytesInFlight() < b.ProbeRttCongestionWindow()+b.MaxOutgoingPacketSize { if b.GetBytesInFlight() < b.ProbeRttCongestionWindow()+b.maxDatagramSize {
b.exitProbeRttAt = now.Add(ProbeRttTime) b.exitProbeRttAt = now.Add(ProbeRttTime)
b.probeRttRoundPassed = false b.probeRttRoundPassed = false
} }
@ -836,7 +833,7 @@ func (b *bbrSender) ProbeRttCongestionWindow() congestion.ByteCount {
if b.probeRttBasedOnBdp { if b.probeRttBasedOnBdp {
return b.GetTargetCongestionWindow(ModerateProbeRttMultiplier) return b.GetTargetCongestionWindow(ModerateProbeRttMultiplier)
} else { } else {
return b.minCongestionWindow return b.minCongestionWindow()
} }
} }
@ -921,8 +918,8 @@ func (b *bbrSender) CalculateCongestionWindow(ackedBytes, excessAcked congestion
} }
// Enforce the limits on the congestion window. // Enforce the limits on the congestion window.
b.congestionWindow = maxByteCount(b.congestionWindow, b.minCongestionWindow) b.congestionWindow = maxByteCount(b.congestionWindow, b.minCongestionWindow())
b.congestionWindow = minByteCount(b.congestionWindow, b.maxCongestionWindow) b.congestionWindow = minByteCount(b.congestionWindow, b.maxCongestionWindow())
} }
func (b *bbrSender) CalculateRecoveryWindow(ackedBytes, lostBytes congestion.ByteCount) { func (b *bbrSender) CalculateRecoveryWindow(ackedBytes, lostBytes congestion.ByteCount) {
@ -936,7 +933,7 @@ func (b *bbrSender) CalculateRecoveryWindow(ackedBytes, lostBytes congestion.Byt
// Set up the initial recovery window. // Set up the initial recovery window.
if b.recoveryWindow == 0 { if b.recoveryWindow == 0 {
b.recoveryWindow = maxByteCount(b.GetBytesInFlight()+ackedBytes, b.minCongestionWindow) b.recoveryWindow = maxByteCount(b.GetBytesInFlight()+ackedBytes, b.minCongestionWindow())
return return
} }
@ -945,7 +942,7 @@ func (b *bbrSender) CalculateRecoveryWindow(ackedBytes, lostBytes congestion.Byt
if b.recoveryWindow >= lostBytes { if b.recoveryWindow >= lostBytes {
b.recoveryWindow -= lostBytes b.recoveryWindow -= lostBytes
} else { } else {
b.recoveryWindow = congestion.ByteCount(MaxSegmentSize) b.recoveryWindow = congestion.ByteCount(b.maxDatagramSize)
} }
// In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH, // In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH,
// release additional |bytes_acked| to achieve a slow-start-like behavior. // release additional |bytes_acked| to achieve a slow-start-like behavior.
@ -955,7 +952,7 @@ func (b *bbrSender) CalculateRecoveryWindow(ackedBytes, lostBytes congestion.Byt
// Sanity checks. Ensure that we always allow to send at least an MSS or // Sanity checks. Ensure that we always allow to send at least an MSS or
// |bytes_acked| in response, whichever is larger. // |bytes_acked| in response, whichever is larger.
b.recoveryWindow = maxByteCount(b.recoveryWindow, b.GetBytesInFlight()+ackedBytes) b.recoveryWindow = maxByteCount(b.recoveryWindow, b.GetBytesInFlight()+ackedBytes)
b.recoveryWindow = maxByteCount(b.recoveryWindow, b.minCongestionWindow) b.recoveryWindow = maxByteCount(b.recoveryWindow, b.minCongestionWindow())
} }
var _ congestion.CongestionControl = &bbrSender{} var _ congestion.CongestionControl = &bbrSender{}

View File

@ -26,7 +26,7 @@ func SetCongestionController(quicConn quic.Connection, cc string) {
quicConn.SetCongestionControl( quicConn.SetCongestionControl(
congestion.NewCubicSender( congestion.NewCubicSender(
congestion.DefaultClock{}, congestion.DefaultClock{},
congestion.GetMaxPacketSize(quicConn.RemoteAddr()), congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
false, false,
nil, nil,
), ),
@ -35,7 +35,7 @@ func SetCongestionController(quicConn quic.Connection, cc string) {
quicConn.SetCongestionControl( quicConn.SetCongestionControl(
congestion.NewCubicSender( congestion.NewCubicSender(
congestion.DefaultClock{}, congestion.DefaultClock{},
congestion.GetMaxPacketSize(quicConn.RemoteAddr()), congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
true, true,
nil, nil,
), ),
@ -44,10 +44,9 @@ func SetCongestionController(quicConn quic.Connection, cc string) {
quicConn.SetCongestionControl( quicConn.SetCongestionControl(
congestion.NewBBRSender( congestion.NewBBRSender(
congestion.DefaultClock{}, congestion.DefaultClock{},
congestion.GetMaxPacketSize(quicConn.RemoteAddr()), congestion.GetInitialPacketSize(quicConn.RemoteAddr()),
congestion.GetMaxOutgoingPacketSize(quicConn.RemoteAddr()), congestion.InitialCongestionWindow*congestion.InitialMaxDatagramSize,
congestion.InitialCongestionWindow, congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize,
congestion.DefaultBBRMaxCongestionWindow,
), ),
) )
} }