Merge pull request #3107 from lucas-clemente/fix-cubic-initialization

initialize the congestion controller with the actual max datagram size
This commit is contained in:
Marten Seemann 2021-04-02 17:35:13 +07:00 committed by GitHub
commit f60306c4bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 50 additions and 13 deletions

View file

@ -9,12 +9,13 @@ import (
// NewAckHandler creates a new SentPacketHandler and a new ReceivedPacketHandler // NewAckHandler creates a new SentPacketHandler and a new ReceivedPacketHandler
func NewAckHandler( func NewAckHandler(
initialPacketNumber protocol.PacketNumber, initialPacketNumber protocol.PacketNumber,
initialMaxDatagramSize protocol.ByteCount,
rttStats *utils.RTTStats, rttStats *utils.RTTStats,
pers protocol.Perspective, pers protocol.Perspective,
tracer logging.ConnectionTracer, tracer logging.ConnectionTracer,
logger utils.Logger, logger utils.Logger,
version protocol.VersionNumber, version protocol.VersionNumber,
) (SentPacketHandler, ReceivedPacketHandler) { ) (SentPacketHandler, ReceivedPacketHandler) {
sph := newSentPacketHandler(initialPacketNumber, rttStats, pers, tracer, logger) sph := newSentPacketHandler(initialPacketNumber, initialMaxDatagramSize, rttStats, pers, tracer, logger)
return sph, newReceivedPacketHandler(sph, rttStats, logger, version) return sph, newReceivedPacketHandler(sph, rttStats, logger, version)
} }

View file

@ -101,6 +101,7 @@ var (
func newSentPacketHandler( func newSentPacketHandler(
initialPN protocol.PacketNumber, initialPN protocol.PacketNumber,
initialMaxDatagramSize protocol.ByteCount,
rttStats *utils.RTTStats, rttStats *utils.RTTStats,
pers protocol.Perspective, pers protocol.Perspective,
tracer logging.ConnectionTracer, tracer logging.ConnectionTracer,
@ -109,6 +110,7 @@ func newSentPacketHandler(
congestion := congestion.NewCubicSender( congestion := congestion.NewCubicSender(
congestion.DefaultClock{}, congestion.DefaultClock{},
rttStats, rttStats,
initialMaxDatagramSize,
true, // use Reno true, // use Reno
tracer, tracer,
) )

View file

@ -27,7 +27,7 @@ var _ = Describe("SentPacketHandler", func() {
JustBeforeEach(func() { JustBeforeEach(func() {
lostPackets = nil lostPackets = nil
rttStats := utils.NewRTTStats() rttStats := utils.NewRTTStats()
handler = newSentPacketHandler(42, rttStats, perspective, nil, utils.DefaultLogger) handler = newSentPacketHandler(42, protocol.InitialPacketSizeIPv4, rttStats, perspective, nil, utils.DefaultLogger)
streamFrame = wire.StreamFrame{ streamFrame = wire.StreamFrame{
StreamID: 5, StreamID: 5,
Data: []byte{0x13, 0x37}, Data: []byte{0x13, 0x37},

View file

@ -1,6 +1,7 @@
package congestion package congestion
import ( import (
"fmt"
"time" "time"
"github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/protocol"
@ -14,9 +15,8 @@ const (
initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4) initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4)
maxBurstPackets = 3 maxBurstPackets = 3
renoBeta = 0.7 // Reno backoff factor. renoBeta = 0.7 // Reno backoff factor.
initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
minCongestionWindowPackets = 2 minCongestionWindowPackets = 2
initialCongestionWindow = 32 * initialMaxDatagramSize initialCongestionWindow = 32
) )
type cubicSender struct { type cubicSender struct {
@ -65,11 +65,33 @@ var (
) )
// NewCubicSender makes a new cubic sender // NewCubicSender makes a new cubic sender
func NewCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, tracer logging.ConnectionTracer) *cubicSender { func NewCubicSender(
return newCubicSender(clock, rttStats, reno, initialCongestionWindow, initialMaxCongestionWindow, tracer) clock Clock,
rttStats *utils.RTTStats,
initialMaxDatagramSize protocol.ByteCount,
reno bool,
tracer logging.ConnectionTracer,
) *cubicSender {
return newCubicSender(
clock,
rttStats,
reno,
initialMaxDatagramSize,
initialCongestionWindow*initialMaxDatagramSize,
protocol.MaxCongestionWindowPackets*initialMaxDatagramSize,
tracer,
)
} }
func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCongestionWindow, initialMaxCongestionWindow protocol.ByteCount, tracer logging.ConnectionTracer) *cubicSender { func newCubicSender(
clock Clock,
rttStats *utils.RTTStats,
reno bool,
initialMaxDatagramSize,
initialCongestionWindow,
initialMaxCongestionWindow protocol.ByteCount,
tracer logging.ConnectionTracer,
) *cubicSender {
c := &cubicSender{ c := &cubicSender{
rttStats: rttStats, rttStats: rttStats,
largestSentPacketNumber: protocol.InvalidPacketNumber, largestSentPacketNumber: protocol.InvalidPacketNumber,
@ -283,7 +305,7 @@ func (c *cubicSender) maybeTraceStateChange(new logging.CongestionState) {
func (c *cubicSender) SetMaxDatagramSize(s protocol.ByteCount) { func (c *cubicSender) SetMaxDatagramSize(s protocol.ByteCount) {
if s < c.maxDatagramSize { if s < c.maxDatagramSize {
panic("congestion BUG: decreased max datagram size") panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", c.maxDatagramSize, s))
} }
cwndIsMinCwnd := c.congestionWindow == c.minCongestionWindow() cwndIsMinCwnd := c.congestionWindow == c.minCongestionWindow()
c.maxDatagramSize = s c.maxDatagramSize = s

View file

@ -42,7 +42,15 @@ var _ = Describe("Cubic Sender", func() {
ackedPacketNumber = 0 ackedPacketNumber = 0
clock = mockClock{} clock = mockClock{}
rttStats = utils.NewRTTStats() rttStats = utils.NewRTTStats()
sender = newCubicSender(&clock, rttStats, true /*reno*/, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil) sender = newCubicSender(
&clock,
rttStats,
true, /*reno*/
protocol.InitialPacketSizeIPv4,
initialCongestionWindowPackets*maxDatagramSize,
MaxCongestionWindow,
nil,
)
}) })
SendAvailableSendWindowLen := func(packetLength protocol.ByteCount) int { SendAvailableSendWindowLen := func(packetLength protocol.ByteCount) int {
@ -310,7 +318,7 @@ var _ = Describe("Cubic Sender", func() {
It("tcp cubic reset epoch on quiescence", func() { It("tcp cubic reset epoch on quiescence", func() {
const maxCongestionWindow = 50 const maxCongestionWindow = 50
const maxCongestionWindowBytes = maxCongestionWindow * maxDatagramSize const maxCongestionWindowBytes = maxCongestionWindow * maxDatagramSize
sender = newCubicSender(&clock, rttStats, false, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindowBytes, nil) sender = newCubicSender(&clock, rttStats, false, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindowBytes, nil)
numSent := SendAvailableSendWindow() numSent := SendAvailableSendWindow()
@ -450,7 +458,8 @@ var _ = Describe("Cubic Sender", func() {
}) })
It("slow starts up to the maximum congestion window", func() { It("slow starts up to the maximum congestion window", func() {
sender = newCubicSender(&clock, rttStats, true, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil) const initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
sender = newCubicSender(&clock, rttStats, true, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil)
for i := 1; i < protocol.MaxCongestionWindowPackets; i++ { for i := 1; i < protocol.MaxCongestionWindowPackets; i++ {
sender.MaybeExitSlowStart() sender.MaybeExitSlowStart()
@ -464,7 +473,8 @@ var _ = Describe("Cubic Sender", func() {
}) })
It("slow starts up to maximum congestion window, if larger packets are sent", func() { It("slow starts up to maximum congestion window, if larger packets are sent", func() {
sender = newCubicSender(&clock, rttStats, true, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil) const initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
sender = newCubicSender(&clock, rttStats, true, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil)
const packetSize = initialMaxDatagramSize + 100 const packetSize = initialMaxDatagramSize + 100
sender.SetMaxDatagramSize(packetSize) sender.SetMaxDatagramSize(packetSize)
for i := 1; i < protocol.MaxCongestionWindowPackets; i++ { for i := 1; i < protocol.MaxCongestionWindowPackets; i++ {
@ -479,7 +489,7 @@ var _ = Describe("Cubic Sender", func() {
It("limit cwnd increase in congestion avoidance", func() { It("limit cwnd increase in congestion avoidance", func() {
// Enable Cubic. // Enable Cubic.
sender = newCubicSender(&clock, rttStats, false, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil) sender = newCubicSender(&clock, rttStats, false, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil)
numSent := SendAvailableSendWindow() numSent := SendAvailableSendWindow()
// Make sure we fall out of slow start. // Make sure we fall out of slow start.

View file

@ -293,6 +293,7 @@ var newSession = func(
s.preSetup() s.preSetup()
s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler( s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler(
0, 0,
getMaxPacketSize(s.conn.RemoteAddr()),
s.rttStats, s.rttStats,
s.perspective, s.perspective,
s.tracer, s.tracer,
@ -417,6 +418,7 @@ var newClientSession = func(
s.preSetup() s.preSetup()
s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler( s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler(
initialPacketNumber, initialPacketNumber,
getMaxPacketSize(s.conn.RemoteAddr()),
s.rttStats, s.rttStats,
s.perspective, s.perspective,
s.tracer, s.tracer,