Repository navigation
Conversation
src/cell/HoCommand.h: - HoCommand is what the CU sends both DUs: the UE, source and target, its id and position at the target, the network superframe of the switch, and the TSF delta. - ho_tsf_delta_us is that delta: for DUs on the PTP fabric, tsf_k(t) = t - phase_k - net_off_k * P, so target - source = (phase_s - phase_t) + (net_off_s - net_off_t) * P. A UE locked to the source knows the target's clock exactly: no scan, no re-acquisition. - HoIe is what the source DU tells the UE in its beacon. It carries a CRC and the cell key's tag (label 'H'), so a forged handover is inert; find_ho_ie returns the newest id addressed to (cell, UE). F1 v4: - Type::Handover (encode/decode_handover, with the freshness seq); - Report carries net_off, filled by the DU; - Ack carries its kind (schedule / handover), and the CU's schedule re-issue only reacts to schedule acks. The cell_m6 ctest covers: - the TSF delta against a simulated two-DU timeline (and both grids on network superframe boundaries); - the F1 handover round trip, tags and every truncation, and the Ack kind; - the IE in an MPDU: newest id, wrong key inert, a torn IE dropped while the intact one stays, unkeyed vs keyed. ctest 92/92. Rig: the M5 coordination run passes on F1 v4. Refs #260 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PR Summary by QodoDefine F1 handover commands and authenticated beacon IEs
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1.
|
- HoReceiver is the UE side. It acts on a handover IE only if its id is above every one it accepted and its switch instant (covered by the tag) is still ahead, so a captured beacon replayed later is inert. - find_ho_ie scans beacons only (frame control 0x80). - selftest: replay of the same, a superseded and a spent IE; a non-beacon frame carrying a valid IE is rejected. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Qodo review addressed in 8ea6edc:
|
|
Both Qodo findings resolved. The remaining item, 'Embed handover in the grant-map IE', is Qodo's alternative-approach note, not a finding. A separate tagged IE keeps the grant map's format and its CRC-only integrity unchanged. Merging under skip-qodo-gate. |
…itional fallback (#530) Part of M6 (#260), epic #254. Step 2b: handover execution on top of #528 (observe-only A3) and #529 (command and IE). Full write-up in `docs/cell-m6.md`. - **CU (`RAN_HO_EXECUTE=1`):** - an A3 candidate becomes a `HoCommand`: the target's free id and position, the switch instant and the TSF delta; - **two-phase:** sent to the target first, to the source on the target's ack, and a cancel goes to the target if the source refuses; - `ran.ho_done` when the target reports the UE. - **Target DU:** pre-admits the UE under the commanded id and publishes its grant for the switch instant. - **Source DU:** airs the tagged IE until the switch, then releases the UE only if it stopped uplinking there; otherwise it keeps it. - **UE:** at the instant it shifts its clock (`TsfSync::ShiftRemote`, new, selftested), takes its target identity and runs the target's buffered map. **Conditional:** with no target grant within 10 superframes it returns to the source. - **Fix:** a DU with no UE now paces its main loop. Its superframe count, and so its reported network superframe, used to run away. Rig (two PTP cells; the crossing is forced with `RAN_A3_OFFSET_DB=-2`, as the UEs are stationary): | | normal | target DU killed right after staging | |---|---|---| | switch | source sf 143 → target sf 137 (= the target's effective sf) | source sf 172 | | target hears the UE | in slot from the first superframe after: 1115/1117 | — | | outcome | committed; source released at +21; `ran.ho_done` +5 | UE fell back at +10; source kept it, 1092/1092 in slot | ctest 92/92. Not yet: DAPS (duplicated uplink plus `SeqDedup`), an emulated moving crossing, and different-channel handover. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…PC#529) Part of M6 (OpenIPC#260), epic OpenIPC#254. Step 2a, headless: the pieces that move a UE's schedule from cell A to cell B. The DU/UE execution and the rig test come next. - **`src/cell/HoCommand.h`:** - **`HoCommand`** (CU → both DUs): the UE, its id and position at the target, the network-wide switch superframe, and the TSF delta. - **`ho_tsf_delta_us`:** for DUs on the PTP fabric, `tsf_k(t) = t − phase_k − net_off_k·P`, so the target's clock is the source's plus `(phase_s − phase_t) + (net_off_s − net_off_t)·P`. A UE locked to A therefore knows B's clock exactly, with no scan and no re-acquisition. - **`HoIe`** (A's beacon → the UE): carries a CRC and the cell key's HMAC tag, so a forged handover is inert. `find_ho_ie` returns the newest command addressed to that UE. - **F1 v4:** `Type::Handover` with a freshness `seq`; `Report.net_off`, filled by the DU; and an `Ack.kind` so handover and schedule acks are distinct. - **`cell_m6` ctest:** - the TSF delta on a simulated two-DU timeline; - the handover message round trip, tags and every truncation; - the IE inside an MPDU: newest id wins, a wrong key is inert, a torn IE is dropped, unkeyed vs keyed. - **Checks:** ctest 92/92, and the M5 rig run passes on F1 v4. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Part of M6 (#260), epic #254. Step 2a, headless: the pieces that move a UE's schedule from cell A to cell B. The DU/UE execution and the rig test come next.
src/cell/HoCommand.h:HoCommand(CU → both DUs): the UE, its id and position at the target, the network-wide switch superframe, and the TSF delta.ho_tsf_delta_us: for DUs on the PTP fabric,tsf_k(t) = t − phase_k − net_off_k·P, so the target's clock is the source's plus(phase_s − phase_t) + (net_off_s − net_off_t)·P. A UE locked to A therefore knows B's clock exactly, with no scan and no re-acquisition.HoIe(A's beacon → the UE): carries a CRC and the cell key's HMAC tag, so a forged handover is inert.find_ho_iereturns the newest command addressed to that UE.Type::Handoverwith a freshnessseq;Report.net_off, filled by the DU; and anAck.kindso handover and schedule acks are distinct.cell_m6ctest:🤖 Generated with Claude Code