Skip to content

Reject 0-RTT downgrade of the extended CONNECT setting - #3940

Merged
larseggert merged 2 commits into
mozilla:mainfrom
srkyn:research/zero-rtt-connect-downgrade
Sep 7, 2026
Merged

larseggert merged 2 commits into
mozilla:mainfrom
srkyn:research/zero-rtt-connect-downgrade

Conversation

@srkyn

@srkyn srkyn commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

On a resumed connection, Neqo currently accepts a new SETTINGS frame that omits SETTINGS_ENABLE_CONNECT_PROTOCOL even when the stored 0-RTT value was 1. The feature negotiation then disables extended CONNECT, but the connection remains open.

RFC 9114 Section 7.2.4.2 requires H3_SETTINGS_ERROR when a server accepts 0-RTT and then omits an understood setting that previously had a non-default value. The setting's default is 0, so omission after a stored value of 1 is covered by that rule.

This adds EnableConnect to the existing 0-RTT settings comparison and includes a regression test for the omitted-setting case.

Validation:

  • cargo test --locked --release -p neqo-http3
  • cargo check --locked -p neqo-http3
  • cargo fmt --all -- --check
  • cargo clippy --locked -p neqo-http3 --all-targets -- -D warnings

@codecov

codecov Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.75%. Comparing base (30f8b8d) to head (18a4bc8).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3940      +/-   ##
==========================================
- Coverage   96.91%   96.75%   -0.16%     
==========================================
  Files         113      118       +5     
  Lines       39439    39801     +362     
  Branches    39439    39801     +362     
==========================================
+ Hits        38222    38510     +288     
- Misses       1202     1266      +64     
- Partials       15       25      +10     
Flag Coverage Δ
freebsd 94.08% <100.00%> (-0.15%) ⬇️
linux 96.94% <100.00%> (-0.01%) ⬇️
macos 95.02% <100.00%> (+<0.01%) ⬆️
windows 95.07% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
neqo-common 99.26% <ø> (ø)
neqo-http3 95.27% <100.00%> (+<0.01%) ⬆️
neqo-qpack 96.88% <ø> (ø)
neqo-transport 97.69% <ø> (ø)
neqo-udp 95.37% <ø> (ø)
mtu 89.13% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed

codspeed Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 78 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing srkyn:research/zero-rtt-connect-downgrade (18a4bc8) with main (152962a)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused implementation and regression test address the RFC requirement with no unresolved issues.

Pull request overview

Adds RFC-compliant rejection of extended CONNECT setting downgrades during 0-RTT resumption.

Changes:

  • Includes EnableConnect in resumed-setting compatibility checks.
  • Adds regression coverage for omission after a stored value of 1.
File summaries
File Description
neqo-http3/src/connection.rs Rejects extended CONNECT downgrades with H3_SETTINGS_ERROR.
neqo-http3/src/connection_client.rs Tests the omitted-setting downgrade case.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread neqo-http3/src/connection_client.rs Resolved
Comment thread neqo-http3/src/connection.rs Resolved
Signed-off-by: David Sarkisyan <[email protected]>
@larseggert
larseggert enabled auto-merge September 7, 2026 05:29
@larseggert

Copy link
Copy Markdown
Collaborator

Thank you!

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Performance profiles for profiler.firefox.com

Benchmarks (14)
  • neqo-bin-main: pr · base
  • neqo-common-decoder: pr · base
  • neqo-http3-streams_simulated: pr · base
  • neqo-http3-streams_walltime: pr · base
  • neqo-transport-frame_decode: pr · base · base · base
  • neqo-transport-min_bandwidth: pr · base
  • neqo-transport-pacer: pr · base
  • neqo-transport-packet_codec: pr · base
  • neqo-transport-range_tracker: pr · base
  • neqo-transport-rx_stream_orderer: pr · base
  • neqo-transport-send_streams: pr · base
  • neqo-transport-sent_packets: pr · base
  • neqo-transport-transfer_simulated: pr · base
  • neqo-transport-transfer_walltime: pr · base
Comparisons (5)

@larseggert
larseggert added this pull request to the merge queue Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Client/server transfer results

Performance differences relative to 152962a.

No significant performance differences.

Table above only shows statistically significant changes. See all results below.

All results

Transfer of 33554432 bytes over loopback, min. 100 runs. All unit-less numbers are in milliseconds.

Client vs. server Mean±σ Min–Max Median±MAD MiB/s±σ ΔMedian
google-google 462.1 ± 2.2 459.2 – 467.9 461.7 ± 1.6 69.2 ± 0.3
google-neqo-cubic 272.2 ± 1.7 267.5 – 277.6 272.1 ± 1.5 117.6 ± 0.7 +0.1 (+0.0%)
neqo-google-cubic 763.0 ± 2.3 754.8 – 768.7 762.8 ± 2.1 41.9 ± 0.1 +0.1 (+0.0%)
neqo-neqo-cubic 78.5 ± 2.2 72.2 – 85.5 78.2 ± 2.0 407.6 ± 11.5 +0.3 (+0.4%)
neqo-neqo-cubic-nopacing 80.4 ± 3.5 76.3 – 96.0 79.6 ± 2.0 398.0 ± 17.2 +0.0 (+0.0%)
neqo-neqo-newreno 78.6 ± 2.0 75.1 – 86.6 78.2 ± 1.4 407.2 ± 10.4 -0.1 (-0.1%)
neqo-neqo-newreno-nopacing 80.0 ± 3.1 73.7 – 92.4 79.4 ± 2.2 399.9 ± 15.6 -0.3 (-0.4%)
neqo-quiche-cubic 194.1 ± 2.0 189.6 – 200.5 193.7 ± 1.2 164.8 ± 1.7 +0.2 (+0.1%)
neqo-s2n-cubic 215.8 ± 1.5 213.0 – 221.5 215.4 ± 1.0 148.3 ± 1.0 -0.8 (-0.4%)
quiche-neqo-cubic 137.6 ± 1.6 132.3 – 143.0 137.5 ± 0.9 232.6 ± 2.7 -0.1 (-0.0%)
quiche-quiche 136.6 ± 3.1 129.3 – 144.7 136.2 ± 2.9 234.3 ± 5.3
s2n-neqo-cubic 219.7 ± 2.2 212.6 – 227.0 219.4 ± 1.3 145.6 ± 1.4 +0.4 (+0.2%)
s2n-s2n ⚠️ 290.8 ± 19.6 279.9 – 390.3 285.9 ± 2.2 110.1 ± 7.4

Download data for profiler.firefox.com or download performance comparison data.

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Failed Interop Tests

QUIC Interop Runner, client vs. server, differences relative to main at 152962a.

neqo-pr as clientneqo-pr as server
neqo-pr vs. go-x-net: BP BA
neqo-pr vs. haproxy: BP BA
neqo-pr vs. linuxquic: ⚠️BP
neqo-pr vs. lsquic: baseline result missing
neqo-pr vs. msquic: A L1 C1
neqo-pr vs. mvfst: A ⚠️BA
neqo-pr vs. neqo: A
neqo-pr vs. nginx: BP BA
neqo-pr vs. ngtcp2: CM
neqo-pr vs. picoquic: A ⚠️BP BA
neqo-pr vs. quic-go: A
neqo-pr vs. quic-zig: B
neqo-pr vs. quiche: BP BA
neqo-pr vs. s2n-quic: CM
neqo-pr vs. tquic: run cancelled after 20 min
neqo-pr vs. xquic: S R Z A L1 C1
aioquic vs. neqo-pr: CM
go-x-net vs. neqo-pr: ⚠️BP CM
kwik vs. neqo-pr: BP BA CM
lsquic vs. neqo-pr: ⚠️C1
msquic vs. neqo-pr: CM
mvfst vs. neqo-pr: Z L1 C1 CM
neqo vs. neqo-pr: A
openssl vs. neqo-pr: LR M A CM
quic-go vs. neqo-pr: CM
quic-zig vs. neqo-pr: ⚠️C1
quiche vs. neqo-pr: 🚀C1 CM
quinn vs. neqo-pr: 🚀C1 V2 CM
s2n-quic vs. neqo-pr: 🚀BA CM
tquic vs. neqo-pr: CM
xquic vs. neqo-pr: M CM
All results

Succeeded Interop Tests

QUIC Interop Runner, client vs. server

neqo-pr as client

neqo-pr as server

Unsupported Interop Tests

QUIC Interop Runner, client vs. server

neqo-pr as client

neqo-pr as server

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Benchmark results

No significant performance differences relative to 152962a.

All results
transfer/1-conn/1-100mb-resp (aka. Download)/mtu-1504: Change within noise threshold.
       time:   [165.16 ms 165.45 ms 165.74 ms]
       thrpt:  [603.37 MiB/s 604.42 MiB/s 605.47 MiB/s]
change:
       time:   [-0.6967% -0.4742% -0.2400%] (p = 0.00 < 0.05)
       thrpt:  [+0.2406% +0.4765% +0.7016%]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
transfer/1-conn/10_000-parallel-1b-resp (aka. RPS)/mtu-1504: No change in performance detected.
       time:   [220.78 ms 221.14 ms 221.54 ms]
       thrpt:  [45.139 Kelem/s 45.221 Kelem/s 45.294 Kelem/s]
change:
       time:   [-0.1175% +0.1083% +0.3380%] (p = 0.37 > 0.05)
       thrpt:  [-0.3368% -0.1082% +0.1177%]
       No change in performance detected.
Found 3 outliers among 100 measurements (3.00%)
2 (2.00%) high mild
1 (1.00%) high severe
transfer/1-conn/1-1b-resp (aka. HPS)/mtu-1504: No change in performance detected.
       time:   [35.798 ms 35.881 ms 35.971 ms]
       thrpt:  [27.801   B/s 27.870   B/s 27.934   B/s]
change:
       time:   [-0.5625% -0.2106% +0.1301%] (p = 0.24 > 0.05)
       thrpt:  [-0.1300% +0.2111% +0.5656%]
       No change in performance detected.
Found 5 outliers among 100 measurements (5.00%)
4 (4.00%) high mild
1 (1.00%) high severe
transfer/1-conn/1-100mb-req (aka. Upload)/mtu-1504: Change within noise threshold.
       time:   [162.07 ms 162.34 ms 162.64 ms]
       thrpt:  [614.87 MiB/s 615.99 MiB/s 617.02 MiB/s]
change:
       time:   [-1.0441% -0.7751% -0.5029%] (p = 0.00 < 0.05)
       thrpt:  [+0.5055% +0.7812% +1.0552%]
       Change within noise threshold.
Found 6 outliers among 100 measurements (6.00%)
5 (5.00%) high mild
1 (1.00%) high severe
streams/walltime/1-streams/each-1000-bytes: No change in performance detected.
       time:   [547.63 µs 549.16 µs 551.00 µs]
       thrpt:  [1.7308 MiB/s 1.7366 MiB/s 1.7415 MiB/s]
change:
       time:   [-0.0496% +0.4451% +0.9465%] (p = 0.08 > 0.05)
       thrpt:  [-0.9376% -0.4431% +0.0496%]
       No change in performance detected.
Found 9 outliers among 100 measurements (9.00%)
1 (1.00%) high mild
8 (8.00%) high severe
streams/walltime/1000-streams/each-1-bytes: No change in performance detected.
       time:   [10.498 ms 10.512 ms 10.525 ms]
       thrpt:  [92.782 KiB/s 92.904 KiB/s 93.022 KiB/s]
change:
       time:   [-0.1937% +0.0076% +0.2050%] (p = 0.94 > 0.05)
       thrpt:  [-0.2046% -0.0076% +0.1940%]
       No change in performance detected.
streams/walltime/1000-streams/each-1000-bytes: Change within noise threshold.
       time:   [30.534 ms 30.568 ms 30.603 ms]
       thrpt:  [31.163 MiB/s 31.198 MiB/s 31.233 MiB/s]
change:
       time:   [-0.6189% -0.4564% -0.2878%] (p = 0.00 < 0.05)
       thrpt:  [+0.2886% +0.4585% +0.6227%]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
streams-flow-controlled/walltime/1-streams/each-4194304-bytes: Change within noise threshold.
       time:   [25.624 ms 25.658 ms 25.693 ms]
       thrpt:  [155.69 MiB/s 155.90 MiB/s 156.10 MiB/s]
change:
       time:   [-0.5754% -0.3909% -0.1980%] (p = 0.00 < 0.05)
       thrpt:  [+0.1984% +0.3924% +0.5788%]
       Change within noise threshold.
streams-flow-controlled/walltime/10-streams/each-1048576-bytes: Change within noise threshold.
       time:   [70.769 ms 70.837 ms 70.907 ms]
       thrpt:  [141.03 MiB/s 141.17 MiB/s 141.31 MiB/s]
change:
       time:   [-0.3989% -0.2392% -0.0853%] (p = 0.00 < 0.05)
       thrpt:  [+0.0853% +0.2398% +0.4005%]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
transfer/walltime/pacing-false/varying-seeds: Change within noise threshold.
       time:   [17.785 ms 17.796 ms 17.807 ms]
       thrpt:  [224.63 MiB/s 224.77 MiB/s 224.90 MiB/s]
change:
       time:   [+0.2133% +0.2927% +0.3786%] (p = 0.00 < 0.05)
       thrpt:  [-0.3772% -0.2918% -0.2129%]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
transfer/walltime/pacing-true/varying-seeds: Change within noise threshold.
       time:   [18.096 ms 18.108 ms 18.119 ms]
       thrpt:  [220.76 MiB/s 220.90 MiB/s 221.04 MiB/s]
change:
       time:   [-0.7854% -0.7073% -0.6239%] (p = 0.00 < 0.05)
       thrpt:  [+0.6278% +0.7124% +0.7916%]
       Change within noise threshold.
Found 2 outliers among 100 measurements (2.00%)
1 (1.00%) low mild
1 (1.00%) high mild
transfer/walltime/pacing-false/same-seed: Change within noise threshold.
       time:   [17.803 ms 17.815 ms 17.827 ms]
       thrpt:  [224.38 MiB/s 224.53 MiB/s 224.68 MiB/s]
change:
       time:   [-1.2925% -1.2003% -1.1105%] (p = 0.00 < 0.05)
       thrpt:  [+1.1230% +1.2148% +1.3094%]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild
transfer/walltime/pacing-true/same-seed: Change within noise threshold.
       time:   [18.052 ms 18.061 ms 18.071 ms]
       thrpt:  [221.35 MiB/s 221.47 MiB/s 221.59 MiB/s]
change:
       time:   [-1.4466% -1.3687% -1.2876%] (p = 0.00 < 0.05)
       thrpt:  [+1.3044% +1.3877% +1.4678%]
       Change within noise threshold.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) high mild

Instructions per cycle

Criterion reported no significant timing changes.

All benchmarks
Benchmark IPC before IPC after ΔIPC
streams/walltime/1000-streams/each-1000-bytes 1.98 2.00 +0.7%
transfer/walltime/pacing-true/same-seed 2.20 2.19 -0.7%
transfer/walltime/pacing-false/varying-seeds 2.21 2.20 -0.5%
streams-flow-controlled/walltime/10-streams/each-1048576-bytes 2.26 2.27 +0.5%
streams-flow-controlled/walltime/1-streams/each-4194304-bytes 2.22 2.23 +0.5%
transfer/walltime/pacing-false/same-seed 2.21 2.20 -0.4%
streams/walltime/1000-streams/each-1-bytes 2.11 2.12 +0.4%
transfer/1-conn/1-100mb-resp (aka. Download)/mtu-1504 2.05 2.06 +0.4%
streams/walltime/1-streams/each-1000-bytes 1.85 1.84 -0.3%
transfer/1-conn/10_000-parallel-1b-resp (aka. RPS)/mtu-1504 1.77 1.77 +0.3%
transfer/1-conn/1-1b-resp (aka. HPS)/mtu-1504 1.80 1.81 +0.1%
transfer/1-conn/1-100mb-req (aka. Upload)/mtu-1504 2.13 2.13 +0.1%
transfer/walltime/pacing-true/varying-seeds 2.20 2.20 -0.0%

Download data for profiler.firefox.com or download performance comparison data.

Merged via the queue into mozilla:main with commit 0426032 Sep 7, 2026
225 of 227 checks passed
mxinden-bot pushed a commit to mxinden-bot/neqo that referenced this pull request Sep 17, 2026
User-visible changes since v0.31.1:

- Update nss-rs to 0.16.1, adding NSS 3.129 support:
  mozilla#4000
- Remove HTTP/3 server push:
  mozilla#3816
- Back-pressure the outbound QUIC datagram queue:
  mozilla#3859
- Reject 0-RTT downgrade of the extended CONNECT setting:
  mozilla#3940
- Report the receiver flow-control window in Stats:
  mozilla#3978
@mxinden mxinden mentioned this pull request Sep 17, 2026
pull Bot pushed a commit to SINHASantos/neqo that referenced this pull request Sep 25, 2026
User-visible changes since v0.31.1:

- Update nss-rs to 0.16.1, adding NSS 3.129 support:
  mozilla#4000
- Remove HTTP/3 server push:
  mozilla#3816
- Back-pressure the outbound QUIC datagram queue:
  mozilla#3859
- Reject 0-RTT downgrade of the extended CONNECT setting:
  mozilla#3940
- Report the receiver flow-control window in Stats:
  mozilla#3978
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.

4 participants