M0: measured feasibility contracts — DL guard, dynamic beacon grants, ACK/TxReport matrix, per-UE RX attribution (closes #261)#286
Merged
Conversation
…ants, ACK/TxReport matrix, per-UE RX attribution (#261) Contract 1 — DL departure (docs/dl-departure.md): TD tag v2 adds host_ns (steady_clock at the send_packet call) so the witness fit measures the host-submit->air quantity directly; txegress_analyze.py gains tail percentiles + a machine txeg.verdict; dl_departure_matrix.sh sweeps TX over J1/J2/J3 USB + 8821CE PCIe against a fixed witness. Measured: transport floor 11-26 us on every transport, but the p99.9 tail is 1-3 ms channel deferral everywhere -> fine sub-ms DL slots refuted; M1 schedules submission-ahead with the measured guard. Contract 2 — dynamic grant delivery (docs/beacon-grant.md): new IRtlDevice::UpdateBeaconPayload (in-place content swap for an active beacon, riding the steer re-download; ~20 lines/gen) and StopBeacon (the chip beacons autonomously after process death — bench-bitten). Measured GO on all three generations: 30/30 updates aired per gen, zero excess skips, zero torn frames (CRC-versioned vendor IE probe), update->air latency TBTT-quantized (p50 40-72 ms at 100 TU). Static-grant fallback not needed. Contract 3 — unicast ACK + TxReport matrix (docs/ack-txreport.md): ack_txreport_matrix.sh sweeps on/retarget/off phases per TX generation against a SetAckResponder peer, with report coverage via tx.stats + SW_DEFINE tag gaps. J1/J3 TX perfect (100% ACK, retries ~0.2, arbitrary-MAC retarget, no-ACK visible per frame); J2 8812BU TX marginal (12-91% run-to-run) — recorded open. Responders: 8814AU best, 8812AU degraded, 8821AU never closes the loop. txdemo now emits a final tx.stats tally. Contract 4 — per-UE RX attribution (docs/ue-rx-attribution.md): src/cell/UeRxAttribution.h — TA-keyed windowed accumulator (drain-snapshot, RxQualityAccumulator conventions, bounded with eviction accounting), the seed of M1's UeRegistry; headless selftest in ctest + on-air two-TX check (frame ratio 4.0 exactly matching the 4x cadence split). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the 5G-NR RAN EPIC #254. Closes #261. Unblocks M1 (#255).
M0 turns the epic's four unmeasured scheduled-MAC assumptions into measured contracts — a docs note with bench distributions and an explicit go/no-go per contract, plus the two small radio-core primitives the measurements proved userspace can't do.
Contract 1 — Deterministic DL departure (
docs/dl-departure.md)examples/tdma/tdma.h, version-gated, v1 stays parseable): addshost_ns— steady_clock stamped immediately beforesend_packet— so the witness fit measures the host-submit→air quantity a slot scheduler actually controls.tests/txegress_analyze.py: tail percentiles (guard is a tail contract, not RMS) + machinetxeg.verdictline;tests/dl_departure_tx.cpp(any USB adapter) + updatedtests/pcie_txegress_tx.cpp;tests/dl_departure_matrix.shsweeps J1/J2/J3 USB + 8821CE PCIe (remote vfio bind/run/restore) against a fixed witness.Contract 2 — Dynamic grant delivery (
docs/beacon-grant.md)IRtlDevice::UpdateBeaconPayload— in-place content swap for an active beacon (interval/TBTT/port identity untouched), riding the existing steer re-download per generation (~20 lines each).IRtlDevice::StopBeacon— the chip beacons autonomously after process death; a killed probe's stale beacon contaminated the next test's witness (bench-bitten), so any beaconing session needs a stop primitive. M1's DU needs it anyway.tsfland separates update-caused skips from background witness loss (--selftestcovered).Contract 3 — Unicast ACK + TxReport capability matrix (
docs/ack-txreport.md)tests/ack_txreport_matrix.sh: per TX generation, phases on / retarget (responder re-armed to a different unicast MAC) / off against aSetAckResponderpeer;tests/ack_txreport_analyze.pycomputes ACK rate, retry distribution and report coverage (tx.stats.submitteddenominator + HalMAC SW_DEFINE tag-gap counting).DEVOURER_TX_WITH_RX=thread— measured: J1/J2 TX-only sessions get zero CCX reports (C2H needs the RX loop; only J3 drains it off its coex runtime). txdemo now emits a finaltx.statstally so short runs report their true sent count.Contract 4 — Per-UE RX attribution (
docs/ue-rx-attribution.md)src/cell/UeRxAttribution.h— the epic's firstsrc/cell/file, seed of M1'sUeRegistry: TA-keyed windowed accumulator withRxQualityAccumulatorfolding conventions, drain-snapshot delta semantics, bounded table with eviction accounting; pure caller-side logic,GetRxQualitystays device-wide.ue_rx_attribution_derive) +tests/ue_rx_probe.cpp(per-UEue.rxJSONL) + on-air two-TX check.Validation
ctest: 20/20 (new: TD v2 round-trip cases,ue_rx_attribution_derive; Python analyzers each carry a--selftest).tests/dl_departure_matrix.sh(4 transports incl. PCIe on the remote rig),tests/beacon_update_check.sh(3 generations),tests/ack_txreport_matrix.sh(9 cells),tests/ue_rx_attribution_check.sh— all runs behind the docs tables.🤖 Generated with Claude Code