router: model the channel as a continuous carrier (never drop mid-transmission) - #15
Merged
Conversation
…nsmission) The per-link audio queue was a fixed ~3 s buffered channel that dropped the oldest block on overflow. A TNC bursts a whole keyup's audio with no real-time pacing, so any transmission longer than ~3 s overran the buffer and net-sim dropped blocks *mid-transmission* — gapping the receiver's audio, collapsing its DCD / carrier sense, and making the far end key up on top of the in-progress transmission. That overlap is a collision (the mixer's MixCollision → silence), the frame is lost, and the loss triggers a go-back-N retransmit storm that overruns the buffer further. A real continuous-carrier channel has no such limit. Measured on a real LinBPQ ↔ packet-node link over the sim (a chat help-text dump = back-to-back long I-frames): the receiver decoded only ~26% of the sender's I-frames; ~36-63% of the receiver's own transmissions collided with the sender's (composite-WAV L/R overlap analysis); and the collisions began a median ~3.3 s into each transmission — i.e. exactly when the 3 s buffer saturated and started dropping. Fix: linkQueue becomes a non-dropping FIFO that grows as needed. The real-time rxFeeder still meters it out at the channel sample rate, so channel timing is unchanged, but the receiver now hears a gap-free carrier for the full transmission and its carrier sense holds. Memory is bounded in practice (a keyup is finite; the backing array is released once drained); only a pathological runaway past a 60 s safety cap ever drops, logged as the anomaly it is. After the fix, on the same link: overflow 0, 0 collisions, receiver I-frame delivery 26% → ~90%, the full help text delivered, and the go-back-N storm gone. Adds TestLinkQueueDeliversLongBurstGapFree: a ~10 s burst (far past the old 3 s cap) must be delivered FIFO and gap-free. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M0LTE
added a commit
to packet-net/packet.net
that referenced
this pull request
Jun 6, 2026
…ssion audio drops) (#324) net-sim's per-link audio queue dropped blocks mid-transmission on any burst longer than its ~3 s buffer, which gapped the receiver's audio, collapsed its carrier sense, and made stations transmit over each other — silently degrading interop scenarios with back-to-back long frames (NET/ROM NODES bursts, chat help dumps, etc.). Fixed in packet-net/net-sim#15 with a non-dropping continuous-carrier FIFO; this bumps the interop stack's pinned digest to pick it up. Validated on the lab against a real LinBPQ link: overflow 2876 -> 0, collisions 36-63% -> 0%, long-frame delivery 26% -> ~90%. [skip-plan] Co-authored-by: Tom M0LTE <tom@fann.ing> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
M0LTE
added a commit
to packet-net/packet.net
that referenced
this pull request
Jun 12, 2026
Both test stacks pinned net-sim 0fb89608 (the 2026-06-06 continuous-carrier build, packet-net/net-sim#15) — which predates ACKMODE entirely. Bump to the v0.2.0 release: ACKMODE end-to-end with the echo delivered at PTT release (not render time) + the tq lost-wakeup fix reconciled, plus time_scale / collision-noise / squelch_open_ms / rt-priority. Forward-compatible — 0.2.0 carries the continuous-carrier fix and the new modes default to the prior behaviour (collision silence, squelch 0, time_scale 1), so plain-KISS interop is unchanged; the interop suite validates in CI. [skip-plan] Co-Authored-By: Claude Fable 5 <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.
Problem
The per-link audio queue (
internal/router/router.golinkQueue) was a fixed ~3 s buffered channel that dropped the oldest block on overflow. A TNC bursts a whole keyup's worth of audio with no real-time pacing, so any transmission longer than ~3 s overran the buffer and net-sim dropped blocks mid-transmission.Dropping mid-transmission gaps the receiver's audio, which collapses its DCD / carrier sense — so the far end thinks the channel is idle and keys up on top of the in-progress transmission. That overlap is a collision (the mixer's
MixCollision→ silence), the frame is lost, and the loss kicks off a go-back-N retransmit storm that overruns the buffer further. A real continuous-carrier channel has no such limit.Evidence
Measured on a real LinBPQ ↔ packet-radio-node link over the sim, driving a chat help-text dump (back-to-back long I-frames):
samoyedanddirewolfbackends, so it's the shared layer (net-sim), not the modem.Fix
Model the channel as a continuous carrier:
linkQueuebecomes a non-dropping FIFO that grows as needed. The real-timerxFeederstill meters it out at the channel sample rate, so channel timing is unchanged — but the receiver now hears a gap-free carrier for the full transmission and its carrier sense holds. Memory is bounded in practice (a keyup is finite; the backing array is released once drained); only a pathological runaway past a 60 s safety cap ever drops, logged as the anomaly it is.Result
Same link, after the fix:
The go-back-N storm disappears (the sender stops retransmitting). Existing
TestCompositeRealTimePacing/TestCompositeConcurrentFeedstill pass (metering unchanged); addsTestLinkQueueDeliversLongBurstGapFree— a ~10 s burst (well past the old 3 s cap) must be delivered FIFO and gap-free.🤖 Generated with Claude Code