Configure Mobility and Cell State
The NRCell resource is the operator surface. Everything on this page is done with
kubectl against your cells. The controller applies your changes to the running network
live (no gNB restarts, no pod rollouts for mobility-only edits) and records them durably so
restarts converge to the same state. How that works is
How Mobility Reaches the CU-CP; the per-command machinery
underneath is the runtime commands reference, and you
should not need it for anything here.
All examples assume cells in racora-system:
kubectl get nrcells -n racora-system
Neighbor Relations: Enabling Handover
Declare which cells are handover neighbors. Relations are directional: for normal two-way mobility, declare both directions.
# on cell nr-n78-b210
spec:
neighbors:
- nrCellRef: nr-n78-b210-node1 # name of the neighbor NRCell
reportConfigs: [2] # measurement configs for this relation
# (default [2] = the built-in A3)
kubectl patch nrcell nr-n78-b210 -n racora-system --type=merge \
-p '{"spec":{"neighbors":[{"nrCellRef":"nr-n78-b210-node1","reportConfigs":[2]}]}}'
kubectl patch nrcell nr-n78-b210-node1 -n racora-system --type=merge \
-p '{"spec":{"neighbors":[{"nrCellRef":"nr-n78-b210","reportConfigs":[2]}]}}'
That is the entire handover configuration for cells under one CU. With the built-in defaults, a UE hands over when a neighbor measures 3 dB stronger than its serving cell for 100 ms.
Physical prerequisite: the two cells must be frame-aligned (clockSource: gpsdo with
GPS lock on both radios), or the neighbor is invisible to UEs whatever you configure; why
is on How Mobility Reaches the CU-CP,
checking lock on Connect a Radio.
Automatic Neighbor Relations (ANR)
You do not have to declare every relation yourself. CU-IP's ANR function watches which
cells UEs actually measure together (the substrate's co-measurement graph) and manages
spec.neighbors for you: sustained overlap between two cells adds the relation on both,
and a relation ANR created is removed again once the evidence stays weak or stale.
Provenance is tracked in status; every applied relation carries where it came from:
kubectl get nrcell nr-n78-b210 -n racora-system -o jsonpath='{.status.neighbors}' | jq
# [{"nrCellRef":"nr-n78-b210-node1","reportConfigs":[2],
# "source":"anr","appliedAt":"…","nci":"0x66C001"}]
Which relations ANR may add and remove, and the ownership modes, are on How Decisions Become Network State.
Tuning and disabling live on the CU-IP side: chart values racora-cu.cuIp.engines and
racora-cu.cuIp.engineConfig (thresholds, sustain windows, and an ownership: report-only
shadow mode that evaluates and logs without acting; drop anr from engines to turn the
function off). Controller-side apply gates are under racora-controller.decisions.
Tuning Handover Behavior
Measurement report configs are defined under spec.mobility and referenced by id from
relations; ids 1 and 2 are built in (How Mobility Reaches the CU-CP).
Report configs are CU-wide: define each id once, on one cell (or identically on all).
Two cells that define the same id differently get the lexicographically first cell's
definition, and the other carries a ReportConfigConflict condition.
A "stickier" A3 for closely spaced cells, with a wider trigger margin and a dead band against ping-pong:
# on one cell
spec:
mobility:
reportConfigs:
- reportCfgId: 3
reportType: event_triggered
eventTriggeredReportType: a3
measTriggerQuantity: rsrp
measTriggerQuantityOffsetDb: 6 # neighbor must win by 6 dB
hysteresisDb: 3 # ±3 dB dead-band around that
timeToTriggerMs: 100
reportIntervalMs: 1024
neighbors:
- nrCellRef: nr-n78-b210-node1
reportConfigs: [3] # relation now uses the tuned config
(and point the other direction's relation at [3] too.)
Ping-pong at hysteresisDb: 0 is not a fault: each bounce is a successful handover
tracking the strongest cell. The offset and hysteresis choose the trade between stickiness
and responsiveness.
Serving-cell periodic measurement reporting is per-cell:
spec:
periodicReportCfgId: 1 # must reference a periodical config; id 1 built-in
Other Events and Thresholds
A3 (neighbor better than serving by an offset) is the handover default, but a report
configuration can use any of the A1 to A6 events: eventTriggeredReportType: a1|a2|a4|a5
with measTriggerQuantityThresholdDb (and measTriggerQuantityThreshold2Db for A5)
instead of the offset; periodicHoRsrpOffsetDb lets a periodical report trigger
handovers when a neighbor is that much stronger (in 0.5 dB units; -1, the default,
disables it). The field list with every range is the NRCell API.
Administrative Cell State
spec:
adminState: Locked # Unlocked (default) | Locked
cellBarred: false # true = on air but UEs may not camp
Locked performs a graceful stop (connected UEs are released cleanly, then the cell leaves
the air) and the intent persists: the cell stays down across DU pod restarts and node
reboots until you set Unlocked again. cellBarred is independent: the cell keeps
transmitting but rejects camping.
When locking a cell long-term, also remove the neighbor relations that point at it: a lock does not touch other cells' measurement configuration (How Mobility Reaches the CU-CP). A handover commanded toward a locked cell is rejected by the CU-CP (runtime commands).
What Happens When You Edit
Mobility and admin edits are applied to the running CU-CP live, within about a second,
and recorded in its boot configuration; a connected UE picks them up at its next RRC
reconfiguration (How Mobility Reaches the CU-CP).
Radio-facing fields (pci, gains, ARFCN) are different: they rebuild the DU configuration
and roll the DU pod, a brief cell restart. Mobility and admin edits never do.
Verifying Your Change
# the controller applied it (look for the runtime sync line):
kubectl logs -n racora-system deploy/racora-controller | grep "mobility runtime sync"
# the CU-CP has it (registry log; relations, report configs, admin state):
kubectl exec -n centralized-unit deploy/cu-cp -c cu-cp -- \
grep -aE "Added neighbor relation|Updated report config|admin_state" /tmp/cu_cp.log | tail
A cell's administrative and operational state on demand is the cell_status command in
the runtime commands reference. Handover activity itself
is visible in the Grafana "RAN Mobility" dashboard and in the CU-CP log
(Trigger intra-CU … handover, then "Intra CU Handover Target Routine" finished successfully); see Read Logs and Traces.