Skip to content

rewrite(phase1): add fragment/respqueue, convert loan to fixed-capacity, ported from c-RCP - #131

Merged
SoundMatt merged 1 commit into
rewrite/v3-from-c-rcpfrom
phase1/fragment-respqueue-loan
Aug 21, 2026
Merged

SoundMatt merged 1 commit into
rewrite/v3-from-c-rcpfrom
phase1/fragment-respqueue-loan

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

Part of the v3.0.0 ground-up rewrite (#129, ROADMAP.md Phase 17). Second batch of Phase 1, alongside request/sequencer/scheduler (separate PR).

fragment.hpp (NEW)

cpp-RCP has never had multi-AVTPDU fragmentation — explicit no-go at ROADMAP.md milestone 52. Ported plan_count()/plan() (encode) + Reassembler (decode) from c-RCP's fragment.h/fragment.c (REQ-FRAG-*, 18 requirements). Fixed-capacity: Reassembler embeds a std::array<uint8_t, 4096> instead of c-RCP's realloc()-grown buffer — no heap allocation at all, stronger than c-RCP's own C version. Ported c-RCP issues #614/#616's oversized-reassembly lesson as a design principle (module stays ACF-agnostic like c-RCP, always reports the true reassembled length so a future integrator can check against an ACF frame ceiling before re-encoding). 30 test cases, 132 assertions.

respqueue.hpp (NEW)

TC18 §12.7.9's per-response/ack-stream TX queue — also entirely absent before. Ported from c-RCP (REQ-RMAP-059/061/062/063/064/065/085): octet-budgeted FIFO, per-message ceiling, evict-lowest-sequence_num overflow policy (not FIFO-oldest). kMaxEntries=64 matches c-RCP's bound exactly. 27 test cases, 405 assertions.

loan.hpp

Found BufferPool::pool_ was an unbounded std::vector<unique_ptr<vector<uint8_t>>> — a real gap flagged in an earlier parity audit. Converted to a bounded std::array<vector<uint8_t>*, 64> matching c-RCP's RCP_LOAN_POOL_MAX_ENTRIES exactly. Test count 6 → 9 (incl. a fixed-capacity overflow test that mutation-proves the bound).

Not cleanly ported (documented in-file, not a follow-up TODO)

c-RCP's RCP_FRAGMENT_REASM_ERR_ALLOC and allocation-failure-injection test cases — structurally eliminated by the fixed-capacity, no-heap design; cpp-RCP has no allocation-failure-injection seam yet (Phase 2 scope).

Verified

Full tree rebuilds clean (221/221 targets), 55/55 ctest suites pass (100%) — independently re-verified from a fresh build, not just the porting agent's own report. No endpoint file touched — wiring fragmentation into real dispatch is Phase 3/4 scope.

Tracked at #129.

…ty, ported from c-RCP

Part of the v3.0.0 ground-up rewrite (cpp-RCP #129, ROADMAP.md Phase 17),
branch rewrite/v3-from-c-rcp. Second batch of Phase 1, alongside
request/sequencer/scheduler (separate PR).

- fragment.hpp (NEW): cpp-RCP has never had multi-AVTPDU fragmentation --
  this codebase made an explicit no-go call at ROADMAP.md milestone 52
  (v2.8.0). Ported rcp::fragment::plan_count()/plan() (encode) and
  Reassembler (decode) from c-RCP's fragment.h/fragment.c (REQ-FRAG-*,
  18 requirements). Fixed-capacity: Reassembler embeds a
  std::array<uint8_t, 4096> instead of c-RCP's realloc()-grown buffer --
  no heap allocation at all, stronger than c-RCP's own C version. Ported
  c-RCP issues #614/#616's oversized-reassembly lesson as a design
  principle: this module stays ACF-agnostic (matching c-RCP -- the real
  fix there lived in mock.c's dispatch layer, not fragment.c) and always
  reports the true, complete reassembled length, so a future integrator
  (Phase 3/4 wiring, out of scope here) can check against an ACF frame
  ceiling before re-encoding, exactly the check c-RCP's dispatch layer
  had to learn to add. 30 test cases, 132 assertions.

- respqueue.hpp (NEW): the per-response/ack-stream TX queue TC18
  Sec12.7.9 describes -- also entirely absent before. Ported from c-RCP's
  respqueue.h/respqueue.c (REQ-RMAP-059/061/062/063/064/065/085):
  octet-budgeted FIFO, per-message max_avtpdu_size_octets ceiling, and
  TC18 Sec12.9.4/Sec12.9.5's evict-lowest-sequence_num overflow policy
  (not FIFO-oldest). kMaxEntries=64 from c-RCP's
  RCP_RESPQUEUE_MAX_ENTRIES, backing a fixed std::array of entry slots.
  27 test cases, 405 assertions.

- loan.hpp: found BufferPool::pool_ was an unbounded
  std::vector<unique_ptr<vector<uint8_t>>> with no capacity ceiling --
  a real gap flagged in an earlier parity audit this session. Converted
  to a std::array<vector<uint8_t>*, 64> matching c-RCP's own
  RCP_LOAN_POOL_MAX_ENTRIES bound exactly (c-RCP bounds entry count
  only, not per-buffer size -- matched that, not a stricter policy).
  Once the free list is full, release now frees the buffer outright
  instead of growing storage further, mirroring c-RCP's pool_append()
  degradation. Also removed a redundant heap re-wrap the old code did
  on every reuse. Test count 6 -> 9 (new: pool sanity, destructor-frees-
  free-list, and a fixed-capacity overflow test that mutation-proves the
  bound).

Not cleanly ported, documented in-file rather than left as a follow-up
TODO (structural, not a gap to close later): c-RCP's
RCP_FRAGMENT_REASM_ERR_ALLOC and its allocation-failure-injection test
cases across all three modules have no C++ analog -- the fixed-capacity,
no-heap design structurally eliminates the allocation-failure class,
and cpp-RCP has no allocation-failure-injection seam yet (that's Phase
2's allocation-seam work).

Verified: full tree rebuilds clean (221/221 targets), 55/55 ctest
suites pass (100%). No endpoint file (can.hpp/spi.hpp/uart.hpp/
regmap.hpp's kOptFragmentation) touched -- wiring fragmentation into
real dispatch is Phase 3/4 scope, not this pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Matt <47545907+SoundMatt@users.noreply.github.com>
@SoundMatt
SoundMatt merged commit 79261c4 into rewrite/v3-from-c-rcp Aug 21, 2026
22 checks passed
@SoundMatt
SoundMatt deleted the phase1/fragment-respqueue-loan branch August 21, 2026 19:16
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