Repository navigation
Description
Part of the 5G-NR RAN EPIC #254. Phase B.
Goal: a CU owns the facility-wide slot map and coordinates cell-edge resources — the disaggregated-RAN control plane over the F1 backhaul.
5G mapping (terminology corrected from the review)
CU / DU split (the CU half); F1 interface = the DU↔CU control link (Xn is inter-gNB — used here for any direct DU↔DU coordination); coordinated scheduling / dynamic-TDD alignment (5G ICIC successor). This is an NR-inspired centralized facility scheduler, not a faithful 3GPP CU (it owns scheduling, not PDCP/RRC).
Deliverables (tools/ran-controller/ — the CU app; never touches the radio)
-
tools/ran-controller/— collects per-DUUeRegistry+ link quality over the F1 socket (UDP/gRPC over LAN), pushes per-DU grant maps back. - coordination planner — for an edge UE heard by two DUs, allocate disjoint time slots (cheapest, tight-sync tier only) or different channels via
FastRetune(slots ≫ retune time); a coarse-sync (USB) DU is restricted to frequency separation, not same-channel time slots (M4 tiers). - each DU exposes a local F1 control socket (accepts a pushed grant map; publishes registry + link quality).
- control-plane failure model (from the review) — a late CU update must never alter a frame already in progress. Grant distribution carries: a monotonically increasing schedule epoch/version, an
effective_atnetwork-frame number, a minimum control-plane lead time, DU acknowledgement of a staged schedule, stale-update rejection, and autonomous DU fallback on CU/backhaul outage.
Reuses
M1 grant map, FastRetune, SetCcaMode, M4's synced TSF (so a CU-assigned slot index means the same instant at every DU).
Dependencies
M4 (#254 tracks) — coordination is meaningless without a shared clock.
Test — tests/ran_coord.sh
An edge UE hearing both DUs: uncoordinated → collisions on the shared airtime; enable the CU coordination planner → the edge UE's airtime goes clean. Headless selftest: the planner's slot/channel-assignment logic in the selftests aggregate.
Status (2026-11-05)
- Done: cell M5 core: coordination planner + F1 control link (failure model) #525 (
src/cell/Coord.hplanner,src/cell/F1.hmessages and the DUStager) and cell M5: F1 DU link, ran-controller CU, rig coordination test #526 (the DU F1 link inexamples/cell,tools/ran-controller, the multi-cell witness,tests/ran_coord_analyze.py). Details indocs/cell-m5.md. - Control-plane failure model: monotone versions,
effective_net_sf(one network-wide instant from the PTP clock), a minimum lead time, DU acks, stale and replay rejection (authenticated freshnessseq), abandonment instead of an off-instant apply, and autonomous DU fallback on CU outage. - Rig (testrig
scripts/m5_ran_coord.sh): two co-channel PTP-locked DUs and one UE each, with the CU on n300-1. At a stagger where cell 2's DL airs on cell 1's UE uplink:- baseline (the CU keeps default positions): cell 1 UL 62.6 %, 361 DL retx;
- coordinated: 100 %, 0 retx, both DUs on one instant;
- CU outage: the DUs go autonomous within 3 s and re-apply on one instant when a new CU appears.
- Planner deliverable (partly done, left unchecked): disjoint time slots are applied, and the tier rule (a coarse DU gets frequency separation only) is implemented and selftested. Channel separation via
FastRetuneis proposed and logged, not applied at runtime. A running cell and its UEs moving channel is open, and there is no USB coarse-tier DU on the rig.
Activity
cell M5 core: coordination planner + F1 control link (failure model) (#…
cell M5: F1 DU link, ran-controller CU, rig coordination test (#526)
josephnef commentedon Nov 12, 2026
Rescoped to the PCIe tier, as agreed. The coarse-tier (USB) part, a coarse DU getting frequency separation on air, moves to #565.
Done and verified on the rig:
tools/ran-controller(#526), the disjoint-slot planner (src/cell/Coord.h, #525; edge UE 62.6 % → 100 % with 0 retx), per-DU F1 sockets, the control-plane failure model (CU outage → autonomous, then a shared instant on the new CU), and the planner selftest (ctestcell_m5). The handover test lives in testrig (m5_ran_coord.sh+tests/ran_coord_analyze.py), nottests/ran_coord.sh.One PCIe item keeps this open: channel separation applied at runtime. The planner computes the spare channel, but the CU only logs it (
ran.retune); no running DU, nor its UEs, moves channel withFastRetune.cell M5: move a running cell to another channel (runtime channel sepa…
josephnef commentedon Nov 12, 2026
Closing on the PCIe tier, as agreed. The last item, applying channel separation at runtime, is in: #567 (7faeb67).
RAN_RETUNE_APPLY=1, F1 v15ChannelSwitch).Rig (testrig
m5_retune.sh, cell 2's DL on UE1's uplink):At this rig's levels the overlap cost UE1 only a few uplinks, so the gain shown is the conflict removed.
The coarse-tier (USB) rule moves to #565.
josephnef commentedon Nov 12, 2026
Note for the record: the M6 regression ran alongside this. On 2026-11-12 the rig's RF levels changed with no code change in between, and the M6 suites built on a standing handover margin stopped finding one; an A/B on master failed the same way. The cause is not established. Those suites are being made placement-independent: the UE's measured level per cell is pinned to each suite's design levels (
CELL_UE_MEAS_LEVEL). With that, all eight M6 suites pass on the changed rig. PR to follow.