rx.parse_abort: count the abandoned-aggregate RX loss on every generation - #387
Conversation
…tion An RX descriptor walk that hits a malformed/truncated descriptor mid-aggregate abandons every remaining frame in that bulk-IN buffer. Those frames were already admitted by the chip — and, with an ACK responder armed, already ACKed to the peer — so this loss class is post-admission: invisible to a hardware-ARQ transmitter, which counts the frames delivered and never retries. It was also invisible to us: Jaguar2/Jaguar3/Kestrel broke out of the walk silently, and Jaguar1 only warned on the diagnostic plane. One shared helper (src/RxParseAbort.h) now emits a machine event at all four sites, with normal end-of-aggregate zero padding (all-zero remainder) excluded so the event only fires on real aborts. The counter is cumulative per RX loop; absence of the event in a session means the walk never aborted. Hardware-validated on all four generations (tests/parse_abort_smoke.sh: ambient-RX per die — frames flow, zero spurious aborts on each family's aggregate padding format), plus a 3-arm ARQ e2e campaign on the 8822EU (~1.14M delivered frames incl. 685k inside A-MPDU aggregates, zero events) — so the exclusion heuristic is proven non-flooding at scale. The smoke's J3 default DUT is the 8812CU: the bench 8822EU decodes no ambient 2.4 GHz (front-end quirk, 5 GHz proven) and would fail the smoke for an unrelated reason. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR Summary by QodoEmit rx.parse_abort for abandoned RX aggregates across generations
AI Description
Diagram
High-Level Assessment
Files changed (8)
|
Code Review by Qodo
1.
|
emit_rx_parse_abort incremented the cumulative counter inside the .f() argument list, so a disabled EventSink still bumped `total` and the function still returned true — later re-enabled sessions would emit totals disagreeing with the number of events actually written. Early-exit on a disabled sink (skipping the zero-scan too) and increment only on the emission path. The docs/logging.md row also restated the header doc-comment; it now points at src/RxParseAbort.h instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
What
A machine event for a loss class that was structurally silent: when an RX descriptor walk hits a malformed/truncated descriptor mid-aggregate, it abandons every remaining frame in that bulk-IN buffer. Those frames were already admitted by the chip — and, with an ACK responder armed, already ACKed to the peer — so a hardware-ARQ transmitter counts them delivered and never retries. Jaguar2/Jaguar3/Kestrel broke out of the walk with no trace at all; Jaguar1 warned on stderr only.
One shared helper (
src/RxParseAbort.h) now emitsrx.parse_abort(off / buf_len / remaining / frame_len / drvinfo / shift / cumulative total) at all four walk sites. Normal end-of-aggregate zero padding (all-zero remainder) is excluded, so the event only fires on real aborts — no event in a session means the walk never abandoned anything. Schema indocs/logging.md.Why now
A PixelPilot field investigation (8822E pair, hardware ARQ, FEC 1/1) surfaced monitor-correlated ACK-then-drop losses. The parse-walk abort was the one remaining silent path in devourer's RX chain that could produce that signature. Instrumenting it was the falsifier.
Measured
tests/arq_e2e_delivery.sh, 8822EU DUT, ch161, retry 4, spsc-fat+backpressure, video-shaped 1400 B and aggregating 512 B loads) — ~1.14 M delivered frames, 685 k inside A-MPDU aggregates: 0 parse aborts, 0 ACKed-but-undelivered attributable to the RX chain. The adversarial pair: the A-MPDU arm's verdict line flagged au=2, but the witness ledger shows both frames aired 5× and 4× with rate fallback and were never BlockAcked — CCX false-oks under AGG_EN (the documented A-MPDU accounting collapse), not delivery loss.tests/parse_abort_smoke.sh(new; ambient-RX per generation, verdict = frames flow ∧ zero events) — 8814AU (J1), 8822BU (J2), 8812CU (J3, post-refactor walk), 35bc:0101 (Kestrel) all OK. The zero-abort result also means the event's cost on healthy links is zero emissions; the all-zero scan only runs on the walk's exit path.🤖 Generated with Claude Code