Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

increase initial packet size to 1280 bytes (for both IPv4 and IPv6) #4500

Merged
merged 1 commit into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading