Skip to content

fix(dc): Disables MTU discovery (base = max MTU = 1450) - #3295

Merged
Mark-Simulacrum merged 1 commit into
aws:mainfrom
Mark-Simulacrum:dc-no-mtu-probes
Sep 1, 2026
Merged

fix(dc): Disables MTU discovery (base = max MTU = 1450)#3295
Mark-Simulacrum merged 1 commit into
aws:mainfrom
Mark-Simulacrum:dc-no-mtu-probes

Conversation

@Mark-Simulacrum

Copy link
Copy Markdown
Collaborator

Release Summary:

  • fix(dc): Disable MTU probing/discovery

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.

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
Mark-Simulacrum marked this pull request as ready for review September 1, 2026 15:00
@Mark-Simulacrum
Mark-Simulacrum requested review from a team as code owners September 1, 2026 15:00
@Mark-Simulacrum
Mark-Simulacrum merged commit 3ca2281 into aws:main Sep 1, 2026
125 checks passed
@Mark-Simulacrum
Mark-Simulacrum deleted the dc-no-mtu-probes branch September 1, 2026 15:43
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants