Skip to content

Propagate --tcp-nodelay to the server (wire intent, no behavior change)#99

Merged
lance0 merged 1 commit into
masterfrom
tcp-nodelay-propagation
Jun 11, 2026
Merged

Propagate --tcp-nodelay to the server (wire intent, no behavior change)#99
lance0 merged 1 commit into
masterfrom
tcp-nodelay-propagation

Conversation

@lance0

@lance0 lance0 commented Jun 11, 2026

Copy link
Copy Markdown
Owner

From the roadmap surface audit — with a correction to the audit's premise discovered during implementation.

The honest finding: the server already hardcodes nodelay: true on every TCP data socket (single-port handler covers upload/download/bidir AND the legacy fallback's accepted streams; control connections have had it since the #70 fix). So --tcp-nodelay not reaching the server had no behavioral consequence today — the audit's "download/bidir silently don't get it" was wrong at the behavior level, right only at the wire level.

Why ship the propagation anyway: it puts the client's intent on the wire (TestStart.tcp_nodelay, wire-additive) so any future change to the server-side default can't silently strand -R/--bidir users who passed the flag. Applied as client_requested || SERVER_DATA_NODELAY with the default expressed as a named constant — replacing instead of OR-ing would have disabled nodelay for every client not passing the flag, regressing deliberate historical behavior. A test pins both halves (client request honored; default never regressed).

No capability added: old servers ignoring the field degrade to identical behavior (same call as window_size).

Serde roundtrip + backward-compat (absent → false) + wire-omission tests included; 297 tests green.

The flag previously configured only client-created sockets; in -R and
--bidir the server is the latency-relevant bulk sender and never heard
about it - the same one-direction asymmetry issues #81/#91 had for
accounting.

TestStart gains a wire-additive tcp_nodelay field (serde-default,
omitted when false), threaded handle_test_request -> run_test ->
spawn_tcp_stream_handlers, mirroring the zerocopy plumbing. The server
ORs the client's request into its own data-socket default via the new
server_data_nodelay helper rather than replacing it: the server has
always run its data sockets with TCP_NODELAY on (harmless for full-MSS
bulk writes, keeps the final partial segment from stalling), so the
client's flag can only add nodelay, never disable it, and the OR is
identity-true today. The explicit threading keeps the client's intent
on the wire and honored if the server-side default ever changes.

No capability is added: an old server ignoring the field already runs
with nodelay on, so the degradation is invisible and exact - the same
call window_size made. The QUIC TestStart sends false (QUIC manages
its own transport; Nagle is a TCP concept), and UDP tests send false
like zerocopy does.

The legacy dead-code multi-port handler now references the shared
SERVER_DATA_NODELAY constant so the historical default has one source
of truth.
@lance0 lance0 force-pushed the tcp-nodelay-propagation branch from 5146719 to d20cc33 Compare June 11, 2026 18:35
@lance0 lance0 merged commit 8b0b098 into master Jun 11, 2026
9 of 10 checks passed
@lance0 lance0 deleted the tcp-nodelay-propagation branch June 11, 2026 18:35
lance0 added a commit that referenced this pull request Jun 11, 2026
Connect timeout, server-side client identification, CSV bidir interval
columns, and tcp-nodelay propagation shipped; the QUIC parameter item
narrows to the remaining real fix (pacing) now that the warning half
landed.
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.

1 participant