Skip to content

feat: forward-port per-source RX demux (v0.7.3) onto 0.8.0#137

Closed
JustinKovacich wants to merge 2 commits into
feat/port_publish_raw_event_to_onto_0_8_0from
feat/port_per_source_e2e_onto_0_8_0
Closed

feat: forward-port per-source RX demux (v0.7.3) onto 0.8.0#137
JustinKovacich wants to merge 2 commits into
feat/port_publish_raw_event_to_onto_0_8_0from
feat/port_per_source_e2e_onto_0_8_0

Conversation

@JustinKovacich

Copy link
Copy Markdown
Contributor

Forward-ports the two v0.7.3 feature commits (cb6e3bd, 662662b) onto the 0.8.0 spine, so the 0.8.0 release doesn't regress per-source RX demux. The 0.7.3 release itself lives only on the release/0.7.2 line (PR #136); this is its 0.8.0 equivalent, the sibling of #135 (which forward-ported 0.7.2).

Stacked on #135. Base is feat/port_publish_raw_event_to_onto_0_8_0; the chore: release v0.7.3 commit is intentionally dropped.

What

  1. ClientUpdate::Unicast now carries source: SocketAddr. The source was already received on ReceivedMessage.source but dropped via .. before forwarding. On a shared subnet the SOME/IP header has no instance id, so the source address is the only demux key. (Clean cherry-pick modulo the sendsend_now rename from Reduce async state and static pool memory in simple_someip to prevent Embassy arena exhaustion #125.)

  2. RX E2E counter state is keyed per (source, key). E2ERegistry splits into endpoint-agnostic profile config + per-(source, key) receive state + per-key transmit state. check() now takes the source IP; protect() is unchanged (fan-out keeps one TX counter; per-recipient TX lives a layer up). A rebooted source's receive state is reset.

Forward-port adaptation (differs materially from the 0.7.3 diff)

The 0.7.3 commit assumed std::HashMap and a free process_discovery(&Arc<Mutex<E2ERegistry>>, …) function. Neither exists on the 0.8.0 spine, so the port was re-authored against the post-#18/#125 surface:

  • Registry is heapless::FnvIndexMap, not HashMap. All three maps are fixed-capacity and const-constructible (no_std, heap-free). Profile/TX bounded by E2E_REGISTRY_CAP; RX bounded by a new E2E_RX_STATE_CAP (64).
  • E2ERegistryHandle gained source on check + a new reset_source, propagated through all three impls (Arc<Mutex>, StaticE2EHandle, NullE2ERegistry).
  • Reboot reset is inline, at the run loop's existing if rebooted site (inner.rs), via the R: E2ERegistryHandle handle — there is no process_discovery to thread a registry through on this spine.
  • Dropped: the unicast-SD discovery-domain arm. 662662b also added a second SD receive arm (discovery_unicast_socket / TransportKind::Unicast); that infrastructure isn't on the 0.8.0 spine and is outside the per-source-E2E feature. Not ported here.

Design decision worth a look — RX saturation policy

rx_states is bounded (E2E_RX_STATE_CAP = 64), unlike the original unbounded HashMap. When full, a brand-new (source, key) can't claim a slot, so check() falls back to a transient per-call counter: CRC is still validated, only sequence continuity is untracked for that source until a slot frees (reset_source / unregister). A one-shot warn! fires the first time (mirrors the session.rs saturation latch). Sizing and this policy are the two things to sanity-check for the target subnet.

Verification

  • cargo clippy --workspace --all-features -- -D warnings -D clippy::pedantic
  • cargo clippy --no-default-features --features client,bare_metal (and server,bare_metal, client,server,bare_metal) pedantic ✅
  • cargo build --target thumbv7em-none-eabihf --no-default-features --features client,bare_metal
  • no_alloc_witness (StaticE2EHandle check/protect) — still zero heap alloc on the per-source path ✅
  • registry unit tests (incl. new distinct_sources_have_independent_e2e_state, reset_source_clears_only_that_source) ✅
  • client_server + bare_metal_e2e + doctests ✅ (client_server passes single-threaded; the parallel run hits the known pre-existing fixture-collision flake)

🤖 Generated with Claude Code

The SOME/IP unicast header carries no instance id, so on a shared subnet
the sender's source address is the only way to attribute an event to a
device. The source was already received (ReceivedMessage.source) but
dropped before forwarding; carry it on ClientUpdate::Unicast instead.
@JustinKovacich
JustinKovacich force-pushed the feat/port_publish_raw_event_to_onto_0_8_0 branch from 385f44c to a683029 Compare June 26, 2026 03:02
@JustinKovacich
JustinKovacich force-pushed the feat/port_per_source_e2e_onto_0_8_0 branch from fee01d1 to 2788e95 Compare June 26, 2026 03:02
@JustinKovacich
JustinKovacich changed the base branch from feat/port_publish_raw_event_to_onto_0_8_0 to main June 26, 2026 03:06
On a shared subnet, several devices send the same (service, method)
under one fixed instance id; a single per-key receive counter collides
their interleaved sequences into spurious WrongSequence. Split the
registry into endpoint-agnostic profile config, per-(source,key) receive
state, and per-key transmit state. check() now takes the source address;
protect() is unchanged. Reset a source's receive state on its reboot.
@JustinKovacich
JustinKovacich force-pushed the feat/port_per_source_e2e_onto_0_8_0 branch from 2788e95 to 4b1d095 Compare June 26, 2026 08:58
Copilot AI review requested due to automatic review settings June 26, 2026 08:58
@JustinKovacich
JustinKovacich changed the base branch from main to feat/port_publish_raw_event_to_onto_0_8_0 June 26, 2026 09:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Forward-ports the per-source RX demux work onto the 0.8.0 codebase by preserving sender identity on unicast updates and keying E2E receive state per source, while also expanding the crate’s no_std/bare-metal tooling, transport surface, and examples to support/verify these paths across targets.

Changes:

  • Preserve unicast sender identity by adding source: SocketAddr to ClientUpdate::Unicast and forwarding it from the client run loop.
  • Key E2E RX counter state per (source, key) with bounded receive-state storage and a reset_source hook for sender reboots.
  • Broaden bare-metal/no_std support & verification (buffer pools, callback transport/mailbox runtime pieces, embassy-net adapter crate, probes, docs/tests).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tools/size_probe/Cargo.toml Adds standalone no_std staticlib probe manifest for size/type-layout measurement.
tools/size_probe/Cargo.lock Locks probe dependencies for repeatable measurement builds.
tools/capture_type_sizes.sh Script to capture -Zprint-type-sizes for host/thumb and summarize results.
tests/no_alloc_server_witness.rs Adds no-alloc witness for server-side static subscription handle hot paths.
tests/data/vsomeip-offerer/subscriber.json Adds vsomeip subscriber config for TX-direction SD conformance testing.
tests/data/vsomeip-offerer/subscriber.cpp Adds vsomeip subscriber binary used by SD compatibility tests.
tests/data/vsomeip-offerer/README.md Documents building/running the vsomeip conformance Docker image and tests.
tests/data/vsomeip-offerer/offerer.json Updates vsomeip offerer config (multicast group alignment commentary).
tests/data/vsomeip-offerer/offerer.cpp Updates/minimizes offerer implementation and logs for test scraping.
tests/data/vsomeip-offerer/entrypoint.sh Adds entrypoint templating logic for vsomeip role configs.
tests/data/vsomeip-offerer/Dockerfile Builds pinned vsomeip + offerer/subscriber binaries for conformance testing.
tests/data/vsomeip-offerer/CMakeLists.txt Builds both vsomeip helper binaries against installed vsomeip3.
tests/buffer_pool.rs Adds tests for the new fixed-capacity BufferPool claim/release behavior.
tests/bare_metal_example_builds.rs Canary test documenting that bare-metal example crates must compile.
tests/bare_metal_client.rs Witness test for constructing/running client without client-tokio using static channels.
tests/bare_metal_client_local.rs Witness test for local-spawner client construction (new_with_deps_local).
src/traits.rs Makes SD helpers more no_std-friendly (visitor APIs, core net types, default no-op hook).
src/server/service_info.rs Gates std-only service/event-group info types; uses core::net where possible.
src/server/README.md Updates server docs for the new announcement loop spawning API and subscription APIs.
src/server/error.rs Expands server error taxonomy (Transport/Capacity/InvalidUsage) with cfg(std) IO.
src/raw_payload.rs Switches SD endpoint/service extraction to visitor pattern for no_std compatibility.
src/protocol/sd/test_support.rs Aligns test payload SD header construction with core types and new trait surface.
src/protocol/sd/options.rs Minor doc fix to avoid broken intra-doc link formatting.
src/protocol/sd/header.rs Minor numeric literal formatting cleanup in tests.
src/protocol/message_type.rs Fixes wire encoding for message type field (Response/Error bytes) + regression test.
src/protocol/message_id.rs Moves/adds Debug impl for MessageId (formatting consistency noted in review).
src/protocol/header.rs Adds upper_header_bytes() accessor and restores WireFormat impl placement.
src/protocol/byte_order.rs Adds clippy allow for float cmp in byte-level roundtrip tests.
src/log.rs Introduces internal logging shim to avoid tracing/alloc requirements on some no_std targets.
src/heapless_payload.rs Adds alloc-free PayloadWireFormat implementation for bare-metal payload handling.
src/e2e/mod.rs Makes registry/state available beyond std and re-exports registry constants/types.
src/e2e/e2e_protector.rs Formatting-only test constant literal updates.
src/e2e/e2e_checker.rs Routes warnings through logging shim; formatting-only test updates.
src/e2e/crc.rs Routes traces through logging shim; formatting-only test updates.
src/client/session.rs Replaces HashMap with bounded FnvIndexMap for session tracking; saturation behavior docs/tests.
src/client/service_registry.rs Makes service registry heap-free via FnvIndexMap, adds capacity error path + tests.
src/client/error.rs Refines client error taxonomy (Capacity/Transport/Shutdown) and adds display regression tests.
src/client/bind_dispatch.rs Adds spawner-agnostic bind+spawn abstraction shared by Send and !Send client constructions.
src/buffer_pool.rs Adds fixed-capacity buffer pool with RAII leases for no-alloc socket loops.
src/bare_metal_runtime/transport.rs Adds callback-driven transport/timer implementations for bare-metal runtime integration.
src/bare_metal_runtime/mod.rs Adds bare-metal runtime module surface exports and feature-gated runtime glue.
src/bare_metal_runtime/mailbox.rs Adds shared RX mailbox for callback transport (bounded slots/capacity) + tests.
simple-someip-embassy-net/src/socket.rs Adds embassy-net TransportSocket adapter with named futures for zero-alloc send/recv.
simple-someip-embassy-net/src/lib.rs New no_std adapter crate surface and MTU guidance.
simple-someip-embassy-net/README.md Documents adapter usage and status.
simple-someip-embassy-net/Cargo.toml Adds new adapter crate manifest with pinned embassy-net deps and host test deps.
README.md Updates crate README for 0.8 feature split, transport traits, and run-loop spawning requirements.
examples/embassy_net_client/Cargo.toml Adds host example wiring simple-someip through the embassy-net adapter.
examples/discovery_client/src/main.rs Updates example to spawn the client run-loop future returned by Client::new.
examples/discovery_client/Cargo.toml Updates example to depend on client-tokio (constructor availability).
examples/client_server/src/main.rs Updates hybrid example to new SD announcement loop API and server config shape.
examples/client_server/Cargo.toml Updates example to client-tokio/server-tokio features.
examples/bare_metal_server/src/main.rs Adds host-side example for no-tokio bare-metal server construction/run.
examples/bare_metal_server/Cargo.toml Adds bare-metal server example manifest with appropriate feature pins.
examples/bare_metal_client/Cargo.toml Adds bare-metal client example manifest with appropriate feature pins.
docs/simple_someip/plans/2026-06-17-pr126-polled-port-handoff.md Adds planning/handoff notes for future polled bare-metal port work.
docs/simple_someip/plans/2026-06-10-pr1-124-followups-design.md Adds design doc covering callback shape, docs, tests, and error-handling decisions.
Cargo.toml Expands workspace members, adds feature split (*-tokio), adds bare-metal runtime deps, excludes probe.
.gitignore Updates ignore list for probe targets and generated Claude artifacts.
.config/nextest.toml Adds nextest serialization groups to prevent static pool exhaustion in parallel runs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@JustinKovacich
JustinKovacich changed the base branch from feat/port_publish_raw_event_to_onto_0_8_0 to main June 26, 2026 12:26
@JustinKovacich
JustinKovacich changed the base branch from main to feat/port_publish_raw_event_to_onto_0_8_0 June 26, 2026 12:26
@JustinKovacich

Copy link
Copy Markdown
Contributor Author

Folded into #138. The 0.8.0 forward-port stack was consolidated via a linear rebase of the whole stack onto main (which now includes #130). #138 is rebased onto main and carries this branch's commits intact — closing here to collapse the stack into a single PR. Verified: 556 all-features lib tests, client_server 11/11, all 5 CI clippy lanes, no_alloc_witness, bare_metal_e2e 9/9.

JustinKovacich added a commit that referenced this pull request Jun 26, 2026
…solidated branch

CI gates that never ran on the spine (gated behind the failing Format &
Lint job) surfaced once the branch was rebased onto main:

- protocol/message_id: `{:#02X}` → `{:#06X}`. Under the `0x` alternate
  flag the width-2 spec has no effect (latest-nightly
  clippy::unused_format_specs); u16 IDs want 4 hex digits.
- buffer_pool: add `;` to the multi-line `const { assert!(..) }`
  (clippy::semicolon_if_nothing_returned, exposed once rustfmt reflowed
  the one-liner).
- e2e: export `E2E_RX_STATE_CAP` alongside its sibling `E2E_REGISTRY_CAP`
  (a #137 forward-port oversight — `E2ERegistry`'s public docs link it).
- docs: demote intra-doc links whose targets are private or
  feature-gated to code spans — `SUBSCRIBERS_PER_GROUP` (pub(crate)),
  `API_SCRATCH_CAP` (private), and `publish_raw_event_to` (`_alloc`-only,
  unresolved in no-alloc doc builds).
- rustfmt over the branch under rustfmt 1.9.

Verified green: fmt --check; all 5 clippy lanes (incl. nightly
bare-metal-runtime); all 5 doc lanes (-D warnings); 556 all-features lib
tests; client_server 11/11 (single-threaded); no_alloc_witness;
bare_metal_e2e 9/9; thumbv7em + build-std=core bare_metal builds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
JustinKovacich added a commit that referenced this pull request Jun 27, 2026
…solidated branch

CI gates that never ran on the spine (gated behind the failing Format &
Lint job) surfaced once the branch was rebased onto main:

- protocol/message_id: `{:#02X}` → `{:#06X}`. Under the `0x` alternate
  flag the width-2 spec has no effect (latest-nightly
  clippy::unused_format_specs); u16 IDs want 4 hex digits.
- buffer_pool: add `;` to the multi-line `const { assert!(..) }`
  (clippy::semicolon_if_nothing_returned, exposed once rustfmt reflowed
  the one-liner).
- e2e: export `E2E_RX_STATE_CAP` alongside its sibling `E2E_REGISTRY_CAP`
  (a #137 forward-port oversight — `E2ERegistry`'s public docs link it).
- docs: demote intra-doc links whose targets are private or
  feature-gated to code spans — `SUBSCRIBERS_PER_GROUP` (pub(crate)),
  `API_SCRATCH_CAP` (private), and `publish_raw_event_to` (`_alloc`-only,
  unresolved in no-alloc doc builds).
- rustfmt over the branch under rustfmt 1.9.

Verified green: fmt --check; all 5 clippy lanes (incl. nightly
bare-metal-runtime); all 5 doc lanes (-D warnings); 556 all-features lib
tests; client_server 11/11 (single-threaded); no_alloc_witness;
bare_metal_e2e 9/9; thumbv7em + build-std=core bare_metal builds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JustinKovacich
JustinKovacich deleted the feat/port_per_source_e2e_onto_0_8_0 branch June 29, 2026 20:40
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.

2 participants