Repository navigation
cell M6: inter-frequency handover (UE retunes at the switch) - #532
Conversation
…nd, the UE retunes at the switch - HoCommand.target_channel (from the target DU's report) and HoIe.channel (IE v2); F1 v6 carries it. - UE: at the switch, as on the same channel, it shifts the clock by the TSF delta (no target beacon needed first), takes the target identity and runs the target's map. In addition it stops its uplink beacon, retunes (FastRetune) and restarts the beacon on the new channel. - Logged: cell.ue.retune (retune_us), and cell.ue.retune_first_beacon (the deaf time to the first serving beacon). - Fallback (no target grant within CELL_HO_FALLBACK_SF) retunes back: the bounded deadline to return to the serving channel. - CU: RAN_HO_FORCE=SRC:UE:TGT@SECONDS forces one handover through the normal execution path. No DU hears a UE across channels until UE measurement gaps exist, so the A3 has nothing to compare. Rig (testrig m6_handover.sh --channel2 157: ch149 -> ch157, 5 normal + 3 target-crash): all pass. - the switch lands on the target's effective sf in every run; - FastRetune 23.5/23.6/23.7 ms (min/median/max); - first target beacon 37/52/101 ms after the retune; - interruption 2/2/3 sf; - crash fallback 10 sf, with 10 sf of source uplink missed. ctest 92/92. docs/cell-m6.md. Refs #260 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PR Summary by QodoEnable inter-frequency handover with UE retuning and fallback
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1.
|
- UE: the uplink beacon must stop before a retune (StopBeacon checked, retried; the retune waits for it, bounded by the fallback deadline). A FastRetune exception is caught (cell.ue.retune_fail): the channel stays, and the fallback resolves it. - CU: RAN_HO_FORCE is consumed only once its command is in flight (pending while busy, full or stale). A handover target's report must be fresh (3 s). Ids are range-checked to uint16 and the time to finite 0..86400 s. Rig regression (m6_handover.sh --channel2 157, 2 normal + 1 crash): pass. ctest 92/92. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Qodo review addressed in 1f8114d:
Rig regression: 2 normal + 1 target-crash inter-frequency runs pass. ctest 92/92. |
|
All 5 Qodo findings resolved. The remaining item, 'Implement UE measurement gaps before inter-frequency handover', is Qodo's alternative-approach note. It is the next PR, already rig-tested on its branch: the A3 triggering this inter-frequency handover on UE-reported gap measurements. Merging under skip-qodo-gate. |
…nter-frequency trigger) (#533) Part of M6 (#260), epic #254: **UE measurement gaps**, the inter-frequency handover trigger, on top of #532. With one radio per DU, no DU hears a UE on another channel, so the A3 needs the UE's own measurements. - **`src/cell/MeasGap.h`:** - **NL IE:** the neighbour list as offsets on the serving grid, `(phase_n − phase_s) mod P`, so the UE knows when a neighbour's beacon airs from its serving clock alone. - **MR IE:** the UE's filtered beacon RSSI/SNR per cell. - Both carry a CRC and the cell key's tag. - **`gap_window()`:** retune + beacon + retune, clear of the serving beacon and the UE's own DL/UL slots; otherwise the gap is skipped. - **F1 v7:** `Neighbours` (CU → DU, every round) and `Report.ue_meas`. - **DU:** airs the NL IE and relays its UEs' MR reports. - **UE:** filters every cell beacon it hears. Every `CELL_UE_GAP_SF` it measures an other-channel neighbour in a gap, if one fits, and reports every second. - **CU:** the A3 on UE reports compares serving and neighbour beacons (metric `ue_rssi`). Rig (testrig `scripts/m6_measgap.sh`, 5 runs; ch149 and ch157, cell 2 at phase 60000 µs; **default A3 thresholds, nothing forced**): all pass. | | min | median | max | |---|---|---|---| | gap deaf time (14 gaps) | 53.7 ms | 53.9 ms | 56.6 ms | | neighbour in gaps vs serving | −46 vs −55..−57 dBm | | | | switch after the network instant | 21 ms | 21 ms | 28 ms | | interruption (sf) | 3 | 3 | 3 | - **Every run:** the A3 fired on UE-reported values, the inter-frequency handover executed, and the gaps cost no uplink. - **TSF continuity:** now asserted exactly. The switch is at the network instant `eff_target·P − ((phase_t − phase_s) mod P)` plus the UE's poll latency. All earlier rig sets re-verify under it. ctest 92/92. Limit: a gap goes only where it clears the UE's slots, so in this layout cell 2's UE cannot measure cell 1 (logged `gap_skip`). 🤖 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: different-channel handover, on top of #530 and #531.
HoCommand.target_channelcomes from the target DU's report, andHoIe.channeltravels with it (IE v2, F1 v6).FastRetune) → restarts it on the new channel. It logs the retune time and the first serving beacon after it.CELL_HO_FALLBACK_SF, the UE retunes back to the source, which still holds it. This bounds the deaf time.RAN_HO_FORCE=SRC:UE:TGT@SECONDSforces one handover through the normal execution path.Rig (testrig
scripts/m6_handover.sh --channel2 157: ch149 → ch157, 5 normal + 3 runs with the target killed after staging; all pass):FastRetune(8852CE, 11 retunes)The switch lands on the target's effective superframe in every run: clock continuity holds across the channel change. ctest 92/92. Details in
docs/cell-m6.md.🤖 Generated with Claude Code