Skip to content

Commit 066f543

Browse files
ccie18643claude
andcommitted
feat(tcp): register tcp.rmem / tcp.wmem / tcp.moderate_rcvbuf sysctls (autotune step 1)
First phase of the Tier-3 buffer auto-tuning plan (docs/refactor/tcp_buffer_autotuning.md §6 / §10 step 1): register the clamp + default source the later Track R (receive DRS) and Track S (send auto-tuning) phases read. Inert registration — nothing consumes these knobs yet, so no behaviour changes. Adds to tcp__constants.py: - tcp.moderate_rcvbuf (default 1 = on, is_int_in_range 0..1) — the DRS enable gate (Linux net.ipv4.tcp_moderate_rcvbuf). - tcp.rmem.{min,default,max} and tcp.wmem.{min,default,max} triples (Linux net.ipv4.tcp_rmem / tcp_wmem), each a positive-int knob plus a min <= default <= max finalize validator. The .default entries deliberately keep PyTCP's current effective defaults (rcv 65535, snd 212992) rather than Linux's small initial values — the small-default switch that makes auto-tuning observable is a separate, behaviour-changing phase (plan §2 / §7 / §10 step 5). Only the .max clamps carry Linux-parity values (rmem 6 MiB, wmem 4 MiB). Tests-first: test__tcp__constants.py pins the registration/defaults, the 0/1 flag bounds, and both triples' cross-field finalize validators. RED pre-impl: ImportError (constants absent) → 11 green post-impl. Plan §10 step 1 marked done in lockstep. Reference: Linux net.ipv4.tcp_rmem / tcp_wmem / tcp_moderate_rcvbuf. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 81e097c commit 066f543

3 files changed

Lines changed: 384 additions & 1 deletion

File tree

docs/refactor/tcp_buffer_autotuning.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,13 @@ CLAUDE.md "Linux as tiebreaker" precedence.
451451

452452
1. **Tier-2 `tcp.rmem` / `tcp.wmem` triples** (§6) — prerequisite clamp +
453453
default source. Small, no behaviour change if defaults match today's
454-
constants; the observable switch is step 6.
454+
constants; the observable switch is step 5. **DONE** — registered
455+
`tcp.moderate_rcvbuf` (default 1) + the `tcp.rmem` / `tcp.wmem`
456+
min/default/max triples in `tcp__constants.py`, each with a
457+
per-value validator and a `min <= default <= max` finalize validator.
458+
`.default` entries keep today's effective values (rcv 65535,
459+
snd 212992); only `.max` clamps carry Linux-parity values. No runtime
460+
consumer yet. Tests: `test__tcp__constants.py`.
455461
2. **S1 + S2** (send auto-tuning) — smaller track, exercises the sysctl
456462
clamp and the ACK-path trigger with low risk (grow-only widening of an
457463
existing gate).

packages/pytcp/pytcp/protocols/tcp/tcp__constants.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,39 @@
112112
# arithmetic-friendly.
113113
TCP__TS_RECENT__OUTDATED_THRESHOLD_MS = 24 * 86_400 * 1_000
114114

115+
# TCP buffer auto-tuning bounds (Tier-3 plan
116+
# docs/refactor/tcp_buffer_autotuning.md §6). Registered now as the clamp
117+
# + default source; there is NO runtime consumer yet — Track R (receive
118+
# Dynamic Right-Sizing) and Track S (send-buffer auto-tuning) land the
119+
# readers in later phases, so this registration changes no behaviour.
120+
#
121+
# The '.default' entries deliberately keep PyTCP's current effective
122+
# defaults (rcv 65535, snd 212992) rather than Linux's small initial
123+
# values: the small-default switch that makes auto-tuning observable is a
124+
# separate, behaviour-changing phase (plan §2 / §7 / §10 step 5). Only
125+
# the '.max' clamps carry Linux-parity values today.
126+
127+
# Linux 'net.ipv4.tcp_moderate_rcvbuf' — the enable flag for
128+
# receive-buffer Dynamic Right-Sizing (Track R). Default 1 (on), matching
129+
# Linux; the DRS grow policy (R4) reads this gate.
130+
TCP__MODERATE_RCVBUF = 1
131+
132+
# Linux 'net.ipv4.tcp_rmem' (min / default / max) receive-buffer bounds.
133+
# '.max' is the DRS grow clamp (Track R4); '.default' will seed the unset
134+
# 'rcv_wnd_max' once the small-default switch lands. '.max' mirrors the
135+
# Linux ~6 MiB default ceiling; '.min' mirrors Linux's 4096 floor.
136+
TCP__RMEM__MIN = 4096
137+
TCP__RMEM__DEFAULT = 65535
138+
TCP__RMEM__MAX = 6_291_456
139+
140+
# Linux 'net.ipv4.tcp_wmem' (min / default / max) send-buffer bounds.
141+
# '.max' is the send-autotune grow clamp (Track S2); '.default' will seed
142+
# the unset send bound once the small-default switch lands. '.max' mirrors
143+
# the Linux ~4 MiB default ceiling; '.min' mirrors Linux's 4096 floor.
144+
TCP__WMEM__MIN = 4096
145+
TCP__WMEM__DEFAULT = 212992
146+
TCP__WMEM__MAX = 4_194_304
147+
115148
# Per-interface conf-plane policy storage. 'dict[str, int]' keyed by
116149
# interface name with a mandatory '"default"' template slot — the
117150
# operator addresses a specific interface ('tcp.<ifname>.<field>') or
@@ -161,6 +194,7 @@
161194

162195
from pytcp.stack.sysctl import ( # noqa: E402
163196
get,
197+
is_int_in_range,
164198
is_positive_int,
165199
register,
166200
register_finalize_validator,
@@ -357,3 +391,108 @@ def _finalize__persist_max_ge_rto_initial() -> None:
357391

358392

359393
register_finalize_validator(_finalize__persist_max_ge_rto_initial)
394+
395+
396+
# TCP buffer auto-tuning knobs (Tier-3 plan
397+
# docs/refactor/tcp_buffer_autotuning.md §6). Flat (not interface_scope)
398+
# for the first pass; no runtime consumer yet.
399+
register(
400+
key="tcp.moderate_rcvbuf",
401+
module_name=__name__,
402+
attr="TCP__MODERATE_RCVBUF",
403+
default=TCP__MODERATE_RCVBUF,
404+
validator=is_int_in_range("tcp.moderate_rcvbuf", low=0, high=1),
405+
description="Linux 'net.ipv4.tcp_moderate_rcvbuf' — enable receive-buffer DRS (0=off, 1=on).",
406+
)
407+
register(
408+
key="tcp.rmem.min",
409+
module_name=__name__,
410+
attr="TCP__RMEM__MIN",
411+
default=TCP__RMEM__MIN,
412+
validator=is_positive_int("tcp.rmem.min"),
413+
description="Linux 'net.ipv4.tcp_rmem[0]' — receive-buffer minimum in bytes.",
414+
)
415+
register(
416+
key="tcp.rmem.default",
417+
module_name=__name__,
418+
attr="TCP__RMEM__DEFAULT",
419+
default=TCP__RMEM__DEFAULT,
420+
validator=is_positive_int("tcp.rmem.default"),
421+
description="Linux 'net.ipv4.tcp_rmem[1]' — receive-buffer default (unset-rcv_wnd_max seed) in bytes.",
422+
)
423+
register(
424+
key="tcp.rmem.max",
425+
module_name=__name__,
426+
attr="TCP__RMEM__MAX",
427+
default=TCP__RMEM__MAX,
428+
validator=is_positive_int("tcp.rmem.max"),
429+
description="Linux 'net.ipv4.tcp_rmem[2]' — receive-buffer maximum (DRS grow clamp) in bytes.",
430+
)
431+
register(
432+
key="tcp.wmem.min",
433+
module_name=__name__,
434+
attr="TCP__WMEM__MIN",
435+
default=TCP__WMEM__MIN,
436+
validator=is_positive_int("tcp.wmem.min"),
437+
description="Linux 'net.ipv4.tcp_wmem[0]' — send-buffer minimum in bytes.",
438+
)
439+
register(
440+
key="tcp.wmem.default",
441+
module_name=__name__,
442+
attr="TCP__WMEM__DEFAULT",
443+
default=TCP__WMEM__DEFAULT,
444+
validator=is_positive_int("tcp.wmem.default"),
445+
description="Linux 'net.ipv4.tcp_wmem[1]' — send-buffer default (unset-SO_SNDBUF seed) in bytes.",
446+
)
447+
register(
448+
key="tcp.wmem.max",
449+
module_name=__name__,
450+
attr="TCP__WMEM__MAX",
451+
default=TCP__WMEM__MAX,
452+
validator=is_positive_int("tcp.wmem.max"),
453+
description="Linux 'net.ipv4.tcp_wmem[2]' — send-buffer maximum (send-autotune grow clamp) in bytes.",
454+
)
455+
456+
457+
def _finalize__rmem_triple_ordered() -> None:
458+
"""
459+
Cross-knob constraint — the 'tcp.rmem' triple must satisfy
460+
min <= default <= max. An inverted triple would let the DRS grow
461+
clamp ('tcp.rmem.max') sit below the seed ('tcp.rmem.default'), so
462+
the grow policy could never raise the window above the seed.
463+
"""
464+
465+
rmem_min, rmem_default, rmem_max = (
466+
get("tcp.rmem.min"),
467+
get("tcp.rmem.default"),
468+
get("tcp.rmem.max"),
469+
)
470+
if not rmem_min <= rmem_default <= rmem_max:
471+
raise ValueError(
472+
f"sysctl 'tcp.rmem' must satisfy min <= default <= max; got "
473+
f"min={rmem_min}, default={rmem_default}, max={rmem_max}.",
474+
)
475+
476+
477+
def _finalize__wmem_triple_ordered() -> None:
478+
"""
479+
Cross-knob constraint — the 'tcp.wmem' triple must satisfy
480+
min <= default <= max. An inverted triple would let the
481+
send-autotune grow clamp ('tcp.wmem.max') sit below the seed
482+
('tcp.wmem.default').
483+
"""
484+
485+
wmem_min, wmem_default, wmem_max = (
486+
get("tcp.wmem.min"),
487+
get("tcp.wmem.default"),
488+
get("tcp.wmem.max"),
489+
)
490+
if not wmem_min <= wmem_default <= wmem_max:
491+
raise ValueError(
492+
f"sysctl 'tcp.wmem' must satisfy min <= default <= max; got "
493+
f"min={wmem_min}, default={wmem_default}, max={wmem_max}.",
494+
)
495+
496+
497+
register_finalize_validator(_finalize__rmem_triple_ordered)
498+
register_finalize_validator(_finalize__wmem_triple_ordered)

0 commit comments

Comments
 (0)