feat(trace-topology): Rust trace-fixture generator (netns + TSN, v0.11.0)#233
Merged
Conversation
…1.0) First PR of v0.11.0. A Rust binary — `gen-fixtures`, in the spar-trace-topology crate — that produces the four runtime artefacts the reconciliation engine will test against, from a synthetic 3-node TSN topology (grandmaster / switch / endpoint) built in Linux network namespaces. Why Rust, not a shell script: - typed config and `Result` error propagation with context on every fallible step; - `NetnsGuard` RAII — `Drop` runs `ip netns del`, so a panic or `?`-propagated error still tears the topology down. A shell `trap` silently no-ops on a crash and leaves stale `/run/netns` handles; - the two transform steps are pure, unit-tested functions. What it generates: - PCAPNG L2 capture (tcpdump on the GM veth); - LLDP neighbour JSON (lldpd -H 0 + lldpctl -f json); - Qcc YANG switch-config JSON — `tc taprio`/`cbs` read via `tc -j qdisc show` and transformed to the shape QccYangSwitchConfigSource ingests. veths are created multi-queue (numtxqueues/numrxqueues 4) because `sch_taprio` rejects single-queue devices; software mode (flags 0x0); - gPTP sync-error JSON — ptp4l + pmc, with `timestamp_ns` replaced by a deterministic synthetic counter (fixed epoch + step) so fixture diffs aren't noisy; `sync_error_ns` (abs master offset) is kept as observed. Qci stream-filters have no Linux kernel equivalent — they are synthesised from a static topology config and documented as such in the code. 9 transformer unit tests (tc->Qcc, pmc->gPTP, LLDP validation) run on any host with no netns dependency; all generated JSON round-trips through the ingest.rs parsers. The CI harness that runs the netns-touching path — a KVM guest, per the smithy QEMU enablement — lands in a follow-up PR. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rivet verification gate✅ 20/20 passed
Filter: Failed artifacts(none) Updated automatically by |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
avrabe
added a commit
that referenced
this pull request
May 26, 2026
Workspace bump from 0.10.0 → 0.11.0 across all 22 spar crates (via
[workspace.package].version), plus the VS Code extension's
package.json — the two version surfaces the release workflow's
check-versions job compares against the tag.
What v0.11.0 ships, since v0.10.0:
trace-topology reconciliation engine (incremental rollout):
#239 IdentityUnknown check (PR 3a — component-borne MAC + chassis-id)
#241 GptpOutOfBudget check (PR 3b — single-budget case)
trace-topology fixture pipeline:
#233 Rust gen-fixtures tool (netns + TSN, RAII teardown)
#234 NixOS guest + QEMU harness for fixture generation
#238 corrected nixos/nix container digest (fd7a5c67…, multi-arch index)
#240 podman runner label so workflows schedule on the only
rootless-podman-capable runner in the fleet (runner9)
codegen:
#232 --format wit emits only WIT (strict-filter; no Rust/Bazel
workspace leakage)
#242 per-category file-count summary + hint when WIT was
requested but the model has no `process` subcomponents
(in-flight at bump time; auto-merge armed)
release flow:
#244 standardise on the synth reference — actions/attest-build-
provenance@v2 + sigstore cosign sign-blob (v2.4.1) over
SHA256SUMS.txt, build-env.txt; the v0.11.0 release is the
first one to exercise the standardised cosign + SLSA chain.
Verification after release:
cosign verify-blob \\
--certificate-identity-regexp \\
'https://github.com/pulseengine/spar/.github/workflows/release.yml@.*' \\
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \\
--bundle SHA256SUMS.txt.cosign.bundle SHA256SUMS.txt
gh attestation verify spar-v0.11.0-<triple>.tar.gz --repo pulseengine/spar
Co-authored-by: Claude Opus 4.7 <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.
Summary
v0.11.0 PR 1. A Rust binary —
gen-fixtures, in thespar-trace-topologycrate — that produces the four runtime artefacts the reconciliation engine will test against, from a synthetic 3-node TSN topology (grandmaster / switch / endpoint) built in Linux network namespaces.Why Rust, not a shell script
The maintainer's standing preference — and it earns its keep here:
Resulterror propagation with context on every fallible step.NetnsGuardRAII —Droprunsip netns del, so a panic or?-propagated error still tears the topology down. A shelltrapsilently no-ops on a crash and leaves stale/run/netnshandles for the next run to collide with.What it generates
capture.pcapngtcpdumpon the GM vethlldp.jsonlldpd -H 0+lldpctl -f jsonqcc-yang.jsontc taprio/cbs→tc -j qdisc show→ transformed to theQccYangSwitchConfigSourceshapegptp.jsonptp4l+pmc→ transformed to theGptpJsonPtpTimeSourceshapeTwo gotchas baked in from smithy's live testing: veths are created multi-queue (
numtxqueues/numrxqueues 4) becausesch_tapriorejects single-queue devices; taprio runs in software mode (flags 0x0) — no TSN NIC.gPTP
timestamp_nsis replaced by a deterministic synthetic counter (fixed epoch + step) so fixture diffs aren't noisy;sync_error_ns(abs master offset) is kept as observed. Qcistream-filtershave no Linux kernel equivalent — synthesised from a static config, documented as such in the code.Scope
Tool only. The 9 transformer unit tests run on any host (no netns dependency) and every generated JSON round-trips through the
ingest.rsparsers. The CI harness that runs the netns-touching path is deliberately a follow-up: per the smithy QEMU enablement it'll be a KVM guest, not thenetnsrunner — building that workflow now would be rework.Test plan
cargo build -p spar-trace-topology --binscleancargo test -p spar-trace-topology— 34 tests pass (9 new transformer tests)cargo clippy -p spar-trace-topology --all-targets -- -D warningscleancargo fmt --checkcleanrivet validatePASSCo-Authored-By: Claude Opus 4.7 noreply@anthropic.com