How Radios Are Driven
Racora does not talk to radios. The DU does, CNS OCUDU (the gNB), over UHD for a USRP, over
Open Fronthaul for an O-RAN split 7.2 O-RU, or over a virtual transport for a simulator. What Racora owns is everything around that:
which node runs which radio, the fields on the NRCell that describe it, and the shape of
the DU pod it generates for each backend. Declaring one is Connect a Radio.
What Each Backend Produces
spec.radioBackend.ruType selects the backend; only the matching block of the NRCell is
read, and the API server rejects any other value at apply time.
uhd, a USRP over UHD. The DU runs with SYS_NICE, IPC_LOCK and PERFMON, pins
its real-time threads to the node's isolated CPUs (read at pod start from the node
itself), requests one ettus.com/usrp, carries the racora.io/rf-ready=true node
selector, and uses the Recreate strategy: the radio is exclusive, so a replacement pod
cannot start while the old one holds it. The USRP device plugin mounts the host's UHD
firmware images (/usr/share/uhd/) read-only into the pod and attaches the radio's
/dev/bus/usb device; a node with two USRPs advertises 2 and can run two cells.
zmq, a virtual radio. The DU's radio driver is zmq with tx_port, rx_port and
base_srate as its device arguments, so IQ samples flow over ZeroMQ instead of RF; the
controller adds port 2000 (zmq-tx) to the cell's Service for the transmit side and no node
selector, so the DU schedules anywhere. The peer is a UE simulator you deploy, such as
srsUE with its ZMQ radio, in the namespace the controller's ueNamespace value names
(default user-equipment), which is where the default rxPort name resolves; Racora
ships no UE.
dummy, no radio. The DU runs with no radio and no UEs: the CU plane, the F1
connection, identity, mobility configuration and telemetry are all real. It is what the
example cell uses and the right backend for a control-plane-only lab.
ofh, an O-RU over Open Fronthaul. The DU drives an O-RAN split 7.2 O-RU through
OCUDU's ru_ofh: C- and U-plane frames on a VLAN of the node's fronthaul NIC, over a raw
socket. The DU therefore runs on the node's host network (hostNetwork, cluster DNS kept)
with NET_RAW and NET_ADMIN added, carries the racora.io/fronthaul-ready=true node
selector, uses Recreate, and requests no device. The ofh block uses OCUDU's ru_ofh
key names in camelCase (the windows, the compression, the eAxC ids, the VLANs, the O-RU
MAC); the antenna counts follow the eAxC ids, and the fronthaul's own rx-window counters
(metrics.layers.enable_ru) are always on.
One Cell, Both Ends of the Fronthaul
The DU and the O-RU must agree on the carrier, the PRB count, the TDD pattern, the eAxC
ids, the VLAN, the O-RU's MAC address and the IQ bit width. For an ofh cell the
controller renders both ends from the one NRCell: the DU's configuration (du0.yml)
and the O-RU's M-plane provisioning file (ru.yml, the OCUDU O1 adapter's
--ru_provision_config format), side by side in the cell's ConfigMap. The carrier is the
cell's dlArfcn and bandwidth on both directions, so the band must be unpaired (TDD); the
TDD pattern, written explicitly to both ends, is spec.tddUlDlCfg or 7 downlink slots, a
special slot of 6 downlink and 4 uplink symbols and 2 uplink slots. The compression is
block floating point with one bit width for every direction, because the O-RU's endpoints
are provisioned with one.
A radio profile holds what one radio model fixes, such as its transmission and
reception windows, IQ scaling, whether its U-plane carries compression headers, and its
M-plane quirks (mplane: fixed endpoint names, the TDD binding, activation replies). It is
a ConfigMap in the cell's namespace, named by ofh.profileRef, with the same keys under
profile.yaml; the cell's own keys win, and the controller reads it whenever it
reconciles the cell.
Three facts belong to the node, not the cell, and the DU resolves them when it starts:
the fronthaul interface (the port node provisioning selected, recorded in
/etc/racora/fronthaul-inventory, unless ofh.networkInterface names one), the DU MAC
address (that interface's own), and the F1-U address. The DU shares the node's port space,
so its F1-U listens on the GTP-U port the CU-UP sends downlink to, 2152, on the node
address the kernel uses toward the CU-UP pod; a UPF on the same node holds that port on the
node's primary address. The OFH timing and TX/RX threads take the node's first two
isolated CPUs.
The Clock Decides Whether Mobility Is Possible
A single cell runs on the radio's internal clock. Cells between which UEs hand over need frame-aligned radios, GPS-disciplined on USRPs; why that is the precondition is How Mobility Reaches the CU-CP, and setting the clock and checking lock is Connect a Radio.
The Fronthaul Needs a Timed Node
This section and the next are the short form. The whole picture of an O-RU cell, which part of Racora runs each plane, the node-side fronthaul agent and the order a cell comes up in, is the Open Fronthaul section: Open Fronthaul in Racora, The Fronthaul Agent, From Power-On to Streaming.
The node side of fronthaul (a NIC with hardware timestamping and a PTP hardware clock,
ptp4l and phc2sys, the racora.io/fronthaul-ready label) is what the
provisioner prepares, and what an ofh DU selects. When
the node is the grandmaster, the NIC's clock is the time root: it free-runs
on the NIC's own oscillator (or follows GNSS when the card has a receiver) and the
system clock follows it, so the radio's carrier inherits the NIC's accuracy and not
the host's. It runs 37 s ahead of UTC so the fronthaul carries TAI: an O-RU numbers
radio frames from PTP time, the DU from the system clock, and the two only agree
when the wire is TAI.
The O-RU's M-plane Session
The DU may only start its fronthaul stream onto an O-RU that is provisioned, synchronized
and has its carriers active. When the cell names the O-RU's NETCONF endpoint
(ofh.mplane.netconfHost, or callHome for an O-RU that dials in), the DU pod carries an
mplane sidecar that holds the O-RU's M-plane session: the OCUDU O1 adapter, which
supervises the O-RU and provisions it from the cell's ru.yml on every connect cycle,
reading the account from a Secret (ofh.mplane.credentialsSecret) as files. The sidecar
starts before the DU and its startup probe is the adapter's /ru/ready, which answers only
once the session is supervised and every carrier is READY, so the DU container does not
start before the O-RU can take the stream. Deleting the cell ends the session with the pod.
The controller reads the pod into the cell's RadioReady and DUReady conditions. A DU
restarted against an O-RU that kept its carriers active would resume the stream mid-flight,
so when the DU container restarts the controller replaces the whole pod: the new pod's
sidecar provisions the O-RU again before the new DU starts.
Without an endpoint the O-RU is provisioned outside Racora, before the cell is applied, from
the same ru.yml; the controller's code renders it from the manifests
(Connect a Radio). One ofh cell per node: the
DU's host-network ports (8001, the F1-U socket, the sidecar's HTTP port) are the node's.
The USRP device plugin advertises the USB B200 family only (B200, B210, B200mini),
so other UHD radios are not supported: a uhd DU requests ettus.com/usrp and would
stay Pending.