Skip to content

feat(network): guard-band-aware 802.1Qbv GCL splitting (REQ-TSN-SYNTH-QBV-GUARDBAND-001)#309

Merged
avrabe merged 1 commit into
mainfrom
feat/qbv-guardband
Jun 27, 2026
Merged

feat(network): guard-band-aware 802.1Qbv GCL splitting (REQ-TSN-SYNTH-QBV-GUARDBAND-001)#309
avrabe merged 1 commit into
mainfrom
feat/qbv-guardband

Conversation

@avrabe

@avrabe avrabe commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

What

synthesize_gcl_split_guarded — the deployment-sound window-splitting 802.1Qbv GCL synthesizer. It charges the IEEE 802.1Q §8.6.8.4 transmission-overrun guard band that the guard-free synthesize_gcl_split (v0.21) ignores, so the synthesizer's "meets deadline" claim becomes a real-hardware claim and the emitted GateSchedule physically carries the guards a switch enforces.

How it stays sound

  • Service is unchanged; only packing tightens. Each class's usable open window is sized by the same validated single-window search the guard-free path uses — the guard doesn't change the service a class receives (open w, latency cycle/K − w), only the budget Σwᵢ + N·g ≤ cycle/K. So the per-round synthesize_gcl is reused unchanged.
  • Non-circular model anchor (the go/no-go). guard_band_k1_equals_sync_error_at_eps_g pins the construction: for a single window, "emit a (D−g)-open window + trailing g guard" yields a service curve byte-identical to the independently-derived tas_residual_service_with_sync_error at ε = g (open D−g, latency C−D+g, rate R·(D−g)/C) — two derivations from different premises agreeing.
  • The rate-loss cliff is enforced. Guards grow as N·K·g while the latency benefit shrinks as 1/K; when no split fits, the oracle returns the structured GuardOversubscribed, never a silently rate-starved GCL.
  • g rounds up to a whole ns (sound direction); g = 0 reproduces synthesize_gcl_split byte-for-byte; the full guarded schedule self-certifies through tas_residual_service + delay_bound before return.

Scope

Library API. Like the whole synthesize_gcl* family it is not yet wired into a CLI / AADL→Qbv consumer — this REQ makes no end-to-end pipeline claim; the "deployable" claim is about the GCL it produces. Consumer wiring is separate future work.

Traceability

  • REQ-TSN-SYNTH-QBV-GUARDBAND-001implemented
  • TEST-TSN-GUARDBAND (satisfies) — 8 unit tests

Verification

  • 156 spar-network lib tests pass; clippy -D warnings clean; nightly fmt clean.
  • Mutation (cargo-mutants, guarded fn + error path): 39 caught / 1 unviable / 1 missed. The 1 missed is the defensive self-cert deadline arm — an equivalent mutant the budget invariant guarantees never trips, matching the identical surviving mutant in the shipped synthesize_gcl / synthesize_gcl_split (precedent: unreachable defensive error arms).

🤖 Generated with Claude Code

…-QBV-GUARDBAND-001)

synthesize_gcl_split_guarded makes the window-splitting GCL synthesizer
DEPLOYMENT-SOUND: it charges the IEEE 802.1Q §8.6.8.4 transmission-overrun
guard band that the guard-free synthesize_gcl_split ignores. Each class's
usable open window is sized by the same validated single-window search (the
guard does not change the service a class receives — open w, latency
cycle/K − w — only the packing budget Σwᵢ + N·g ≤ cycle/K), then an explicit
trailing closed guard window of g is emitted after every class window so the
deployed GateSchedule physically carries the guards a switch enforces.

The guard-band rate-loss cliff (guards grow as N·K·g while the latency
benefit shrinks as 1/K) is enforced automatically: when no split fits, the
oracle returns the structured GuardOversubscribed rather than a silently
rate-starved, unsound GCL.

Model soundness is pinned NON-CIRCULARLY by a K=1 anchor test: "emit a
(D−g)-open window + trailing g guard" is proven algebraically identical to
the independently-derived tas_residual_service_with_sync_error at ε = g
(open D−g, latency C−D+g, rate R·(D−g)/C from two different premises). g
rounds UP to a whole ns (sound direction); g = 0 reproduces
synthesize_gcl_split byte-for-byte.

No new dependency (existing tsn.rs + curves.rs). Library API — like the
whole synthesize_gcl* family it is not yet wired into a CLI/AADL→Qbv
consumer; this REQ makes no end-to-end pipeline claim.

Tests: 8 new (K=1 model anchor, g=0 degeneracy, feasible-split-with-guards,
sub-ns round-up, the GuardOversubscribed cliff with required_ps assertion,
exact-fit boundary, never-coarser-than-unguarded, input validation).
156 lib tests pass; clippy -D clean; nightly fmt clean; mutation 39 caught /
1 unviable / 1 missed (the defensive self-cert deadline arm — equivalent
mutant matching shipped synthesize_gcl / synthesize_gcl_split precedent).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@avrabe avrabe enabled auto-merge (squash) June 27, 2026 08:43
@github-actions

Copy link
Copy Markdown

Rivet verification gate

20/20 passed

count
Passed 20
Failed 0
Skipped (no steps) 0

Filter: (and (= type "feature") (or (has-tag "v093") (has-tag "v0100")))

Failed artifacts

(none)

Updated automatically by tools/post_verification_comment.py. Source of truth: artifacts/verification.yaml.

@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.78723% with 24 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/spar-network/src/tsn.rs 89.78% 24 Missing ⚠️

📢 Thoughts on this report? Let us know!

@avrabe avrabe merged commit 3fe75c9 into main Jun 27, 2026
18 checks passed
@avrabe avrabe deleted the feat/qbv-guardband branch June 27, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant