Repository: quic-go/quic-go
Pull request #4500 (2024-05-08 03:33:55)

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

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/quic-go/quic-go/pull/4500?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 85.11%. Comparing base [(`66f968b`)](https://app.codecov.io/gh/quic-go/quic-go/commit/66f968b9ff1d459ee7980d69dc6aa477e1980f1e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go) to head [(`f675b66`)](https://app.codecov.io/gh/quic-go/quic-go/pull/4500?dropdown=coverage&src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4500      +/-   ##
==========================================
- Coverage   85.15%   85.11%   -0.04%     
==========================================
  Files         154      151       -3     
  Lines       14768    14480     -288     
==========================================
- Hits        12575    12324     -251     
+ Misses       1688     1669      -19     
+ Partials      505      487      -18     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/quic-go/quic-go/pull/4500?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=quic-go).


Patch:
diff --git a/connection.go b/connection.go
index 0b009fbd..e992ead6 100644
--- a/connection.go
+++ b/connection.go
@@ -276,10 +276,9 @@ 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,
@@ -287,8 +286,8 @@ var newConnection = func(
 		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),
@@ -387,10 +386,9 @@ 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,
@@ -398,8 +396,8 @@ var newClientConnection = func(
 		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),
diff --git a/interface.go b/interface.go
index 6f906fff..ff0e9b8d 100644
--- a/interface.go
+++ b/interface.go
@@ -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.
diff --git a/internal/congestion/cubic.go b/internal/congestion/cubic.go
index 4e30de65..b35d40d4 100644
--- a/internal/congestion/cubic.go
+++ b/internal/congestion/cubic.go
@@ -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
diff --git a/internal/congestion/cubic_sender.go b/internal/congestion/cubic_sender.go
index a1b06ab3..075b08e0 100644
--- a/internal/congestion/cubic_sender.go
+++ b/internal/congestion/cubic_sender.go
@@ -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
diff --git a/internal/protocol/params.go b/internal/protocol/params.go
index a08deeaa..7c4d8d4d 100644
--- a/internal/protocol/params.go
+++ b/internal/protocol/params.go
@@ -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
diff --git a/mtu_discoverer.go b/mtu_discoverer.go
index 317b0929..00ae254c 100644
--- a/mtu_discoverer.go
+++ b/mtu_discoverer.go
@@ -1,7 +1,6 @@
 package quic
 
 import (
-	"net"
 	"time"
 
 	"github.com/quic-go/quic-go/internal/ackhandler"
@@ -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)


Test patch:
diff --git a/integrationtests/self/dplpmtud_test.go b/integrationtests/self/dplpmtud_test.go
index 40272632..dd898b04 100644
--- a/integrationtests/self/dplpmtud_test.go
+++ b/integrationtests/self/dplpmtud_test.go
@@ -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"
@@ -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))
 	})
 })
diff --git a/internal/ackhandler/sent_packet_handler_test.go b/internal/ackhandler/sent_packet_handler_test.go
index 63f1b834..75c1ae2c 100644
--- a/internal/ackhandler/sent_packet_handler_test.go
+++ b/internal/ackhandler/sent_packet_handler_test.go
@@ -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},
@@ -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() {
@@ -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
 		})
diff --git a/internal/congestion/cubic_sender_test.go b/internal/congestion/cubic_sender_test.go
index d02ec3e8..78565500 100644
--- a/internal/congestion/cubic_sender_test.go
+++ b/internal/congestion/cubic_sender_test.go
@@ -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 (
@@ -47,7 +47,7 @@ var _ = Describe("Cubic Sender", func() {
 			&clock,
 			rttStats,
 			true, /*reno*/
-			protocol.InitialPacketSizeIPv4,
+			protocol.InitialPacketSize,
 			initialCongestionWindowPackets*maxDatagramSize,
 			MaxCongestionWindow,
 			nil,
@@ -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()
 
@@ -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()
@@ -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++ {
@@ -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.
diff --git a/internal/wire/extended_header_test.go b/internal/wire/extended_header_test.go
index 23a25233..e71e1519 100644
--- a/internal/wire/extended_header_test.go
+++ b/internal/wire/extended_header_test.go
@@ -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,
@@ -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))
 			})
 
diff --git a/packet_packer_test.go b/packet_packer_test.go
index 27dfb748..e0c2bb7f 100644
--- a/packet_packer_test.go
+++ b/packet_packer_test.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"net"
 	"time"
 
 	"golang.org/x/exp/rand"
@@ -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)