TUN-5623: Configure quic max datagram frame size to 1350 bytes for none Windows platforms

This commit is contained in:
cthuang
2022-01-06 12:17:10 +00:00
parent ef3152f334
commit 6fa58aadba
44 changed files with 11652 additions and 57 deletions

View File

@@ -99,6 +99,10 @@ func populateConfig(config *Config) *Config {
} else if maxIncomingUniStreams < 0 {
maxIncomingUniStreams = 0
}
maxDatagrameFrameSize := config.MaxDatagramFrameSize
if maxDatagrameFrameSize == 0 {
maxDatagrameFrameSize = int64(protocol.DefaultMaxDatagramFrameSize)
}
return &Config{
Versions: versions,
@@ -116,6 +120,7 @@ func populateConfig(config *Config) *Config {
StatelessResetKey: config.StatelessResetKey,
TokenStore: config.TokenStore,
EnableDatagrams: config.EnableDatagrams,
MaxDatagramFrameSize: maxDatagrameFrameSize,
DisablePathMTUDiscovery: config.DisablePathMTUDiscovery,
DisableVersionNegotiationPackets: config.DisableVersionNegotiationPackets,
Tracer: config.Tracer,

View File

@@ -1,6 +1,8 @@
package quic
import (
"fmt"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/internal/wire"
@@ -15,7 +17,7 @@ type datagramQueue struct {
hasData func()
dequeued chan struct{}
dequeued chan error
logger utils.Logger
}
@@ -25,7 +27,7 @@ func newDatagramQueue(hasData func(), logger utils.Logger) *datagramQueue {
hasData: hasData,
sendQueue: make(chan *wire.DatagramFrame, 1),
rcvQueue: make(chan []byte, protocol.DatagramRcvQueueLen),
dequeued: make(chan struct{}),
dequeued: make(chan error),
closed: make(chan struct{}),
logger: logger,
}
@@ -42,18 +44,23 @@ func (h *datagramQueue) AddAndWait(f *wire.DatagramFrame) error {
}
select {
case <-h.dequeued:
return nil
case err := <-h.dequeued:
return err
case <-h.closed:
return h.closeErr
}
}
// Get dequeues a DATAGRAM frame for sending.
func (h *datagramQueue) Get() *wire.DatagramFrame {
func (h *datagramQueue) Get(maxDatagramSize protocol.ByteCount, version protocol.VersionNumber) *wire.DatagramFrame {
select {
case f := <-h.sendQueue:
h.dequeued <- struct{}{}
datagramSize := f.Length(version)
if datagramSize > maxDatagramSize {
h.dequeued <- fmt.Errorf("datagram size %d exceed current limit of %d", datagramSize, maxDatagramSize)
return nil
}
h.dequeued <- nil
return f
default:
return nil

View File

@@ -291,8 +291,9 @@ type Config struct {
DisableVersionNegotiationPackets bool
// See https://datatracker.ietf.org/doc/draft-ietf-quic-datagram/.
// Datagrams will only be available when both peers enable datagram support.
EnableDatagrams bool
Tracer logging.Tracer
EnableDatagrams bool
MaxDatagramFrameSize int64
Tracer logging.Tracer
}
// ConnectionState records basic details about a QUIC connection

View File

@@ -41,7 +41,7 @@ type cubicSender struct {
// Used for stats collection of slowstartPacketsLost
lastCutbackExitedSlowstart bool
// Congestion window in packets.
// Congestion window in bytes.
congestionWindow protocol.ByteCount
// Slow start congestion window in bytes, aka ssthresh.

View File

@@ -132,10 +132,10 @@ const MaxPostHandshakeCryptoFrameSize = 1000
// but must ensure that a maximum size ACK frame fits into one packet.
const MaxAckFrameSize ByteCount = 1000
// MaxDatagramFrameSize is the maximum size of a DATAGRAM frame as defined in
// DefaultMaxDatagramFrameSize is the maximum size of a DATAGRAM frame as defined in
// https://datatracker.ietf.org/doc/draft-pauly-quic-datagram/.
// The size is chosen such that a DATAGRAM frame fits into a QUIC packet.
const MaxDatagramFrameSize ByteCount = 1220
const DefaultMaxDatagramFrameSize ByteCount = 1220
// DatagramRcvQueueLen is the length of the receive queue for DATAGRAM frames.
// See https://datatracker.ietf.org/doc/draft-pauly-quic-datagram/.

View File

@@ -1,5 +1,5 @@
//go:build go1.17
// +build go1.17
//go:build go1.17 && !go1.18
// +build go1.17,!go1.18
package qtls

View File

@@ -3,4 +3,98 @@
package qtls
var _ int = "quic-go doesn't build on Go 1.18 yet."
import (
"crypto"
"crypto/cipher"
"crypto/tls"
"net"
"unsafe"
"github.com/marten-seemann/qtls-go1-18"
)
type (
// Alert is a TLS alert
Alert = qtls.Alert
// A Certificate is qtls.Certificate.
Certificate = qtls.Certificate
// CertificateRequestInfo contains inforamtion about a certificate request.
CertificateRequestInfo = qtls.CertificateRequestInfo
// A CipherSuiteTLS13 is a cipher suite for TLS 1.3
CipherSuiteTLS13 = qtls.CipherSuiteTLS13
// ClientHelloInfo contains information about a ClientHello.
ClientHelloInfo = qtls.ClientHelloInfo
// ClientSessionCache is a cache used for session resumption.
ClientSessionCache = qtls.ClientSessionCache
// ClientSessionState is a state needed for session resumption.
ClientSessionState = qtls.ClientSessionState
// A Config is a qtls.Config.
Config = qtls.Config
// A Conn is a qtls.Conn.
Conn = qtls.Conn
// ConnectionState contains information about the state of the connection.
ConnectionState = qtls.ConnectionStateWith0RTT
// EncryptionLevel is the encryption level of a message.
EncryptionLevel = qtls.EncryptionLevel
// Extension is a TLS extension
Extension = qtls.Extension
// ExtraConfig is the qtls.ExtraConfig
ExtraConfig = qtls.ExtraConfig
// RecordLayer is a qtls RecordLayer.
RecordLayer = qtls.RecordLayer
)
const (
// EncryptionHandshake is the Handshake encryption level
EncryptionHandshake = qtls.EncryptionHandshake
// Encryption0RTT is the 0-RTT encryption level
Encryption0RTT = qtls.Encryption0RTT
// EncryptionApplication is the application data encryption level
EncryptionApplication = qtls.EncryptionApplication
)
// AEADAESGCMTLS13 creates a new AES-GCM AEAD for TLS 1.3
func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD {
return qtls.AEADAESGCMTLS13(key, fixedNonce)
}
// Client returns a new TLS client side connection.
func Client(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
return qtls.Client(conn, config, extraConfig)
}
// Server returns a new TLS server side connection.
func Server(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
return qtls.Server(conn, config, extraConfig)
}
func GetConnectionState(conn *Conn) ConnectionState {
return conn.ConnectionStateWith0RTT()
}
// ToTLSConnectionState extracts the tls.ConnectionState
func ToTLSConnectionState(cs ConnectionState) tls.ConnectionState {
return cs.ConnectionState
}
type cipherSuiteTLS13 struct {
ID uint16
KeyLen int
AEAD func(key, fixedNonce []byte) cipher.AEAD
Hash crypto.Hash
}
//go:linkname cipherSuiteTLS13ByID github.com/marten-seemann/qtls-go1-18.cipherSuiteTLS13ByID
func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13
// CipherSuiteTLS13ByID gets a TLS 1.3 cipher suite.
func CipherSuiteTLS13ByID(id uint16) *CipherSuiteTLS13 {
val := cipherSuiteTLS13ByID(id)
cs := (*cipherSuiteTLS13)(unsafe.Pointer(val))
return &qtls.CipherSuiteTLS13{
ID: cs.ID,
KeyLen: cs.KeyLen,
AEAD: cs.AEAD,
Hash: cs.Hash,
}
}

View File

@@ -0,0 +1,6 @@
//go:build go1.19
// +build go1.19
package qtls
var _ int = "quic-go doesn't build on Go 1.19 yet."

View File

@@ -1,4 +1,4 @@
package logging
//go:generate sh -c "mockgen -package logging -self_package github.com/lucas-clemente/quic-go/logging -destination mock_connection_tracer_test.go github.com/lucas-clemente/quic-go/logging ConnectionTracer && goimports -w mock_connection_tracer_test.go"
//go:generate sh -c "mockgen -package logging -self_package github.com/lucas-clemente/quic-go/logging -destination mock_tracer_test.go github.com/lucas-clemente/quic-go/logging Tracer && goimports -w mock_tracer_test.go"
//go:generate sh -c "mockgen -package logging -self_package github.com/lucas-clemente/quic-go/logging -destination mock_connection_tracer_test.go github.com/lucas-clemente/quic-go/logging ConnectionTracer"
//go:generate sh -c "mockgen -package logging -self_package github.com/lucas-clemente/quic-go/logging -destination mock_tracer_test.go github.com/lucas-clemente/quic-go/logging Tracer"

View File

@@ -23,5 +23,5 @@ package quic
//go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_manager_test.go github.com/lucas-clemente/quic-go packetHandlerManager"
//go:generate sh -c "./mockgen_private.sh quic mock_multiplexer_test.go github.com/lucas-clemente/quic-go multiplexer"
//go:generate sh -c "./mockgen_private.sh quic mock_batch_conn_test.go github.com/lucas-clemente/quic-go batchConn"
//go:generate sh -c "mockgen -package quic -self_package github.com/lucas-clemente/quic-go -destination mock_token_store_test.go github.com/lucas-clemente/quic-go TokenStore && goimports -w mock_token_store_test.go"
//go:generate sh -c "mockgen -package quic -self_package github.com/lucas-clemente/quic-go -destination mock_packetconn_test.go net PacketConn && goimports -w mock_packetconn_test.go"
//go:generate sh -c "mockgen -package quic -self_package github.com/lucas-clemente/quic-go -destination mock_token_store_test.go github.com/lucas-clemente/quic-go TokenStore"
//go:generate sh -c "mockgen -package quic -self_package github.com/lucas-clemente/quic-go -destination mock_packetconn_test.go net PacketConn"

View File

@@ -44,8 +44,6 @@ AUX_FILES=$(IFS=, ; echo "${AUX[*]}")
## create a public alias for the interface, so that mockgen can process it
echo -e "package $1\n" > $TMPFILE
echo "$INTERFACE" | sed "s/$ORIG_INTERFACE_NAME/$INTERFACE_NAME/" >> $TMPFILE
goimports -w $TMPFILE
mockgen -package $1 -self_package $3 -destination $DEST -source=$TMPFILE -aux_files $AUX_FILES
goimports -w $DEST
sed "s/$TMPFILE/$SRC/" "$DEST" > "$DEST.new" && mv "$DEST.new" "$DEST"
rm "$TMPFILE"

View File

@@ -596,7 +596,7 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, ackAll
var hasDatagram bool
if p.datagramQueue != nil {
if datagram := p.datagramQueue.Get(); datagram != nil {
if datagram := p.datagramQueue.Get(maxFrameSize, p.version); datagram != nil {
payload.frames = append(payload.frames, ackhandler.Frame{
Frame: datagram,
// set it to a no-op. Then we won't set the default callback, which would retransmit the frame.

View File

@@ -316,7 +316,10 @@ var newSession = func(
RetrySourceConnectionID: retrySrcConnID,
}
if s.config.EnableDatagrams {
params.MaxDatagramFrameSize = protocol.MaxDatagramFrameSize
params.MaxDatagramFrameSize = protocol.ByteCount(s.config.MaxDatagramFrameSize)
if params.MaxDatagramFrameSize == 0 {
params.MaxDatagramFrameSize = protocol.DefaultMaxDatagramFrameSize
}
}
if s.tracer != nil {
s.tracer.SentTransportParameters(params)
@@ -440,7 +443,7 @@ var newClientSession = func(
InitialSourceConnectionID: srcConnID,
}
if s.config.EnableDatagrams {
params.MaxDatagramFrameSize = protocol.MaxDatagramFrameSize
params.MaxDatagramFrameSize = protocol.ByteCount(s.config.MaxDatagramFrameSize)
}
if s.tracer != nil {
s.tracer.SentTransportParameters(params)
@@ -1409,7 +1412,7 @@ func (s *session) handleAckFrame(frame *wire.AckFrame, encLevel protocol.Encrypt
}
func (s *session) handleDatagramFrame(f *wire.DatagramFrame) error {
if f.Length(s.version) > protocol.MaxDatagramFrameSize {
if f.Length(s.version) > protocol.ByteCount(s.config.MaxDatagramFrameSize) {
return &qerr.TransportError{
ErrorCode: qerr.ProtocolViolation,
ErrorMessage: "DATAGRAM frame too large",