joule-contrib: a retransmission of a packet not yet seen is recovered; the SRT tests count the first sends lost #510

Merged
dcharlot merged 2 commits from fix/srt-tests-first-send-losses into main 2026-10-27 12:18:43 -04:00
Owner

What

These are two fixes found while chasing an SRT ingest test that failed on #505's linux-arm64 leg (4 recoveries where it required 6).

1. A retransmission of a packet not yet seen is recovered, not a first try (live-contribution §6.1)

A receiver marked a packet as recovered only when a later arrival had shown its gap. Since #503, a sender re-sends its newest packet when its acknowledgements stall (§4.1). That probe arrives before anything shows the gap, so the SRT receiver took it, R flag set, as the next packet in order. It then counted a first try for a packet whose first send was lost. The signed link record came up short on recoveries.

Both receivers now treat an arrival flagged as a retransmission, of a sequence number not yet seen and not known to be missing, as found missing on arrival. It is counted as recovered, with a recovery time of 0 µs. The flag is SRT's R flag or RIST's retransmission SSRC. §6.1's definitions and the CHANGELOG say so.

2. The SRT tests count the first sends that were lost, instead of assuming a burst's size

Both tests drop a run of datagrams by index and required that many recoveries. Control packets (ACKACKs, keepalives) take some of those indexes as the timing falls. The lossy proxy now keeps the datagrams it drops (Counts::dropped_log, protocol-agnostic). The tests read from it the sequence numbers whose first send was lost, and require exactly that many recovered. srt_link also requires a loss run at least as long as the longest run of them.

Evidence (Framework box, x86_64 Linux; four at once pinned to two cores)

Run Result
losses_each_way_are_recovered_within_the_window 32/32
an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt 32/32
Same ingest test before the receiver fix 0/32: recovered 6–9 against more first sends lost
Falsification: receiver fix disabled 8/8 fail (7 recovered, 9 first sends lost)
Falsification: proxy records nothing srt_link fails ("the path lost first sends of data: {}")

The job's suites pass:

Suite Tests
joule-contrib --all-targets 30
joule-contrib --all-targets --features rist 43
joule-moq-ingest --all-targets 73
joule-moq-ingest --all-targets --features rist 75

The link-vector corpus is unchanged (101 files). Clippy reports nothing in the changed files. The comparative-prose, vanity, spec-refs and section-refs checks pass.

🤖 Generated with Claude Code

## What These are two fixes found while chasing an SRT ingest test that failed on #505's linux-arm64 leg (4 recoveries where it required 6). ### 1. A retransmission of a packet not yet seen is recovered, not a first try (live-contribution §6.1) A receiver marked a packet as recovered only when a later arrival had shown its gap. Since #503, a sender re-sends its newest packet when its acknowledgements stall (§4.1). That probe arrives before anything shows the gap, so the SRT receiver took it, R flag set, as the next packet in order. It then counted a first try for a packet whose first send was lost. The signed link record came up short on recoveries. Both receivers now treat an arrival flagged as a retransmission, of a sequence number not yet seen and not known to be missing, as found missing on arrival. It is counted as recovered, with a recovery time of 0 µs. The flag is SRT's R flag or RIST's retransmission SSRC. §6.1's definitions and the CHANGELOG say so. ### 2. The SRT tests count the first sends that were lost, instead of assuming a burst's size Both tests drop a run of datagrams by index and required that many recoveries. Control packets (ACKACKs, keepalives) take some of those indexes as the timing falls. The lossy proxy now keeps the datagrams it drops (`Counts::dropped_log`, protocol-agnostic). The tests read from it the sequence numbers whose first send was lost, and require exactly that many recovered. `srt_link` also requires a loss run at least as long as the longest run of them. ## Evidence (Framework box, x86_64 Linux; four at once pinned to two cores) | Run | Result | |---|---| | `losses_each_way_are_recovered_within_the_window` | 32/32 | | `an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt` | 32/32 | | Same ingest test before the receiver fix | 0/32: recovered 6–9 against more first sends lost | | Falsification: receiver fix disabled | 8/8 fail (7 recovered, 9 first sends lost) | | Falsification: proxy records nothing | `srt_link` fails ("the path lost first sends of data: {}") | The job's suites pass: | Suite | Tests | |---|---| | `joule-contrib --all-targets` | 30 | | `joule-contrib --all-targets --features rist` | 43 | | `joule-moq-ingest --all-targets` | 73 | | `joule-moq-ingest --all-targets --features rist` | 75 | The link-vector corpus is unchanged (101 files). Clippy reports nothing in the changed files. The comparative-prose, vanity, spec-refs and section-refs checks pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
an_srt_publisher_reaches_a_relay_subscriber_with_every_receipt required at
least six recoveries from a burst of six dropped datagrams, and
losses_each_way_are_recovered_within_the_window five from five. A burst
drops datagrams by index, and the control packets between data packets
(ACKACKs, keepalives) take some of those indexes as the timing falls: CI's
linux-arm64 leg saw 4 recoveries on #505 with every payload delivered and
nothing dropped.

The lossy proxy now keeps the datagrams it drops (Counts::dropped_log, the
first 4096), protocol-agnostic. The two tests read from it the sequence
numbers whose first send was lost and require exactly that many recovered,
and srt_link a loss run at least as long as the longest run of them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
joule-contrib: a retransmission of a packet not yet seen is recovered, not a first try (live-contribution §6.1)
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 16s
WAI conformance / does this change touch it (pull_request) Successful in 16s
WAI energy receipts / does this change touch it (pull_request) Successful in 19s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 8s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 44s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m1s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m48s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 5m53s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m22s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 27s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 2m57s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 7m24s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 7m27s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 19s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 33s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m18s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m56s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 11m19s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 14m42s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 4m22s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 9m8s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 19m51s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h0m11s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (pull_request) Successful in 39s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 29s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 1m12s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m37s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 11m39s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 18m16s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 10m47s
f441c8b906
A receiver marked a packet recovered only when a later arrival had shown its
gap. A sender's probe of a stalled tail (§4.1) re-sends the newest packet
before anything shows the gap, so the SRT receiver took it, R flag and all,
as the next packet in order and counted a first try for a packet whose first
send was lost. The counted recoveries came up short of the first sends the
path dropped (6-9 short-counted in 32 contended runs of the SRT ingest test).

Both receivers now treat an arrival flagged as a retransmission (SRT's R
flag, RIST's retransmission SSRC) of a sequence number not yet seen and not
known missing as found missing on arrival: recovered, with a recovery of 0
µs. §6.1 says so, and the CHANGELOG.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!510
No description provided.