Skip to content

Commit

Permalink
increase initial packet size to 1280 bytes, apply to both IPv4 and IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed May 8, 2024
1 parent 66f968b commit 355989f
Show file tree
Hide file tree
Showing 11 changed files with 29 additions and 66 deletions.
14 changes: 6 additions & 8 deletions connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,19 +276,18 @@ var newConnection = func(
)
s.ctx, s.ctxCancel = context.WithCancelCause(context.WithValue(context.Background(), ConnectionTracingKey, tracingID))
s.preSetup()
initialPacketSize := getMaxPacketSize(s.conn.RemoteAddr())
s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler(
0,
initialPacketSize,
protocol.InitialPacketSize,
s.rttStats,
clientAddressValidated,
s.conn.capabilities().ECN,
s.perspective,
s.tracer,
s.logger,
)
s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, initialPacketSize, s.onMTUIncreased)
s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(initialPacketSize)))
s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, protocol.InitialPacketSize, s.onMTUIncreased)
s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(protocol.InitialPacketSize)))
params := &wire.TransportParameters{
InitialMaxStreamDataBidiLocal: protocol.ByteCount(s.config.InitialStreamReceiveWindow),
InitialMaxStreamDataBidiRemote: protocol.ByteCount(s.config.InitialStreamReceiveWindow),
Expand Down Expand Up @@ -387,19 +386,18 @@ var newClientConnection = func(
)
s.ctx, s.ctxCancel = context.WithCancelCause(context.WithValue(context.Background(), ConnectionTracingKey, tracingID))
s.preSetup()
initialPacketSize := getMaxPacketSize(s.conn.RemoteAddr())
s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler(
initialPacketNumber,
initialPacketSize,
protocol.InitialPacketSize,
s.rttStats,
false, // has no effect
s.conn.capabilities().ECN,
s.perspective,
s.tracer,
s.logger,
)
s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, initialPacketSize, s.onMTUIncreased)
s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(initialPacketSize)))
s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, protocol.InitialPacketSize, s.onMTUIncreased)
s.maxPayloadSizeEstimate.Store(uint32(estimateMaxPayloadSize(protocol.InitialPacketSize)))
oneRTTStream := newCryptoStream()
params := &wire.TransportParameters{
InitialMaxStreamDataBidiRemote: protocol.ByteCount(s.config.InitialStreamReceiveWindow),
Expand Down
5 changes: 3 additions & 2 deletions integrationtests/self/dplpmtud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/quic-go/quic-go"
quicproxy "github.com/quic-go/quic-go/integrationtests/tools/proxy"
"github.com/quic-go/quic-go/internal/protocol"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand Down Expand Up @@ -109,9 +110,9 @@ var _ = Describe("DPLPMTUD", func() {
fmt.Fprintf(GinkgoWriter, "max server packet size: %d, MTU: %d\n", maxPacketSizeServer, mtu)
Expect(maxPacketSizeClient).To(BeNumerically(">=", mtu-25))
const maxDiff = 40 // this includes the 21 bytes for the short header, 16 bytes for the encryption tag, and framing overhead
Expect(initialMaxDatagramSize).To(BeNumerically(">=", 1252-maxDiff))
Expect(initialMaxDatagramSize).To(BeNumerically(">=", protocol.InitialPacketSize-maxDiff))
Expect(finalMaxDatagramSize).To(BeNumerically(">=", maxPacketSizeClient-maxDiff))
// MTU discovery was disabled on the server side
Expect(maxPacketSizeServer).To(Equal(1252))
Expect(maxPacketSizeServer).To(BeEquivalentTo(protocol.InitialPacketSize))
})
})
2 changes: 1 addition & 1 deletion interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ type Config struct {
// DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
// This allows the sending of QUIC packets that fully utilize the available MTU of the path.
// Path MTU discovery is only available on systems that allow setting of the Don't Fragment (DF) bit.
// If unavailable or disabled, packets will be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
// If unavailable or disabled, packets will be at most 1280 bytes in size.
DisablePathMTUDiscovery bool
// Allow0RTT allows the application to decide if a 0-RTT connection attempt should be accepted.
// Only valid for the server.
Expand Down
6 changes: 3 additions & 3 deletions internal/ackhandler/sent_packet_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var _ = Describe("SentPacketHandler", func() {
JustBeforeEach(func() {
lostPackets = nil
rttStats := utils.NewRTTStats()
handler = newSentPacketHandler(42, protocol.InitialPacketSizeIPv4, rttStats, false, false, perspective, nil, utils.DefaultLogger)
handler = newSentPacketHandler(42, protocol.InitialPacketSize, rttStats, false, false, perspective, nil, utils.DefaultLogger)
streamFrame = wire.StreamFrame{
StreamID: 5,
Data: []byte{0x13, 0x37},
Expand Down Expand Up @@ -984,7 +984,7 @@ var _ = Describe("SentPacketHandler", func() {
Context("amplification limit, for the server, with validated address", func() {
JustBeforeEach(func() {
rttStats := utils.NewRTTStats()
handler = newSentPacketHandler(42, protocol.InitialPacketSizeIPv4, rttStats, true, false, perspective, nil, utils.DefaultLogger)
handler = newSentPacketHandler(42, protocol.InitialPacketSize, rttStats, true, false, perspective, nil, utils.DefaultLogger)
})

It("do not limits the window", func() {
Expand Down Expand Up @@ -1443,7 +1443,7 @@ var _ = Describe("SentPacketHandler", func() {
lostPackets = nil
rttStats := utils.NewRTTStats()
rttStats.UpdateRTT(time.Hour, 0, time.Now())
handler = newSentPacketHandler(42, protocol.InitialPacketSizeIPv4, rttStats, false, false, perspective, nil, utils.DefaultLogger)
handler = newSentPacketHandler(42, protocol.InitialPacketSize, rttStats, false, false, perspective, nil, utils.DefaultLogger)
handler.ecnTracker = ecnHandler
handler.congestion = cong
})
Expand Down
8 changes: 4 additions & 4 deletions internal/congestion/cubic.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import (
// 1024*1024^3 (first 1024 is from 0.100^3)
// where 0.100 is 100 ms which is the scaling round trip time.
const (
cubeScale = 40
cubeCongestionWindowScale = 410
cubeFactor protocol.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize
cubeScale = 40
cubeCongestionWindowScale = 410
cubeFactor = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize
// TODO: when re-enabling cubic, make sure to use the actual packet size here
maxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4)
maxDatagramSize = protocol.ByteCount(protocol.InitialPacketSize)
)

const defaultNumConnections = 1
Expand Down
2 changes: 1 addition & 1 deletion internal/congestion/cubic_sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
const (
// maxDatagramSize is the default maximum packet size used in the Linux TCP implementation.
// Used in QUIC for congestion window computations in bytes.
initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4)
initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSize)
maxBurstPackets = 3
renoBeta = 0.7 // Reno backoff factor.
minCongestionWindowPackets = 2
Expand Down
12 changes: 6 additions & 6 deletions internal/congestion/cubic_sender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (c *mockClock) Advance(d time.Duration) {
*c = mockClock(time.Time(*c).Add(d))
}

const MaxCongestionWindow protocol.ByteCount = 200 * maxDatagramSize
const MaxCongestionWindow = 200 * maxDatagramSize

var _ = Describe("Cubic Sender", func() {
var (
Expand All @@ -47,7 +47,7 @@ var _ = Describe("Cubic Sender", func() {
&clock,
rttStats,
true, /*reno*/
protocol.InitialPacketSizeIPv4,
protocol.InitialPacketSize,
initialCongestionWindowPackets*maxDatagramSize,
MaxCongestionWindow,
nil,
Expand Down Expand Up @@ -319,7 +319,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, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindowBytes, nil)
sender = newCubicSender(&clock, rttStats, false, protocol.InitialPacketSize, initialCongestionWindowPackets*maxDatagramSize, maxCongestionWindowBytes, nil)

numSent := SendAvailableSendWindow()

Expand Down Expand Up @@ -460,7 +460,7 @@ var _ = Describe("Cubic Sender", func() {

It("slow starts up to the maximum congestion window", func() {
const initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
sender = newCubicSender(&clock, rttStats, true, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil)
sender = newCubicSender(&clock, rttStats, true, protocol.InitialPacketSize, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil)

for i := 1; i < protocol.MaxCongestionWindowPackets; i++ {
sender.MaybeExitSlowStart()
Expand All @@ -475,7 +475,7 @@ var _ = Describe("Cubic Sender", func() {

It("slow starts up to maximum congestion window, if larger packets are sent", func() {
const initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
sender = newCubicSender(&clock, rttStats, true, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil)
sender = newCubicSender(&clock, rttStats, true, protocol.InitialPacketSize, initialCongestionWindowPackets*maxDatagramSize, initialMaxCongestionWindow, nil)
const packetSize = initialMaxDatagramSize + 100
sender.SetMaxDatagramSize(packetSize)
for i := 1; i < protocol.MaxCongestionWindowPackets; i++ {
Expand All @@ -490,7 +490,7 @@ var _ = Describe("Cubic Sender", func() {

It("limit cwnd increase in congestion avoidance", func() {
// Enable Cubic.
sender = newCubicSender(&clock, rttStats, false, protocol.InitialPacketSizeIPv4, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil)
sender = newCubicSender(&clock, rttStats, false, protocol.InitialPacketSize, initialCongestionWindowPackets*maxDatagramSize, MaxCongestionWindow, nil)
numSent := SendAvailableSendWindow()

// Make sure we fall out of slow start.
Expand Down
7 changes: 2 additions & 5 deletions internal/protocol/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@ const DesiredReceiveBufferSize = (1 << 20) * 7 // 7 MB
// DesiredSendBufferSize is the kernel UDP send buffer size that we'd like to use.
const DesiredSendBufferSize = (1 << 20) * 7 // 7 MB

// InitialPacketSizeIPv4 is the maximum packet size that we use for sending IPv4 packets.
const InitialPacketSizeIPv4 = 1252

// InitialPacketSizeIPv6 is the maximum packet size that we use for sending IPv6 packets.
const InitialPacketSizeIPv6 = 1232
// InitialPacketSize is the initial (before Path MTU discovery) maximum packet size used.
const InitialPacketSize = 1280

// MaxCongestionWindowPackets is the maximum congestion window in packet.
const MaxCongestionWindowPackets = 10000
Expand Down
6 changes: 3 additions & 3 deletions internal/wire/extended_header_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var _ = Describe("Header", func() {
DestConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe}),
SrcConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad, 0x0, 0x0, 0x13, 0x37}),
Version: 0x1020304,
Length: protocol.InitialPacketSizeIPv4,
Length: 1234,
},
PacketNumber: 0xdecaf,
PacketNumberLen: protocol.PacketNumberLen3,
Expand All @@ -39,8 +39,8 @@ var _ = Describe("Header", func() {
0x8, // src connection ID length
0xde, 0xca, 0xfb, 0xad, 0x0, 0x0, 0x13, 0x37, // source connection ID
}
expected = append(expected, encodeVarInt(protocol.InitialPacketSizeIPv4)...) // length
expected = append(expected, []byte{0xd, 0xec, 0xaf}...) // packet number
expected = append(expected, encodeVarInt(1234)...) // length
expected = append(expected, []byte{0xd, 0xec, 0xaf}...) // packet number
Expect(b).To(Equal(expected))
})

Expand Down
15 changes: 0 additions & 15 deletions mtu_discoverer.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package quic

import (
"net"
"time"

"github.com/quic-go/quic-go/internal/ackhandler"
Expand All @@ -27,20 +26,6 @@ const (
mtuProbeDelay = 5
)

func getMaxPacketSize(addr net.Addr) protocol.ByteCount {
maxSize := protocol.ByteCount(protocol.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 utils.IsIPv4(udpAddr.IP) {
maxSize = protocol.InitialPacketSizeIPv4
} else {
maxSize = protocol.InitialPacketSizeIPv6
}
}
return maxSize
}

type mtuFinder struct {
lastProbeTime time.Time
mtuIncreased func(protocol.ByteCount)
Expand Down
18 changes: 0 additions & 18 deletions packet_packer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"fmt"
"net"
"time"

"golang.org/x/exp/rand"
Expand Down Expand Up @@ -100,23 +99,6 @@ var _ = Describe("Packet packer", func() {
packer = newPacketPacker(protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8}), func() protocol.ConnectionID { return connID }, initialStream, handshakeStream, pnManager, retransmissionQueue, sealingManager, framer, ackFramer, datagramQueue, protocol.PerspectiveServer)
})

Context("determining the maximum packet size", func() {
It("uses the minimum initial size, if it can't determine if the remote address is IPv4 or IPv6", func() {
Expect(getMaxPacketSize(&net.TCPAddr{})).To(BeEquivalentTo(protocol.MinInitialPacketSize))
})

It("uses the maximum IPv4 packet size, if the remote address is IPv4", func() {
addr := &net.UDPAddr{IP: net.IPv4(11, 12, 13, 14), Port: 1337}
Expect(getMaxPacketSize(addr)).To(BeEquivalentTo(protocol.InitialPacketSizeIPv4))
})

It("uses the maximum IPv6 packet size, if the remote address is IPv6", func() {
ip := net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
addr := &net.UDPAddr{IP: ip, Port: 1337}
Expect(getMaxPacketSize(addr)).To(BeEquivalentTo(protocol.InitialPacketSizeIPv6))
})
})

Context("generating a packet header", func() {
It("uses the Long Header format", func() {
pnManager.EXPECT().PeekPacketNumber(protocol.EncryptionHandshake).Return(protocol.PacketNumber(0x42), protocol.PacketNumberLen3)
Expand Down

0 comments on commit 355989f

Please sign in to comment.