Skip to main content

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.