The Benetel RAN650 is a commercial O-RAN 7.2x radio unit (O-RU) for band n78 with four transmit
and four receive branches. On COSMOS both open-source O-DU stacks drive it end to end with a COTS
Quectel modem: OCUDU (srsRAN) runs it standalone from the radio's own stored configuration,
and Duranta (OAI) runs it under hierarchical M-Plane, with the gNB acting as the NETCONF
client. The two stacks need different persistent settings on the same radio, so every bring-up
restores the stack's committed golden state before the O-DU starts.
Danger: The Benetel and the LiteOn FlexFi share one RF space. Since 2026-10-16 every O-RU reservation carries its band, centre frequency and bandwidth, and the shared scheduler refuses overlapping bookings, so both may be powered only on non-overlapping channels;
cosmos-oru resetstops if a co-channel O-RU is being driven, or if a DU is already streaming at yours.
Confirm power by ping, not by theomf tellreply. The radio is a shared
instrument: leave it powered as you found it.
Other O-RUs: fleet overview · Benetel RAN650 · LiteOn FlexFi · Foxconn RPQN-7801 · Software O-RUs
| Item | Value on COSMOS |
|---|---|
| Band / range | n78, 3300–3800 MHz |
| Carrier | 100 MHz, 273 physical resource blocks (PRB), 30 kHz subcarrier spacing (SCS), centre 3750 MHz |
| Duplex | Time-division duplex (TDD). The frame pattern is a stored RU setting and differs per stack: DDDSU (2.5 ms) for Duranta, DDDDDDDSUU (5 ms) for OCUDU; special slot DDDDDDGGGGUUUU (6 downlink / 4 guard / 4 uplink symbols) for both |
| Antennas | 4T4R. The RU's mimo_mode selects how many branches the fronthaul feeds: 1_2_3_4_4x4 (Duranta) or 1_2_3_4_4x2 (OCUDU) |
| TX power | tx_power_dbm=35.000000 in the RU's /etc/ru_config.cfg (both stacks). The vendor maximum is not recorded here |
| Firmware | V2.1.0, hardware category A |
| Fronthaul | O-RAN 7.2x split (Control/User/Synchronisation planes over Ethernet); C- and U-plane on VLAN 4; block floating point (BFP) compression, 9-bit, with a static compression header (Duranta) or a dynamic one (OCUDU); Duranta's fronthaul library is configured for MTU 9216 and the host sets the E810 physical function to MTU 9000 |
| M-Plane | Yes, NETCONF on TCP 830. The mode is a stored RU setting: enabled for Duranta, disabled (standalone) for OCUDU |
| Timing | Precision Time Protocol (PTP), ITU-T G.8275.1 telecom profile (L2 transport, domain 24) from the COSMOS fronthaul fabric. O-DU windows (µs): T1a C-plane DL 419–470, T1a C-plane UL 285–336, T1a U-plane 294–345; Ta4 0–200 (Duranta) or 0–1960 (OCUDU) |
| RU address / MAC | management 10.3.12.20, fronthaul MAC 8c:1f:64:d1:11:f0. The unit has also answered on 10.3.12.21, so identify it by MAC |
| DU MAC expected by the RU | 00:11:22:33:44:66 (C-plane and U-plane) |
| Power control | omf tell -a {on,off,offh,offs,reset,reboot} -t benetel-oru.instrument.orbit-lab.org from your fronthaul console (the console your O-RU reservation targets) |
| Physical cell ID (PCI) on COSMOS | 2 (both stacks). COSMOS convention: LiteOn 1, Benetel 2, Foxconn 3, soft/RF simulator 0 |
The RAN650 is a small ARM Linux system. Its datapath is set by field-programmable gate array
(FPGA) registers, which the radio's own /usr/sbin/radio_setup.sh writes at every boot from
/etc/ru_config.cfg. That file is read only at boot, so a change to it takes effect after a
restart of the radio. What happens after boot depends on the stored M-Plane mode:
o-ran-uplane-conf) and must hold the session: under O-RANnr-softmodem is that client. The M-Plane session does not push the TDD pattern; on V2.1.0tdd_pattern_* keys in its own ru_config.cfg, so thoseru_config.cfg and the DU only exchanges C/U/S-plane traffic with it.The mode moves the PRACH streams. In standalone mode the RU carries the physical random-access
channel (PRACH) on extended antenna-carrier identifiers (eAxC) 4, 5, 6, 7; in M-Plane mode on 8, 9.
The downlink and uplink data streams do not move, so a DU that asks for PRACH on the wrong eAxC sees
healthy counters and no random access at all.
What the RU sets for itself, and what it does not. On this firmware the RU writes its own
uplink timing alignment (C0303 = 0x20e), TDD switching alignment (C0366 = 0x1500), downlink
scaling (C0358 = 0x0) and short-form PRACH (C0328 = 0x3) correctly; tooling verifies these and
never writes them. It does not set the number of transmitters: C0300 must read 0x1010101,
and at 0 the radio is configured, PTP-locked and silent. The O-RU profile tool
(oru-apply.py benetel-ran650.yml --stack <stack> --apply) writes only that register and verifies
the rest. Register reads over registercontrol -r are occasionally wrong on the first read; the
tools require two identical consecutive reads.
The golden-state rule. The RU keeps whatever the last stack wrote. A rig counts as working only
once a full state capture (mode, the whole ru_config.cfg, file checksums and registers) is
committed as its golden, and every bring-up restores that golden and refuses to start the DU on a
mismatch. The goldens live on the DU host:
python3 /root/oru-setup/oru_golden.py diff /root/oru-setup/golden/osc-benetel-ocudu.txt
python3 /root/oru-setup/oru_golden.py restore /root/oru-setup/golden/osc-benetel-ocudu.txt
# exit 0 = matches · exit 3 = ru_config.cfg rewritten, the RU needs a PDU COLD cycle · exit 1 = drift remains
benetel-bringup.sh (Duranta) runs the restore twice: before the DU with --scope persistent,
and again after the M-Plane commit, because the DU writes registers over NETCONF.
ocudu-72_cycle.sh (OCUDU) runs it at step [5b].
Restart rules.
The RAN650 starts transmitting only on a fresh boot against an already-locked PTP clock.
Restarting the DU under a running RU never revives the transmitter, and a PTP servo that degrades
mid-run stops the radio. Order: PTP locked → DU stopped → RU restarted → wait for the boot marker
→ registers → DU started → radiating confirmed.
For Duranta the restart must be a power cycle. After an in-RU reboot the cell comes up but
the DU sees uplink symbols early and late and UEs lose sync (ulsch_DTX 100, BLER 0.92), or the RU
comes up on the wrong numerology (RU0 mu0) and never radiates. Port 830 reopening after about
300 s indicates a genuine cold cycle; about 80 s means the RU never lost power.
# Benetel, from your fronthaul console:
omf tell -a off -t benetel-oru.instrument.orbit-lab.org; sleep 25
omf tell -a on -t benetel-oru.instrument.orbit-lab.org
OCUDU's ocudu-72_cycle.sh restarts the RU from its own OS (reboot over SSH) and gates on the
BOOTUP line in /var/log/Benetel_logs/startup.log changing — that file still holds the
previous boot's "Radio bringup complete", and oru_status answers about 40 s before the radio is
configured, so neither is a readiness signal on its own.
The only reliable "is it radiating" indicator is the RU's TX mean power (TXMeanPower, or
TX n Mean Power in oru_status): a real dBm figure, not No dBm. Zero fronthaul drops prove
nothing about RF.
Both stacks put the carrier at the RU's centre_frequency_hz=3750000000 (3750 MHz).
| Parameter | Duranta | OCUDU |
|---|---|---|
| Band / bandwidth / SCS | n78 / 100 MHz (273 PRB) / 30 kHz | n78 / 100 MHz / 30 kHz |
| Carrier definition | dl_absoluteFrequencyPointA = 646724, absoluteFrequencySSB = 650016 (3750.24 MHz) |
dl_arfcn: 650000 (3750.00 MHz; srsRAN derives Point A and the SSB position) |
| CORESET#0 | initialDLBWPcontrolResourceSetZero = 11 |
derived by OCUDU |
| TDD | 2.5 ms: 3 DL slots, special slot 6 DL / 4 UL symbols, 1 UL slot (DDDSU) |
5 ms: 7 DL slots, special slot 6 DL / 4 UL symbols, 2 UL slots (DDDDDDDSUU) |
| PRACH configuration index | 148 | 159 |
| PCI / cell identity | physCellId = 2, nr_cellid = 2 |
pci: 2, sector_id: 2 |
| RU transmit power | tx_power_dbm=35.000000 |
tx_power_dbm=35.000000 |
| RU uplink gain | ul_gain_correction=0 |
ul_gain_correction=0 |
| DU downlink gain | att_tx = 35, tx_amp_backoff_dB = 12 |
iq_scaling: 5.5, ssb_block_power_dbm: -4 |
The UE on COSMOS sits a few metres from the radio, so both gains are deliberately low. The vendor
default ul_gain_correction=18 saturates a receive branch at this range: that branch reads exactly
0.000000 dBFS and uplink collapses to kbit/s. An iq_scaling of 20 clips the downlink (BLER
stuck at 20–30 % with link adaptation already several dB negative); 5.5 gives 0 % BLER.
| Item | Duranta (M-Plane mode) | OCUDU (standalone mode) |
|---|---|---|
| DL eAxC | 0, 1, 2, 3 (nb_tx = 4) |
dl_port_id: [0, 2] (two of the four branches) |
| UL eAxC | 0, 1 | ul_port_id: [0, 1] |
| PRACH eAxC | not set in the conf: the fhi_72 library reads the PRACH eAxC offset from the RU's M-Plane advertisement (the RU's M-Plane-mode map puts PRACH on 8, 9) | prach_port_id: [4, 5] |
| PRACH C-plane | sent by the DU | is_prach_cp_enabled: true (the RU follows the DU's PRACH C-plane: prach_freq_offset_dynamic=true) |
| Compression | BFP 9-bit, IQ and PRACH (iq_width = 9, iq_width_prach = 9); RU compression=static_compressed |
BFP 9-bit DL/UL/PRACH; RU compression=dynamic_compressed paired with enable_*_static_compr_hdr: false |
| VLAN | vlan_tag = (4) |
vlan_tag_cp: 4, vlan_tag_up: 4 |
| Priority code point (PCP) | not set in the DU configuration | not set in the DU configuration |
| DU MAC | du_addr = ("00:11:22:33:44:66") |
du_mac_addr: 00:11:22:33:44:66 |
| RU MAC | ru_addr = ("8c:1f:64:d1:11:f0") |
ru_mac_addr: 8c:1f:64:d1:11:f0 |
| Timing windows (µs) | T1a_cp_dl = (419, 470), T1a_cp_ul = (285, 336), T1a_up = (294, 345), Ta4 = (0, 200) |
t1a_*_cp_dl 419/470, t1a_*_cp_ul 285/336, t1a_*_up 294/345, ta4_min: 0, ta4_max: 1960 |
| Host NIC | E810 virtual function bound to DPDK (dpdk_devices); VF MAC set to the DU MAC, VLAN 4 |
the E810 physical function DATA1a through a raw socket; the NIC must be promiscuous or srsRAN receives no fronthaul frames |
The RU-side counterparts are registers the RU derives from its mode: PRACH receive paths C032A
(0xf, four, for Duranta; 0x3, two, for OCUDU), U-plane compression header C0350–C0352
(0x0 static for Duranta; 0x1 dynamic for OCUDU), expected DU MAC C0319/C031A
(0x22334466/0x11), DU VLAN C0330/C0331 (0x4).
OCUDU's gnb (srsRAN Project) speaks only the C/U/S-planes, so the Benetel must be standalone
(benetel-ru-mode.sh nomplane) and self-configured from its golden ru_config.cfg. The DU talks to
the RU through a raw socket on the E810 physical function DATA1a, which must be in promiscuous
mode.
Files on the O-DU host (OCUDU image). Configurations /root/ocudu/gnb-ocudu-benetel-open5gs-0909cell.yml
(Open5GS on the same host) and /root/ocudu/gnb-ocudu-benetel-sdcore-0909cell.yml (Aether SD-Core on a
separate core server); bring-up /root/ocudu-72_cycle.sh; mode script /root/benetel-ru-mode.sh;
the O-RU key /root/oru/ssh_keys/id_ed25519; the golden /root/oru-setup/golden/osc-benetel-ocudu.txt;
log /tmp/ocudu-72.log. The cycle script checks PTP, stops the DU, restarts the RU, restores and
diffs the golden, and starts /opt/ocudu/build/apps/gnb/gnb -c $CFG on the configured cores.
# on the O-DU host, PTP locked
CFG=/root/ocudu/gnb-ocudu-benetel-open5gs-0909cell.yml /root/ocudu-72_cycle.sh
The Open5GS configuration, as run (the SD-Core variant differs only in cu_cp.amf.addrs: 10.59.1.17,
bind_addrs: 10.59.1.18 and tac: 1 in both places; the SD-Core core serves only TAC 1 and 2):
cu_cp:
amf:
addrs: 127.0.0.5
port: 38412
bind_addrs: 127.0.0.1
supported_tracking_areas:
- tac: 7
plmn_list:
- plmn: "00101"
tai_slice_support_list:
- sst: 1
ru_ofh:
# Timing windows: the values published for a WORKING RAN650 (srsRAN discussion #744). They are much
# tighter than upstream's RAN550 defaults (535/286, up 390/80, ta4 500/25), and this RU is a 650.
t1a_max_cp_dl: 470
t1a_min_cp_dl: 419
t1a_max_cp_ul: 336
t1a_min_cp_ul: 285
t1a_max_up: 345
t1a_min_up: 294
ta4_max: 1960
ta4_min: 0
# With PRACH C-Plane disabled srsRAN never sets up PRACH reception and there is no RACH at all.
is_prach_cp_enabled: true
compr_method_ul: bfp
compr_bitwidth_ul: 9
compr_method_dl: bfp
compr_bitwidth_dl: 9
compr_method_prach: bfp
compr_bitwidth_prach: 9
# Must match the O-RU's own `compression=` in /etc/ru_config.cfg (standalone mode makes the RU
# the authority): static_compressed -> true, dynamic_compressed -> false.
enable_ul_static_compr_hdr: false
enable_dl_static_compr_hdr: false
# ⭐ DL gain. At the metres-scale range of this rig a HIGH iq_scaling CLIPS: DL BLER sticks at
# 20-30 % with OLLA already several dB negative and never converges. See ocudu-72_params.yml.
iq_scaling: 5.5
cells:
- network_interface: DATA1a
ru_mac_addr: 8c:1f:64:d1:11:f0
du_mac_addr: 00:11:22:33:44:66
vlan_tag_cp: 4
vlan_tag_up: 4
prach_port_id: [4, 5]
dl_port_id: [0, 2]
ul_port_id: [0, 1]
cell_cfg:
dl_arfcn: 650000
band: 78
channel_bandwidth_MHz: 100
common_scs: 30
plmn: "00101"
tac: 7
pci: 2
sector_id: 2
nof_antennas_dl: 2
nof_antennas_ul: 2
pdsch:
# qam64, not the 256QAM table: at high CQI the scheduler stays over-optimistic and DL BLER
# sits at 21-26 %. This took it to 0 %.
mcs_table: qam64
olla_target_bler: 0.1
pusch:
mcs_table: qam64
ssb:
ssb_block_power_dbm: -4
prach:
prach_config_index: 159
prach_root_sequence_index: 1
zero_correlation_zone: 0
tdd_ul_dl_cfg:
# MUST equal the RU's own TDD pattern. Default here is the RAN650's Category A DDDDDDDSUU;
# Duranta drives the same radio as DDDSU.
dl_ul_tx_period: 10
nof_dl_slots: 7
nof_dl_symbols: 6
nof_ul_slots: 2
nof_ul_symbols: 4
log:
filename: /tmp/ocudu-72.log
all_level: warning
ofh_level: warning
expert_execution:
threads:
main_pool:
# srsRAN does NOT derive the pool size from main_pool_cpus: nof_threads is its own property and
# defaults low (9 on a 24-core host), so a 100 MHz 4-layer cell fails its own check
# "Maximum PUSCH and SRS concurrency (i.e., 10) exceeds the number of main pool threads (i.e., 9)".
# These are upper-PHY/upper-layer threads, NOT the hard real-time RU/OFH ones, so they may live
# on the second socket; only nof_cores caps them.
nof_threads: 16
affinities:
main_pool_cpus: 12,13,14,15,16,17,18,19,20,21,22,23,36,37,38,39,40,41,42,43,44,45,46,47
ofh:
txrx_cpus: ["5,6,7,8"]
cell_affinities:
- ru_cpus: 3,4
The CPU lists are for a 2× Xeon Gold 6126 host with cores 3–11 and their hyperthread siblings
27–35 isolated. main_pool_cpus must exclude the siblings of the RU/OFH cores as well as the
cores themselves; no counter reports the contention if it does not. Keep all_level: warning: at
info srsRAN logs every scheduled channel in every slot and fills the root file system. The
metrics and pcap sections of the file are omitted above.
RU-side golden for OCUDU (osc-benetel-ocudu.txt, captured 2026-09-22): M-Plane disabled, and:
### RU_CONFIG.CFG (full, sorted)
bandwidth_hz=100000000
c_plane_du_mac=00:11:22:33:44:66
c_plane_du_vlan=4
centre_frequency_hz=3750000000
compression=dynamic_compressed
cplane_per_symbol_timing=false
cplane_per_symbol_workaround=disabled
cuplane_dl_coupling_sectionID=disabled
dl_tuning_special_slot=0x13b6
downlink_scaling=0
dpd_reset_timer=43200
flexran_prach_workaround=disabled
lf_prach_compression_enable=true
lf_prach_slot_id=0
m_plane_u_plane_config_v16=true
mimo_mode=1_2_3_4_4x2
non_ideal_c4_timing_enable=false
prach_format=short
prach_freq_offset=0
prach_freq_offset_dynamic=true
prach_msg1_freq_start=0
special_slots_symbols1=
special_slots_symbols2=
special_slots_symbols=DDDDDDGGGGUUUU
synce_enable=false
tdd_pattern_1=DDDDDDDSUU
tdd_pattern_2=DDDDDDDSUU
tdd_switching=1500
tx_power_dbm=35.000000
u_plane_du_mac=00:11:22:33:44:66
u_plane_du_vlan_downlink=4
u_plane_du_vlan_uplink=4
ul_gain_correction=0
### REGISTERS
C0300 = Register 0xc0300, Value : 0x1010101
C0303 = Register 0xc0303, Value : 0x20e
C0315 = Register 0xc0315, Value : 0x22334466
C0316 = Register 0xc0316, Value : 0x11
C0318 = Register 0xc0318, Value : 0x4
C0319 = Register 0xc0319, Value : 0x22334466
C031A = Register 0xc031a, Value : 0x11
C0322 = Register 0xc0322, Value : 0x7
C0328 = Register 0xc0328, Value : 0x3
C032A = Register 0xc032a, Value : 0x3
C0330 = Register 0xc0330, Value : 0x4
C0331 = Register 0xc0331, Value : 0x4
C0350 = Register 0xc0350, Value : 0x1
C0351 = Register 0xc0351, Value : 0x1
C0352 = Register 0xc0352, Value : 0x1
C0353 = Register 0xc0353, Value : 0x1
C0356 = Register 0xc0356, Value : 0x0
C0358 = Register 0xc0358, Value : 0x0
C0366 = Register 0xc0366, Value : 0x1500
C037B = Register 0xc037b, Value : 0x1
DDDDDDDSUU is the RU's own category A default; any other pattern in standalone mode makes its boot
log report "TDD Pattern is out of range". The OCUDU vendor guide for this radio requires 4x2,
dynamic BFP-9 and this pattern together. The full walkthrough, including a three-mode (manual /
Ansible / Jupyter) bundle, is OCUDU over a commercial O-RU.
Duranta's monolithic gNB (nr-softmodem, CU and DU in one process) drives the Benetel over the
O-RAN 7.2 fronthaul library (fhi_72, xran) with the M-Plane variant of the transport library, and
is the NETCONF client for the whole life of the cell.
Files in the Duranta image. Base configuration /root/oru/gnb-benetel.conf; bring-up
/root/benetel-bringup.sh; the O-RU key /root/oru/ssh_keys/id_ed25519 (ships in the image); the
host deriver /root/oai72-host.py, which renders /root/oru/gnb-benetel.<host>.conf with this
server's virtual function (VF) and real-time cores; the golden
/root/oru-setup/golden/osc-benetel-duranta.txt. The bring-up also points
liboai_transpro.so at liboran_fhlib_5g_mplane.so, discovers the AMF address from the running
OAI CN5G containers, and requires the performance CPU governor.
# on the DU host, after the RU is cold-cycled and PTP is locked
/root/benetel-bringup.sh
gNB antenna block as shipped (/root/oru/gnb-benetel.conf, duranta-20260927 onward):
////////// Physical parameters (4x4, 2 layers — matches Benetel RAN650):
pdsch_AntennaPorts_XP = 2;
pdsch_AntennaPorts_N1 = 2;
pusch_AntennaPorts = 4;
maxMIMO_layers = 4;
do_CSIRS = 1; # CSI-RS on: without it the UE reports no rank and OAI sends ONE layer (2026-09-25)
min_rxtxtime = 6;
Note: The bring-up renders a host copy (
/root/oru/gnb-benetel.<host>.conf). On a server that
gives the DU fewer than 20 CPUs the host tool writesmaxMIMO_layers = 2anddo_CSIRS = 0there
(one downlink layer), because multi-layer downlink overloads the real-time L1 on such hosts. See
Tuning and open items.
Cell (servingCellConfigCommon, frequency, PRACH and TDD lines):
physCellId = 2;
# SSB @ 3750.24 MHz (ARFCN 650016), band n78, 273 PRB (100 MHz), PointA 646724
absoluteFrequencySSB = 650016;
dl_frequencyBand = 78;
dl_absoluteFrequencyPointA = 646724;
dl_offstToCarrier = 0;
dl_subcarrierSpacing = 1;
dl_carrierBandwidth = 273;
initialDLBWPlocationAndBandwidth = 1099;
initialDLBWPsubcarrierSpacing = 1;
initialDLBWPcontrolResourceSetZero = 11;
initialDLBWPsearchSpaceZero = 0;
ul_frequencyBand = 78;
ul_offstToCarrier = 0;
ul_subcarrierSpacing = 1;
ul_carrierBandwidth = 273;
pMax = 23;
initialULBWPlocationAndBandwidth = 1099;
initialULBWPsubcarrierSpacing = 1;
prach_ConfigurationIndex = 148;
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 0;
zeroCorrelationZoneConfig = 0;
preambleReceivedTargetPower = -100;
...
referenceSubcarrierSpacing = 1;
dl_UL_TransmissionPeriodicity = 5;
nrofDownlinkSlots = 3;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 1;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0;
L1, RU and fronthaul sections (the core numbers and dpdk_devices are rewritten per host by
oai72-host.py):
L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
prach_dtx_threshold = 100;
pucch0_dtx_threshold = 80;
pusch_dtx_threshold = 10;
tx_amp_backoff_dB = 12; # needs to match O-RU configuration
L1_rx_thread_core = 8;
L1_tx_thread_core = 10;
phase_compensation = 0; # needs to match O-RU configuration
}
);
RUs = (
{
local_rf = "no";
nb_tx = 4;
nb_rx = 4;
att_tx = 35;
att_rx = 0;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
sf_extension = 0;
eNB_instances = [0];
sl_ahead = 10;
tr_preference = "raw_if4p5"; # important: activate FHI7.2
do_precoding = 0; # needs to match O-RU configuration
}
);
# ---- O-RAN 7.2 fronthaul to the Benetel RAN650 (M-Plane over NETCONF) ----
fhi_72 = {
dpdk_iova_mode = "VA";
dpdk_mem_size = 16384;
dpdk_devices = ("0000:12:01.0"); # srv19 DATA1a (E810) VF
system_core = 3;
io_core = 5;
worker_cores = (7, 9);
du_addr = ("00:11:22:33:44:66");
du_key_pair = ("/root/oru/ssh_keys/id_ed25519.pub", "/root/oru/ssh_keys/id_ed25519");
ru_addr = ("8c:1f:64:d1:11:f0"); # Benetel RAN650
vlan_tag = (4);
ru_username = ("oranbenetel");
ru_ip_addr = ("10.3.12.20"); # Benetel M-Plane
mtu = 9216;
file_prefix = "fhi_72";
fh_config = ({
T1a_cp_dl = (419, 470);
T1a_cp_ul = (285, 336);
T1a_up = (294, 345);
Ta4 = (0, 200);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
});
};
RU-side golden for Duranta (osc-benetel-duranta.txt, captured 2026-09-22): M-Plane
enabled, and:
### RU_CONFIG.CFG (full, sorted)
bandwidth_hz=100000000
c_plane_du_mac=00:11:22:33:44:66
c_plane_du_vlan=4
centre_frequency_hz=3750000000
compression=static_compressed
cplane_per_symbol_timing=false
cplane_per_symbol_workaround=disabled
cuplane_dl_coupling_sectionID=disabled
dl_tuning_special_slot=0x13b6
downlink_scaling=0
dpd_reset_timer=43200
flexran_prach_workaround=disabled
lf_prach_compression_enable=true
lf_prach_slot_id=0
m_plane_u_plane_config_v16=true
mimo_mode=1_2_3_4_4x4
non_ideal_c4_timing_enable=false
prach_format=short
prach_freq_offset=0
prach_freq_offset_dynamic=true
prach_msg1_freq_start=0
special_slots_symbols1=
special_slots_symbols2=
special_slots_symbols=DDDDDDGGGGUUUU
synce_enable=false
tdd_pattern_1=DDDSU
tdd_pattern_2=DDDSU
tdd_switching=1500
tx_power_dbm=35.000000
u_plane_du_mac=00:11:22:33:44:66
u_plane_du_vlan_downlink=4
u_plane_du_vlan_uplink=4
ul_gain_correction=0
### REGISTERS
C0300 = Register 0xc0300, Value : 0x1010101
C0303 = Register 0xc0303, Value : 0x20e
C0315 = Register 0xc0315, Value : 0x22334466
C0316 = Register 0xc0316, Value : 0x11
C0318 = Register 0xc0318, Value : 0xe004
C0319 = Register 0xc0319, Value : 0x22334466
C031A = Register 0xc031a, Value : 0x11
C0322 = Register 0xc0322, Value : 0x7
C0328 = Register 0xc0328, Value : 0x3
C032A = Register 0xc032a, Value : 0xf
C0330 = Register 0xc0330, Value : 0x4
C0331 = Register 0xc0331, Value : 0x4
C0350 = Register 0xc0350, Value : 0x0
C0351 = Register 0xc0351, Value : 0x0
C0352 = Register 0xc0352, Value : 0x0
C0353 = Register 0xc0353, Value : 0x1
C0356 = Register 0xc0356, Value : 0x0
C0358 = Register 0xc0358, Value : 0x0
C0366 = Register 0xc0366, Value : 0x1500
C037B = Register 0xc037b, Value : 0x1
The full walkthrough is Duranta over a commercial O-RU.
| Setting | Duranta | OCUDU | Why they differ |
|---|---|---|---|
| RU M-Plane mode | enabled | disabled | Duranta is a NETCONF client and must hold the session; srsRAN has no NETCONF client |
| PRACH eAxC | from the RU's M-Plane advertisement (M-Plane map: 8, 9) | 4, 5 | the stored mode changes the RU's PRACH map |
mimo_mode |
1_2_3_4_4x4 |
1_2_3_4_4x2 |
Duranta drives four DL ports; the OCUDU vendor guide specifies 4x2 |
compression / DU header |
static_compressed / static |
dynamic_compressed / enable_*_static_compr_hdr: false |
each side must match the other; a mismatch corrupts every U-plane section with clean counters |
PRACH receive paths C032A |
0xf (four) |
0x3 (two) |
derived by the RU from mimo_mode |
| TDD (RU and DU) | DDDSU, 2.5 ms |
DDDDDDDSUU, 5 ms |
Duranta's reference frame; OCUDU follows the RU's category A default |
| DL ports / antennas | 4 (nb_tx = 4), 4 layers with CSI-RS |
dl_port_id: [0, 2], nof_antennas_dl: 2 |
OCUDU uses the two-port layout of the published working RAN650 srsRAN configuration |
| PRACH configuration index | 148 | 159 | each stack's validated value for its frame |
| Carrier definition | Point A 646724, SSB 650016 | dl_arfcn: 650000 |
same 3750 MHz centre; OAI takes explicit Point A/SSB, srsRAN derives them |
| Ta4 window | 0–200 µs | 0–1960 µs | the OCUDU value is the one validated on COSMOS O-RUs with srsRAN |
| DL gain knob | att_tx = 35, tx_amp_backoff_dB = 12 |
iq_scaling: 5.5 |
different mechanisms; both kept low for metres-scale range |
| MCS table | OAI default | qam64 (PDSCH and PUSCH) |
at high CQI srsRAN's 256QAM choice left DL BLER at 21–26 % |
| RU restart | cold power cycle from your fronthaul console | in-RU reboot from ocudu-72_cycle.sh; cold cycle after a golden restore that rewrote ru_config.cfg |
warm reboots leave Duranta's M-Plane path mis-timed |
| Golden | osc-benetel-duranta.txt |
osc-benetel-ocudu.txt |
the persistent RU state each stack was validated with |
| APN on the UE | COSMOS-D convention (OAI CN5G) |
COSMOS-O (Open5GS), internet (SD-Core) |
one APN per stack, so a modem's stack is obvious |
One UE, iperf3 receiver-side, n78 100 MHz. The UE interface matters: a modem on USB 2.0 caps the
application rate at about 300 Mbit/s even when the MAC delivers more. Rows marked 1 layer are
Duranta without do_CSIRS = 1.
Duranta (OAI CN5G)
| DU CPU platform | Date | Image | UE | Config | DL (Mbit/s) | UL (Mbit/s) |
|---|---|---|---|---|---|---|
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-27 | duranta-20260927 (host tool → 1 layer) |
SimCom SIM8200 on USB 3 | 1 layer, software LDPC | UDP ceiling 348; TCP 208 (1 stream) / 145 (4) / 112 (8) | UDP 60.8; TCP 50.0–53.2 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-27 | duranta-20260927 (host tool → 1 layer) |
SimCom SIM8200 on USB 3 | 1 layer, LDPC on Intel ACC100 | UDP ceiling 367; TCP 221 (1) / 136 (4) / 119 (8) | UDP 59.2; TCP 48.3–52.2 |
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 2026-09-25 | duranta-20260925 + CSI-RS lines |
SimCom SIM8200 on USB 3 | 4 layers (maxMIMO_layers = 4, do_CSIRS = 1), RI 4, DL MCS 19 |
830 UDP (1 Gbit/s offered); 601 UDP at 600 Mbit/s offered (1.5 % loss); TCP 186–205 | 63 UDP; TCP 57–62 |
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 2026-09-25 | duranta-20260925 + CSI-RS lines |
Quectel on USB 2.0 | 4 layers | 218 TCP | 59.8 TCP |
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 2026-09-25 | duranta-20260925 |
Quectel on USB 2.0 | maxMIMO_layers = 4, no CSI-RS: 1 layer |
297 UDP; TCP 184 (1 stream) – 252 (8 streams) | 67.7 UDP; TCP 62–64 |
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 2026-09-25 | duranta-20260925 |
Quectel on USB 2.0 | 2 layers configured, no CSI-RS: 1 layer; software LDPC / Intel ACC100 | 209 / 209 TCP (1 stream) | 64.4 / 63.5 TCP |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-24/25 | not recorded | Quectel on USB 2.0 | 1 layer, software LDPC | 182–214 | 58.5–63.3 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-24/25 | not recorded | Quectel on USB 2.0 | 1 layer, LDPC on Intel ACC100 | 186–206 | 60.8–62.0 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-22 | not recorded | Quectel on USB 2.0 | 1 layer, golden restored | 186–218 | 57–61 |
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 2026-09-14 | not recorded | Quectel | 1 layer | 222–261 | 51.4–54.9 |
| 2× Intel Xeon Gold 6226, 24 cores / 24 threads | 2026-09-14 | not recorded | Quectel | 1 layer | 270–287 | 50.0–50.2 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-11 | duranta-20260907c |
Amarisoft lteue, 1 UE |
1 layer | 143 | 57.1 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-07 | duranta-20260907b |
Quectel | 1 layer | 268 | 64.6 |
OCUDU
| DU CPU platform | Date | Image | Core / UE | DL (Mbit/s) | UL (Mbit/s) | Notes |
|---|---|---|---|---|---|---|
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-24/25 | not recorded | Quectel on USB 2.0 | 169–175 | 76.7–77.5 | socket fronthaul, software LDPC |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-24/25 | not recorded | Quectel on USB 2.0 | 145–150 | 76.7–77.0 | DPDK fronthaul, software LDPC |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-24/25 | not recorded | Quectel on USB 2.0 | 141–173 | 76.7–76.8 | DPDK fronthaul, LDPC on Intel ACC100 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-22 | ocudu-20260916 |
Open5GS / Quectel | 209–220 | 78 | golden restored |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-22 | ocudu-20260916 |
Open5GS / Quectel on USB 2.0 | 141–150 | 74 | golden restored |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-22 | ocudu-20260916 |
Aether SD-Core / Quectel on USB 2.0 | 189–214 | 74 | CQI 15, RI 2, MCS 28, BLER 0 |
| 2× Intel Xeon Gold 6226, 24 cores / 24 threads | 2026-09-16 | ocudu-20260915 |
Open5GS / Quectel | 106–111 | 79.3–79.6 | three-mode parity; RSRP −69, SINR 25 |
| 2× Intel Xeon Gold 6226, 24 cores / 24 threads | 2026-09-14 | ocudu-20260909b |
Open5GS / Quectel | 101–109 | 78–80 | three-mode bundle; RSRP −70, SINR 25 |
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 2026-09-14 | ocudu-20260909b |
Open5GS / Quectel | 104 | 79.8 | three-mode bundle, Ansible mode; RSRP −70, SINR 26 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 2026-09-09 | ocudu-20260909b |
Open5GS / Quectel | 248 | 77.4 | manual procedure; 18 isolated cores |
Multi-layer downlink needs CSI-RS and enough CPU. Without do_CSIRS = 1 the gNB sends no
channel-state-information reference signals, the UE reports no rank indicator (RI), and OAI
schedules one layer: MAC goodput is pinned at about 388 Mbit/s (one layer × 273 PRB, every DL slot),
whatever maxMIMO_layers says. With maxMIMO_layers = 4 and do_CSIRS = 1 the UE reports
CSI [CQI 11 RI 4] and the downlink carries four layers — but only on a server with enough cores
for the DU. Measured on this radio:
| DU CPU platform | CPUs the DU gets | 4 layers + CSI-RS | 1 layer |
|---|---|---|---|
| 1× AMD EPYC 9355P, 32 cores / 32 threads | 25 | stable: UDP DL 822–828 Mbit/s (cell ceiling, MCS 19), TCP DL ~200 | UDP DL ~300 |
| 2× Intel Xeon Gold 6126, 24 cores / 48 threads | 10 (NIC socket only) | DU dies under load (real-time L1 falls behind: iavf segfault or xran PRACH-queue assertion), also with ACC100, also at 2 layers | stable: UDP DL 348–367, TCP DL 208–221 |
The Duranta image (duranta-20260927 onward) therefore ships the configuration with
maxMIMO_layers = 4 and do_CSIRS = 1, and the bring-up's host tool (/root/oai72-host.py) decides
per server: with at least 20 CPUs for the DU it keeps four layers; with fewer it renders the proven
single-layer settings (maxMIMO_layers = 2, do_CSIRS = 0) into the host copy of the
configuration. Force either with DURANTA_DL_LAYERS=4 or =1 in the environment of the bring-up.
Every upstream Duranta Benetel sample configuration sets do_CSIRS = 1.
Duranta TCP downlink stays near 200 Mbit/s (open). With four layers UDP reaches 830 but TCP
gives 186–205. It is not the TCP window (64 MB receive buffer), not the UE CPU, and not buffering
(loaded RTT 21 ms equals idle). Under TCP the DU schedules about half the slots, DL MCS falls to
11–13 with BLER 0.1–0.2 (19 and about 0 under UDP), and the uplink carrying the TCP ACKs runs at
NPRB 5 with 6–9 % BLER. Next: the outer-loop link adaptation (OLLA) BLER target and the uplink grant
size for ACK traffic.
UE interface. The Quectel on node1.osc sits on a USB 2.0 controller and caps application
throughput at about 287–306 Mbit/s. Four-layer Duranta numbers need a modem on USB 3.
OCUDU uses two of the four DL branches. The validated OCUDU configuration is
dl_port_id: [0, 2], nof_antennas_dl: 2, RU mimo_mode=1_2_3_4_4x2 (RI 2 measured). A four-port
OCUDU downlink on this radio has not been validated.
OCUDU link adaptation. mcs_table: qam64 gives 0 % DL BLER where the 256QAM table left
21–26 %; the gain in peak rate from 256QAM at a lower iq_scaling or a different OLLA target has
not been measured.
| Symptom | Cause | Fix |
|---|---|---|
Cell configured, PTP locked, every counter healthy, no RF (No dBm) |
C0300 (number of transmitters) reads 0 |
write 0x01010101 (oru-apply.py … --apply); read registers twice before trusting them |
| OCUDU: no PRACH detected, DL/UL fronthaul clean, no UE attaches | RU left in M-Plane mode, PRACH on eAxC 8, 9 while the DU asks on 4, 5 | bash /root/benetel-ru-mode.sh nomplane or restore the OCUDU golden; do not change prach_port_id/ul_port_id to follow an observed eAxC |
| Good RSRP, CQI 2, DL about 3 Mbit/s, about 75 % DL BLER (OCUDU) | RU still carries Duranta's mimo_mode 1_2_3_4_4x4 and DDDSU |
diff and restore the golden, then power-cycle the RU |
Duranta: PRACH detected, every Msg3 lost (RA failed at state WAIT_Msg3) |
RU's own tdd_pattern_* differs from the DU's DDDSU; M-Plane does not push TDD |
set tdd_pattern_1/tdd_pattern_2 = DDDSU, special DDDDDDGGGGUUUU (the Duranta golden), cold-cycle; recheck after any firmware flash |
Duranta: cell up but UL early/late and UEs drop (ulsch_DTX 100), or RU0 mu0 and no RF |
RU was warm-rebooted, not power-cycled | power-cycle from your fronthaul console; port 830 should take about 300 s to reopen |
| DU restarted, RU silent although all registers read correct | the RAN650 only starts transmitting on a fresh boot against a locked clock | lock PTP, stop the DU, restart the RU, then start the DU |
Uplink collapses to kbit/s; one RX branch reads 0.000000 dBFS |
ul_gain_correction too high for metres-scale range (factory 18) |
ul_gain_correction=0. Allowed values are 0, 6, 12, 18; a value outside that (24) hangs mplane.service at "Waiting for radio to be initialized" until reverted |
| DL BLER stuck at 20–30 %, OLLA several dB negative (OCUDU) | iq_scaling too high clips |
iq_scaling: 5.5 |
| Perfect downlink, deaf uplink after "applying the known-good register set" | category B values from an older firmware written over the RU's own C0303/C0366/C0358 |
never write self-configured registers; the RU's /tmp/logs/radio_status lists what it set. Registers persist across reboot until explicitly undone |
OCUDU: DU receives nothing (ether_rx rx_bytes 0) while tcpdump shows frames |
fronthaul NIC not promiscuous; the raw socket misses VLAN-offloaded frames | put DATA1a in promiscuous mode (the bring-up does) |
| OCUDU: fronthaul timing degraded with clean counters | main_pool_cpus includes the hyperthread siblings of the RU/OFH cores |
exclude the siblings (see the configuration above) |
| Duranta: xran PRACH assert on start | CPU governor powersave |
set the performance governor (the bring-up requires it) |
| TX3/TX4 go offline | oru_dpd_reset run on a working radio |
do not run it; a full power cycle recovers |
| PTP never reaches SLAVE; fronthaul blocked | PTP management messages reflected by single-port ptp4l instances and re-flooded by the fabric |
cosmos-fh-ptp-guard (egress drop of management messages) on the DU host |
The RU does not answer on 10.3.12.20 |
the unit has moved address before | find it by MAC 8c:1f:64:d1:11:f0 |
/opt/duranta/targets/PROJECTS/GENERIC-NR-5GC/CONF/*benetel* in the image.Author(s): COSMOS team · Last reviewed: 2026-09-25 · Tags: oran, o-ru, 7.2, fronthaul, benetel, ran650, m-plane, netconf, ocudu, duranta, ptp, hardware