fix(dc): Disables MTU discovery (base = max MTU = 1450) - #3295
Merged
Conversation
This is primarily intended to address bad behavior we found when enabling hybrid ML-KEM, which increases the size of ClientHello and ServerHello past the supported MTU on some networks. There are likely deficiencies to be fixed within s2n-quic's logic such that this is less necessary, but this is the right short-term solution.
Mark-Simulacrum
marked this pull request as ready for review
September 1, 2026 15:00
ben-r-smith
approved these changes
Sep 1, 2026
Mark-Simulacrum
force-pushed
the
dc-no-mtu-probes
branch
from
September 1, 2026 15:42
f811a72 to
5e08fe4
Compare
Mark-Simulacrum
added a commit
to Mark-Simulacrum/s2n-quic
that referenced
this pull request
Sep 1, 2026
Adds a bach simulation of the handshake latency regression that appears when
post-quantum key exchange (s2n-tls policy 20250721) makes the first flight too
large for a PTO probe to carry.
s2n-quic pads the first flight out to initial_mtu to validate it, so an endpoint
configured with an initial_mtu the path cannot carry loses that flight. Recovery
normally costs one PTO, since probes are clamped to MINIMUM_MAX_DATAGRAM_SIZE and
a classical ~271 byte ClientHello fits comfortably in the ~1145 bytes that leaves
for CRYPTO.
An ML-KEM ClientHello is ~1503 bytes and does not fit, so each probe delivers only
a prefix. The server cannot report what it received either: its Normal-mode
transmissions are padded to initial_mtu as well, so even a pure-ACK reply goes out
as an oversized datagram and is dropped. Nothing is ever ACKed, so the client
re-sends from offset 0 on every probe, and progress waits for the server's own PTO
to fire with a clamped, deliverable probe. That puts the client's full PTO backoff
ladder (3, 6, 12, 24, 48, 96ms) on the critical path and makes the penalty largely
independent of RTT.
Measured in simulated time at a 1ms RTT on a 1500-byte path, with base_mtu 1450
and initial_mtu 8940 on both endpoints:
classical ClientHello 10ms
ML-KEM ClientHello 191ms
ML-KEM ClientHello, initial_mtu = base_mtu 5ms
On a jumbo-capable path both policies complete in 1 RTT, so the trigger is the
first flight being padded above the path MTU rather than the ClientHello size on
its own.
s2n-quic-dc no longer triggers this directly: aws#3295 disabled MTU discovery
(base_mtu = initial_mtu = max_mtu) and aws#3296 enabled client packet buffering.
dc_mtu_config_is_unaffected pins that down, and the client packet buffer is part
of the shared scenario setup so the remaining cases measure what dc would see. The
regression cases are kept because the behavior is still reachable by any
application that configures an initial_mtu above the real path MTU, and because
the underlying causes are still worth fixing:
- probes re-send CRYPTO from offset 0 rather than advancing past un-ACKed ranges
- Normal-mode transmissions are padded to initial_mtu even when they carry
nothing but an ACK, so an endpoint cannot report progress over a path that
has already shown it cannot carry that size
The last case (client clamped, server still jumbo) covers the residual cost: the
ML-KEM ServerHello is 1178 bytes of Initial CRYPTO and a 1200-byte probe carries
only 1125, so the tail costs one extra round trip.
Existing MTU coverage only exercises oversized application-data packets, so a
handshake flight exceeding the initial MTU was untested.
Mark-Simulacrum
added a commit
to Mark-Simulacrum/s2n-quic
that referenced
this pull request
Sep 2, 2026
Adds a bach simulation of the handshake latency regression that appears when post-quantum key exchange (s2n-tls policy 20250721) makes the first flight too large for a PTO probe to carry and the initial MTU is set to ~9kb. Measured in simulated time at a 1ms RTT on a 1500-byte path, with base_mtu 1450 and initial_mtu 8940 on both endpoints: * classical ClientHello - 10ms * ML-KEM ClientHello - 191ms * ML-KEM ClientHello, initial_mtu = base_mtu - 9ms w/o client buffering * ML-KEM ClientHello, initial_mtu = base_mtu - 5ms w/ client buffering This is essentially adding a test case demonstrating the fixes in aws#3295 and aws#3296 work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release Summary:
Resolved issues:
Description of changes:
This is primarily intended to address bad behavior we found when enabling hybrid ML-KEM, which increases the size of ClientHello and ServerHello past the supported MTU on some networks. There are likely deficiencies to be fixed within s2n-quic's logic such that this is less necessary, but this is the right short-term solution.
Call-outs:
n/a
Testing:
See added tests that confirm this does what it says. I'd like deeper test coverage to confirm this doesn't cause more issues but getting this patch out in the meantime.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.