Make max flow control windows configurable

This commit is contained in:
Thomas De Keulenaer
2017-06-13 15:52:51 +02:00
parent 93e2f751b5
commit 89f96d1e89
9 changed files with 108 additions and 33 deletions

View File

@@ -9,9 +9,9 @@ import (
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/internal/utils"
)
type client struct {
@@ -124,10 +124,14 @@ func populateClientConfig(config *Config) *Config {
}
return &Config{
TLSConfig: config.TLSConfig,
Versions: versions,
HandshakeTimeout: handshakeTimeout,
RequestConnectionIDTruncation: config.RequestConnectionIDTruncation,
TLSConfig: config.TLSConfig,
Versions: versions,
HandshakeTimeout: handshakeTimeout,
RequestConnectionIDTruncation: config.RequestConnectionIDTruncation,
MaxReceiveStreamFlowControlWindowServer: config.MaxReceiveStreamFlowControlWindowServer,
MaxReceiveConnectionFlowControlWindowServer: config.MaxReceiveConnectionFlowControlWindowServer,
MaxReceiveStreamFlowControlWindowClient: config.MaxReceiveStreamFlowControlWindowClient,
MaxReceiveConnectionFlowControlWindowClient: config.MaxReceiveConnectionFlowControlWindowClient,
}
}

View File

@@ -5,9 +5,9 @@ import (
"sync"
"time"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/internal/utils"
)
// ConnectionParametersManager negotiates and stores the connection parameters
@@ -50,6 +50,11 @@ type connectionParametersManager struct {
sendConnectionFlowControlWindow protocol.ByteCount
receiveStreamFlowControlWindow protocol.ByteCount
receiveConnectionFlowControlWindow protocol.ByteCount
maxReceiveStreamFlowControlWindowServer protocol.ByteCount
maxReceiveConnectionFlowControlWindowServer protocol.ByteCount
maxReceiveStreamFlowControlWindowClient protocol.ByteCount
maxReceiveConnectionFlowControlWindowClient protocol.ByteCount
}
var _ ConnectionParametersManager = &connectionParametersManager{}
@@ -61,7 +66,24 @@ var (
)
// NewConnectionParamatersManager creates a new connection parameters manager
func NewConnectionParamatersManager(pers protocol.Perspective, v protocol.VersionNumber) ConnectionParametersManager {
func NewConnectionParamatersManager(
pers protocol.Perspective, v protocol.VersionNumber,
maxReceiveStreamFlowControlWindowServer protocol.ByteCount, maxReceiveConnectionFlowControlWindowServer protocol.ByteCount,
maxReceiveStreamFlowControlWindowClient protocol.ByteCount, maxReceiveConnectionFlowControlWindowClient protocol.ByteCount,
) ConnectionParametersManager {
if maxReceiveStreamFlowControlWindowServer == 0 {
maxReceiveStreamFlowControlWindowServer = protocol.DefaultMaxReceiveStreamFlowControlWindowServer
}
if maxReceiveConnectionFlowControlWindowServer == 0 {
maxReceiveConnectionFlowControlWindowServer = protocol.DefaultMaxReceiveConnectionFlowControlWindowServer
}
if maxReceiveStreamFlowControlWindowClient == 0 {
maxReceiveStreamFlowControlWindowClient = protocol.DefaultMaxReceiveStreamFlowControlWindowClient
}
if maxReceiveConnectionFlowControlWindowClient == 0 {
maxReceiveConnectionFlowControlWindowClient = protocol.DefaultMaxReceiveConnectionFlowControlWindowClient
}
h := &connectionParametersManager{
perspective: pers,
version: v,
@@ -69,6 +91,11 @@ func NewConnectionParamatersManager(pers protocol.Perspective, v protocol.Versio
sendConnectionFlowControlWindow: protocol.InitialConnectionFlowControlWindow, // can only be changed by the client
receiveStreamFlowControlWindow: protocol.ReceiveStreamFlowControlWindow,
receiveConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
maxReceiveStreamFlowControlWindowServer: maxReceiveStreamFlowControlWindowServer,
maxReceiveConnectionFlowControlWindowServer: maxReceiveConnectionFlowControlWindowServer,
maxReceiveStreamFlowControlWindowClient: maxReceiveStreamFlowControlWindowClient,
maxReceiveConnectionFlowControlWindowClient: maxReceiveConnectionFlowControlWindowClient,
}
if h.perspective == protocol.PerspectiveServer {
@@ -208,9 +235,9 @@ func (h *connectionParametersManager) GetReceiveStreamFlowControlWindow() protoc
// GetMaxReceiveStreamFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
func (h *connectionParametersManager) GetMaxReceiveStreamFlowControlWindow() protocol.ByteCount {
if h.perspective == protocol.PerspectiveServer {
return protocol.MaxReceiveStreamFlowControlWindowServer
return h.maxReceiveStreamFlowControlWindowServer
}
return protocol.MaxReceiveStreamFlowControlWindowClient
return h.maxReceiveStreamFlowControlWindowClient
}
// GetReceiveConnectionFlowControlWindow gets the size of the stream-level flow control window for receiving data
@@ -223,9 +250,9 @@ func (h *connectionParametersManager) GetReceiveConnectionFlowControlWindow() pr
// GetMaxReceiveConnectionFlowControlWindow gets the maximum size of the stream-level flow control window for sending data
func (h *connectionParametersManager) GetMaxReceiveConnectionFlowControlWindow() protocol.ByteCount {
if h.perspective == protocol.PerspectiveServer {
return protocol.MaxReceiveConnectionFlowControlWindowServer
return h.maxReceiveConnectionFlowControlWindowServer
}
return protocol.MaxReceiveConnectionFlowControlWindowClient
return h.maxReceiveConnectionFlowControlWindowClient
}
// GetMaxOutgoingStreams gets the maximum number of outgoing streams per connection

View File

@@ -2,6 +2,7 @@ package handshake
import (
"encoding/binary"
"math"
"time"
"github.com/lucas-clemente/quic-go/protocol"
@@ -12,10 +13,20 @@ import (
var _ = Describe("ConnectionsParameterManager", func() {
var cpm *connectionParametersManager // a connectionParametersManager for a server
var cpmClient *connectionParametersManager
const MB = 1 << 20
maxReceiveStreamFlowControlWindowServer := protocol.ByteCount(math.Floor(1.1 * MB)) // default is 1 MB
maxReceiveConnectionFlowControlWindowServer := protocol.ByteCount(math.Floor(1.5 * MB)) // default is 1.5 MB
maxReceiveStreamFlowControlWindowClient := protocol.ByteCount(math.Floor(6.4 * MB)) // default is 6 MB
maxReceiveConnectionFlowControlWindowClient := protocol.ByteCount(math.Floor(13 * MB)) // default is 15 MB
BeforeEach(func() {
cpm = NewConnectionParamatersManager(protocol.PerspectiveServer, protocol.Version36).(*connectionParametersManager)
cpmClient = NewConnectionParamatersManager(protocol.PerspectiveClient, protocol.Version36).(*connectionParametersManager)
cpm = NewConnectionParamatersManager(protocol.PerspectiveServer, protocol.Version36,
maxReceiveStreamFlowControlWindowServer, maxReceiveConnectionFlowControlWindowServer,
maxReceiveStreamFlowControlWindowClient, maxReceiveConnectionFlowControlWindowClient,
).(*connectionParametersManager)
cpmClient = NewConnectionParamatersManager(protocol.PerspectiveClient, protocol.Version36,
maxReceiveStreamFlowControlWindowServer, maxReceiveConnectionFlowControlWindowServer,
maxReceiveStreamFlowControlWindowClient, maxReceiveConnectionFlowControlWindowClient,
).(*connectionParametersManager)
})
Context("SHLO", func() {
@@ -137,10 +148,19 @@ var _ = Describe("ConnectionsParameterManager", func() {
})
It("has the correct maximum flow control windows", func() {
Expect(cpm.GetMaxReceiveStreamFlowControlWindow()).To(Equal(protocol.MaxReceiveStreamFlowControlWindowServer))
Expect(cpm.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(protocol.MaxReceiveConnectionFlowControlWindowServer))
Expect(cpmClient.GetMaxReceiveStreamFlowControlWindow()).To(Equal(protocol.MaxReceiveStreamFlowControlWindowClient))
Expect(cpmClient.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(protocol.MaxReceiveConnectionFlowControlWindowClient))
Expect(cpm.GetMaxReceiveStreamFlowControlWindow()).To(Equal(maxReceiveStreamFlowControlWindowServer))
Expect(cpm.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(maxReceiveConnectionFlowControlWindowServer))
Expect(cpmClient.GetMaxReceiveStreamFlowControlWindow()).To(Equal(maxReceiveStreamFlowControlWindowClient))
Expect(cpmClient.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(maxReceiveConnectionFlowControlWindowClient))
})
It("defaults to the correct maximum flow control windows", func() {
cpmDefault := NewConnectionParamatersManager(protocol.PerspectiveServer, protocol.Version36, 0, 0, 0, 0).(*connectionParametersManager)
cpmClientDefault := NewConnectionParamatersManager(protocol.PerspectiveClient, protocol.Version36, 0, 0, 0, 0).(*connectionParametersManager)
Expect(cpmDefault.GetMaxReceiveStreamFlowControlWindow()).To(Equal(protocol.DefaultMaxReceiveStreamFlowControlWindowServer))
Expect(cpmDefault.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(protocol.DefaultMaxReceiveConnectionFlowControlWindowServer))
Expect(cpmClientDefault.GetMaxReceiveStreamFlowControlWindow()).To(Equal(protocol.DefaultMaxReceiveStreamFlowControlWindowClient))
Expect(cpmClientDefault.GetMaxReceiveConnectionFlowControlWindow()).To(Equal(protocol.DefaultMaxReceiveConnectionFlowControlWindowClient))
})
It("sets a new stream-level flow control window for sending", func() {

View File

@@ -8,9 +8,9 @@ import (
"time"
"github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/internal/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
@@ -111,7 +111,10 @@ var _ = Describe("Client Crypto Setup", func() {
version,
stream,
nil,
NewConnectionParamatersManager(protocol.PerspectiveClient, version),
NewConnectionParamatersManager(protocol.PerspectiveClient, version,
protocol.DefaultMaxReceiveStreamFlowControlWindowServer, protocol.DefaultMaxReceiveConnectionFlowControlWindowServer,
protocol.DefaultMaxReceiveStreamFlowControlWindowClient, protocol.DefaultMaxReceiveConnectionFlowControlWindowClient,
),
aeadChanged,
&TransportParameters{},
nil,

View File

@@ -7,9 +7,9 @@ import (
"net"
"github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/internal/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -184,7 +184,10 @@ var _ = Describe("Server Crypto Setup", func() {
Expect(err).NotTo(HaveOccurred())
version = protocol.SupportedVersions[len(protocol.SupportedVersions)-1]
supportedVersions = []protocol.VersionNumber{version, 98, 99}
cpm = NewConnectionParamatersManager(protocol.PerspectiveServer, protocol.VersionWhatever)
cpm = NewConnectionParamatersManager(protocol.PerspectiveServer, protocol.VersionWhatever,
protocol.DefaultMaxReceiveStreamFlowControlWindowServer, protocol.DefaultMaxReceiveConnectionFlowControlWindowServer,
protocol.DefaultMaxReceiveStreamFlowControlWindowClient, protocol.DefaultMaxReceiveConnectionFlowControlWindowClient,
)
csInt, err := NewCryptoSetup(
protocol.ConnectionID(42),
remoteAddr,

View File

@@ -80,6 +80,18 @@ type Config struct {
// If not set, it verifies that the address matches, and that the STK was issued within the last 24 hours
// This option is only valid for the server.
AcceptSTK func(clientAddr net.Addr, stk *STK) bool
// MaxReceiveStreamFlowControlWindowServer is the maximum stream-level flow control window for receiving data, for the server
// If this value is zero, the timeout is set to protocol.DefaultMaxReceiveStreamFlowControlWindowServer
MaxReceiveStreamFlowControlWindowServer protocol.ByteCount
// MaxReceiveConnectionFlowControlWindowServer is the connection-level flow control window for receiving data, for the server
// If this value is zero, the timeout is set to protocol.DefaultMaxReceiveConnectionFlowControlWindowServer
MaxReceiveConnectionFlowControlWindowServer protocol.ByteCount
// MaxReceiveStreamFlowControlWindowClient is the maximum stream-level flow control window for receiving data, for the client
// If this value is zero, the timeout is set to protocol.DefaultMaxReceiveStreamFlowControlWindowClient
MaxReceiveStreamFlowControlWindowClient protocol.ByteCount
// MaxReceiveConnectionFlowControlWindowClient is the connection-level flow control window for receiving data, for the client
// If this value is zero, the timeout is set to protocol.DefaultMaxReceiveConnectionFlowControlWindowClient
MaxReceiveConnectionFlowControlWindowClient protocol.ByteCount
}
// A Listener for incoming QUIC connections

View File

@@ -39,21 +39,21 @@ const ReceiveStreamFlowControlWindow ByteCount = (1 << 10) * 32 // 32 kB
// This is the value that Google servers are using
const ReceiveConnectionFlowControlWindow ByteCount = (1 << 10) * 48 // 48 kB
// MaxReceiveStreamFlowControlWindowServer is the maximum stream-level flow control window for receiving data, for the server
// DefaultMaxReceiveStreamFlowControlWindowServer is the default maximum stream-level flow control window for receiving data, for the server
// This is the value that Google servers are using
const MaxReceiveStreamFlowControlWindowServer ByteCount = 1 * (1 << 20) // 1 MB
const DefaultMaxReceiveStreamFlowControlWindowServer ByteCount = 1 * (1 << 20) // 1 MB
// MaxReceiveConnectionFlowControlWindowServer is the connection-level flow control window for receiving data, for the server
// DefaultMaxReceiveConnectionFlowControlWindowServer is the default connection-level flow control window for receiving data, for the server
// This is the value that Google servers are using
const MaxReceiveConnectionFlowControlWindowServer ByteCount = 1.5 * (1 << 20) // 1.5 MB
const DefaultMaxReceiveConnectionFlowControlWindowServer ByteCount = 1.5 * (1 << 20) // 1.5 MB
// MaxReceiveStreamFlowControlWindowClient is the maximum stream-level flow control window for receiving data, for the client
// DefaultMaxReceiveStreamFlowControlWindowClient is the default maximum stream-level flow control window for receiving data, for the client
// This is the value that Chromium is using
const MaxReceiveStreamFlowControlWindowClient ByteCount = 6 * (1 << 20) // 6 MB
const DefaultMaxReceiveStreamFlowControlWindowClient ByteCount = 6 * (1 << 20) // 6 MB
// MaxReceiveConnectionFlowControlWindowClient is the connection-level flow control window for receiving data, for the client
// DefaultMaxReceiveConnectionFlowControlWindowClient is the default connection-level flow control window for receiving data, for the client
// This is the value that Google servers are using
const MaxReceiveConnectionFlowControlWindowClient ByteCount = 15 * (1 << 20) // 15 MB
const DefaultMaxReceiveConnectionFlowControlWindowClient ByteCount = 15 * (1 << 20) // 15 MB
// ConnectionFlowControlMultiplier determines how much larger the connection flow control windows needs to be relative to any stream's flow control window
// This is the value that Chromium is using

View File

@@ -9,9 +9,9 @@ import (
"github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/internal/utils"
)
// packetHandler handles packets
@@ -122,6 +122,10 @@ func populateServerConfig(config *Config) *Config {
Versions: versions,
HandshakeTimeout: handshakeTimeout,
AcceptSTK: vsa,
MaxReceiveStreamFlowControlWindowServer: config.MaxReceiveStreamFlowControlWindowServer,
MaxReceiveConnectionFlowControlWindowServer: config.MaxReceiveConnectionFlowControlWindowServer,
MaxReceiveStreamFlowControlWindowClient: config.MaxReceiveStreamFlowControlWindowClient,
MaxReceiveConnectionFlowControlWindowClient: config.MaxReceiveConnectionFlowControlWindowClient,
}
}

View File

@@ -12,9 +12,9 @@ import (
"github.com/lucas-clemente/quic-go/flowcontrol"
"github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"github.com/lucas-clemente/quic-go/qerr"
"github.com/lucas-clemente/quic-go/internal/utils"
)
type unpacker interface {
@@ -172,7 +172,9 @@ func (s *session) setup(
s.sessionCreationTime = now
s.rttStats = &congestion.RTTStats{}
s.connectionParameters = handshake.NewConnectionParamatersManager(s.perspective, s.version)
s.connectionParameters = handshake.NewConnectionParamatersManager(s.perspective, s.version,
s.config.MaxReceiveStreamFlowControlWindowServer, s.config.MaxReceiveConnectionFlowControlWindowServer,
s.config.MaxReceiveStreamFlowControlWindowClient, s.config.MaxReceiveConnectionFlowControlWindowClient)
s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats)
s.flowControlManager = flowcontrol.NewFlowControlManager(s.connectionParameters, s.rttStats)
s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.ackAlarmChanged)