forked from quic-go/quic-go
trace congestion state changes
This commit is contained in:
@@ -103,6 +103,7 @@ func newSentPacketHandler(
|
||||
congestion.DefaultClock{},
|
||||
rttStats,
|
||||
true, // use Reno
|
||||
tracer,
|
||||
)
|
||||
|
||||
return &sentPacketHandler{
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/logging"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -57,17 +58,20 @@ type cubicSender struct {
|
||||
|
||||
initialCongestionWindow protocol.ByteCount
|
||||
initialMaxCongestionWindow protocol.ByteCount
|
||||
|
||||
lastState logging.CongestionState
|
||||
tracer logging.ConnectionTracer
|
||||
}
|
||||
|
||||
var _ SendAlgorithm = &cubicSender{}
|
||||
var _ SendAlgorithmWithDebugInfos = &cubicSender{}
|
||||
|
||||
// NewCubicSender makes a new cubic sender
|
||||
func NewCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool) *cubicSender {
|
||||
return newCubicSender(clock, rttStats, reno, initialCongestionWindow, maxCongestionWindow)
|
||||
func NewCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, tracer logging.ConnectionTracer) *cubicSender {
|
||||
return newCubicSender(clock, rttStats, reno, initialCongestionWindow, maxCongestionWindow, tracer)
|
||||
}
|
||||
|
||||
func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCongestionWindow, initialMaxCongestionWindow protocol.ByteCount) *cubicSender {
|
||||
func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCongestionWindow, initialMaxCongestionWindow protocol.ByteCount, tracer logging.ConnectionTracer) *cubicSender {
|
||||
c := &cubicSender{
|
||||
rttStats: rttStats,
|
||||
largestSentPacketNumber: protocol.InvalidPacketNumber,
|
||||
@@ -82,8 +86,13 @@ func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCon
|
||||
cubic: NewCubic(clock),
|
||||
clock: clock,
|
||||
reno: reno,
|
||||
tracer: tracer,
|
||||
}
|
||||
c.pacer = newPacer(c.BandwidthEstimate)
|
||||
if c.tracer != nil {
|
||||
c.lastState = logging.CongestionStateSlowStart
|
||||
c.tracer.UpdatedCongestionState(logging.CongestionStateSlowStart)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -131,6 +140,7 @@ func (c *cubicSender) MaybeExitSlowStart() {
|
||||
if c.InSlowStart() && c.hybridSlowStart.ShouldExitSlowStart(c.rttStats.LatestRTT(), c.rttStats.MinRTT(), c.GetCongestionWindow()/maxDatagramSize) {
|
||||
// exit slow start
|
||||
c.slowStartThreshold = c.congestionWindow
|
||||
c.maybeTraceStateChange(logging.CongestionStateCongestionAvoidance)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +171,7 @@ func (c *cubicSender) OnPacketLost(
|
||||
return
|
||||
}
|
||||
c.lastCutbackExitedSlowstart = c.InSlowStart()
|
||||
c.maybeTraceStateChange(logging.CongestionStateRecovery)
|
||||
|
||||
if c.reno {
|
||||
c.congestionWindow = protocol.ByteCount(float64(c.congestionWindow) * renoBeta)
|
||||
@@ -189,6 +200,7 @@ func (c *cubicSender) maybeIncreaseCwnd(
|
||||
// the current window.
|
||||
if !c.isCwndLimited(priorInFlight) {
|
||||
c.cubic.OnApplicationLimited()
|
||||
c.maybeTraceStateChange(logging.CongestionStateApplicationLimited)
|
||||
return
|
||||
}
|
||||
if c.congestionWindow >= c.maxCongestionWindow {
|
||||
@@ -197,9 +209,11 @@ func (c *cubicSender) maybeIncreaseCwnd(
|
||||
if c.InSlowStart() {
|
||||
// TCP slow start, exponential growth, increase by one for each ACK.
|
||||
c.congestionWindow += maxDatagramSize
|
||||
c.maybeTraceStateChange(logging.CongestionStateSlowStart)
|
||||
return
|
||||
}
|
||||
// Congestion avoidance
|
||||
c.maybeTraceStateChange(logging.CongestionStateCongestionAvoidance)
|
||||
if c.reno {
|
||||
// Classic Reno congestion avoidance.
|
||||
c.numAckedPackets++
|
||||
@@ -257,3 +271,10 @@ func (c *cubicSender) OnConnectionMigration() {
|
||||
c.slowStartThreshold = c.initialMaxCongestionWindow
|
||||
c.maxCongestionWindow = c.initialMaxCongestionWindow
|
||||
}
|
||||
|
||||
func (c *cubicSender) maybeTraceStateChange(new logging.CongestionState) {
|
||||
if c.tracer == nil || new == c.lastState {
|
||||
return
|
||||
}
|
||||
c.tracer.UpdatedCongestionState(new)
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ var _ = Describe("Cubic Sender", func() {
|
||||
ackedPacketNumber = 0
|
||||
clock = mockClock{}
|
||||
rttStats = utils.NewRTTStats()
|
||||
sender = newCubicSender(&clock, rttStats, true /*reno*/, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow)
|
||||
sender = newCubicSender(&clock, rttStats, true /*reno*/, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil)
|
||||
})
|
||||
|
||||
SendAvailableSendWindowLen := func(packetLength protocol.ByteCount) int {
|
||||
@@ -308,7 +308,7 @@ var _ = Describe("Cubic Sender", func() {
|
||||
It("tcp cubic reset epoch on quiescence", func() {
|
||||
const maxCongestionWindow = 50
|
||||
const maxCongestionWindowBytes = maxCongestionWindow * maxDatagramSize
|
||||
sender = newCubicSender(&clock, rttStats, false, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindowBytes)
|
||||
sender = newCubicSender(&clock, rttStats, false, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindowBytes, nil)
|
||||
|
||||
numSent := SendAvailableSendWindow()
|
||||
|
||||
@@ -448,7 +448,7 @@ var _ = Describe("Cubic Sender", func() {
|
||||
})
|
||||
|
||||
It("default max cwnd", func() {
|
||||
sender = newCubicSender(&clock, rttStats, true /*reno*/, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindow)
|
||||
sender = newCubicSender(&clock, rttStats, true /*reno*/, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindow, nil)
|
||||
|
||||
defaultMaxCongestionWindowPackets := maxCongestionWindow / maxDatagramSize
|
||||
for i := 1; i < int(defaultMaxCongestionWindowPackets); i++ {
|
||||
@@ -460,7 +460,7 @@ var _ = Describe("Cubic Sender", func() {
|
||||
|
||||
It("limit cwnd increase in congestion avoidance", func() {
|
||||
// Enable Cubic.
|
||||
sender = newCubicSender(&clock, rttStats, false, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow)
|
||||
sender = newCubicSender(&clock, rttStats, false, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil)
|
||||
numSent := SendAvailableSendWindow()
|
||||
|
||||
// Make sure we fall out of slow start.
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"time"
|
||||
net "net"
|
||||
reflect "reflect"
|
||||
time "time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
"github.com/lucas-clemente/quic-go/logging"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
protocol "github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
utils "github.com/lucas-clemente/quic-go/internal/utils"
|
||||
wire "github.com/lucas-clemente/quic-go/internal/wire"
|
||||
logging "github.com/lucas-clemente/quic-go/logging"
|
||||
)
|
||||
|
||||
// MockConnectionTracer is a mock of ConnectionTracer interface
|
||||
@@ -232,6 +231,18 @@ func (mr *MockConnectionTracerMockRecorder) StartedConnection(arg0, arg1, arg2,
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartedConnection", reflect.TypeOf((*MockConnectionTracer)(nil).StartedConnection), arg0, arg1, arg2, arg3, arg4)
|
||||
}
|
||||
|
||||
// UpdatedCongestionState mocks base method
|
||||
func (m *MockConnectionTracer) UpdatedCongestionState(arg0 logging.CongestionState) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "UpdatedCongestionState", arg0)
|
||||
}
|
||||
|
||||
// UpdatedCongestionState indicates an expected call of UpdatedCongestionState
|
||||
func (mr *MockConnectionTracerMockRecorder) UpdatedCongestionState(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatedCongestionState", reflect.TypeOf((*MockConnectionTracer)(nil).UpdatedCongestionState), arg0)
|
||||
}
|
||||
|
||||
// UpdatedKey mocks base method
|
||||
func (m *MockConnectionTracer) UpdatedKey(arg0 protocol.KeyPhase, arg1 bool) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
Reference in New Issue
Block a user