The Foxconn RPQN-7801 is a commercial O-RAN radio unit (O-RU) for band n78 with four transmit and four
receive chains. It has no M-Plane client: it runs from a configuration file stored on the radio
(/home/root/test/RRHconfig_xran.xml, "file mode"), and both open-source O-DU stacks on COSMOS —
OCUDU (srsRAN) and Duranta (OAI) — drive it with the RU in that mode. Current status: no UE attaches
with either stack. The fronthaul, timing and downlink work; the attach fails at different points on
the two stacks (see Current status).
Status: not attaching. OCUDU last tested 2026-09-14, Duranta last tested 2026-09-05. For a
working commercial-O-RU rig use the Benetel RAN650 or the LiteOn FlexFi from the
O-RU overview.
| OCUDU (srsRAN) — 2026-09-14 | Duranta (OAI) — 2026-09-05 | |
|---|---|---|
| RU Precision Time Protocol (PTP) lock | works — state=3, rms 5–13 ns |
works |
| RU C/U-plane activation (latch) | works — RRH_state=DATA_EXCHANGING, c_on climbing |
works — RU Latch 0→9→1 |
| Fronthaul receive at the DU | works — 0 Open Fronthaul (OFH) drops with enable_ul_static_compr_hdr: true |
works — PUSCH U-plane on eAxC 0–3, RX Timing on time climbing |
| N2 (gNB ↔ AMF) | works | works — NGSetupResponse, cell in service |
| Downlink / cell detection | blocked — no UE sees the cell; the RU logs repeated AD9025 PA protection error at iq_scaling: 1.0 |
works — Quectel camps at RSRP −50 to −67 dBm, LIMSRV |
| Random access (PRACH) | not reached | blocked — the UE never starts registration (+C5GREG: 0,0) and the RU forwards no PRACH U-plane on any eAxC while the DU sends PRACH C-plane every PRACH slot |
| Registration / PDU session / data | not reached | not reached |
The same RU and the same OCUDU DU completed a full attach, PDU session and iperf3 run on 2026-08-19
(see Performance); that result does not reproduce on the current rig.
Other O-RUs: fleet overview · Benetel RAN650 · LiteOn FlexFi · Foxconn RPQN-7801 · Software O-RUs
| Model / SKU | Foxconn RPQN-7801E (product 5G-RHUB-V1); RF range read from the unit's EEPROM: 3650–3850 MHz |
| Band / range | n78, 3650–3850 MHz |
| Bandwidth / PRB / SCS | 100 MHz, 273 PRB (RRH_MAX_PRB = 273), 30 kHz subcarrier spacing (µ=1; RRH_SLOT_TICKS_IN_SEC = 2000) |
| Duplex / TDD | TDD; the TDD pattern is set by the DU (the RU file has no TDD key) |
| Antennas | 4T4R (RRH_TRX_EN_BIT_MASK = 0xf, RRH_RF_EN_BIT_MASK = 0xf) |
| Max TX power | 24 dBm per branch (RRH_TX_POWER = 24, 24; range 4–24 dBm); TX attenuation 24.0 dB per layer (must stay above 10 dB) |
| Firmware | v3.1.15q.551v0706 (engineering build eng_v3_1_15q) |
| Fronthaul | O-RAN 7.2x split, eCPRI over Ethernet; C-plane and U-plane on VLAN 4; block floating point (BFP) 9-bit for PDSCH/PUSCH and PRACH, no udCompHdr (RRH_CMPR_HDR_PRESENT = 0) |
| M-Plane | none used. Port 830 is an SSH shell into the RU (legacy key exchange); port 22 is always refused. No NETCONF configuration is applied by either DU |
| Timing | PTP G.8275.1, multicast over 10 G (RRH_PTPV2_GRAND_MASTER_MODE = 3), domain 24; DU-side windows in Fronthaul mapping |
| Address / MAC | 10.3.16.1; RU MAC 6c:ad:ad:00:0d:60; the RU sends all uplink to DU MAC 00:11:22:33:44:66 |
| Power-control target | foxconn-oru1.instrument.orbit-lab.org from your fronthaul console, the console your O-RU reservation targets (on, offh, reset) |
| PCI on COSMOS | 3 (Benetel uses 2, LiteOn 1 — unique per O-RU) |
The RPQN-7801 has no M-Plane client, so neither DU configures it. Everything the radio needs comes
from its own file, /home/root/test/RRHconfig_xran.xml, which is read when the C/U-plane is
activated. The DU configuration has to mirror that file by hand — carrier, bandwidth, MACs, VLAN,
compression and eAxC numbers must agree value for value.
What the RU sets itself (from the file): LO frequency (3750 MHz), maximum PRB, TX power and
attenuation, RX attenuation, compression, VLAN tags, the eAxC table, digital pre-distortion (DPD) and
closed-loop gain control, and its PTP client settings.
What the DU must set: the cell (ARFCNs, PointA, SSB, TDD pattern, PRACH), the fronthaul timing
windows, the DU-side eAxC mapping, and the DL IQ amplitude.
Activation. init_rrh_config_enable_cuplane (a compiled program in /home/root/test/) reads the
file, validates the carrier (Setting of LO1 and PRB is valid, Setting of Tx attenuation is valid)
and enables the C/U-plane. It also writes the RU's PTP configuration /tmp/ptp4l_user_gen.cfg, which
every RU reboot wipes. Other RU tools in the same directory: rrh_get_cuplane_status (latch and DPD
status), reset_cuplane, rrh_reconfig_rf_param (applies RF parameters such as TX attenuation to a
running RU), pa_control, tx_recover.sh.
Credentials. The RU shell uses a vendor-default root login; ask problems@cosmos-lab.org for
access. The shell is reached with legacy SSH algorithms:
ssh -p 830 -o KexAlgorithms=+diffie-hellman-group14-sha1 \
-o HostKeyAlgorithms=+ssh-rsa root@10.3.16.1
Golden state. Both stacks use the same RRHconfig_xran.xml, so the RU does not carry per-stack
state the way the Benetel does, and no golden capture is committed for this unit. The file below is
the reference; diff the live file against it before a run.
Bring-up order (current procedure, the one used on 2026-09-14). The RU runs a hardware watchdog
(rrh_hw_watchdog) that resets it every 10–15 minutes when it is idle or half set up, so the whole
sequence has to run without gaps, and the DU is started exactly once:
omf tell -a reset -t foxconn-oru1.instrument.orbit-lab.org. If it does not answer ping a minuteoffh, wait ~25 s, on./tmp/ptp4l_user_gen.cfg to exist on the RU.ptp4l once (the boot-time instance does not lock) and wait for state=3;ptp4l must be left running.init_rrh_config_enable_cuplane in the background on the RU and wait for core1 is running.configs/ocudu-foxconn-72/fx_relatch.sh in the duranta-cosmos repository runs steps 2–5 for
OCUDU from the DU host. The killall in it runs inside the O-RU's embedded Linux and stops only the
RU's own PTP daemons; do not use killall on COSMOS servers.
Is it radiating? Read c_on in /var/log/rrh_log_print/rrh_log_print.log (grep -a xRN):
c_on must climb with c_early, c_late and err_tci/ecpri/port/sct at 0. err_total is not a
rejection counter (it is high on working runs too), and core1 is running is not proof of
radiation. Check the log's timestamp first — a stale log shows a flat c_on. The RU's port 830 can
become unreachable while a DU is streaming, so start any RU-side sampling before the DU.
/home/root/test/RRHconfig_xran.xml)This is the live file on the RU, as committed in configs/foxconn-rru/RRHconfig_xran.xml:
<!-- -->
<!-- Common -->
<!-- -->
<!-- RRH_DST_MAC_ADDR: Destination MAC address, fill with 6 bytes and separate each others by colon -->
RRH_DST_MAC_ADDR = 00:11:22:33:44:66
<!-- RRH_SRC_MAC_ADDR: Source MAC address, fill with 6 bytes and separate each others by colon -->
RRH_SRC_MAC_ADDR = 6c:ad:ad:00:0d:60
<!-- RRH_EN_EAXC_ID: Enable using eAxC ID field defined in O-RAN spec. -->
<!-- When 0 is set, RU port ID=0,1,2,3 are used for PDSCH/PUSCH if RRH_TRX_EN_BIT_MASK = 0x0F -->
<!-- When 0 is set, RU port ID=4,5,6,7 are used for PRACH if RRH_TRX_EN_BIT_MASK = 0x0F -->
<!-- When 0 is set, RU port ID=0,1 are used for PDSCH/PUSCH if RRH_TRX_EN_BIT_MASK = 0x03 -->
<!-- When 0 is set, RU port ID=2,3 are used for PRACH if RRH_TRX_EN_BIT_MASK = 0x03 -->
RRH_EN_EAXC_ID = 1
<!-- RRH_EAXC_ID_TYPE1: Specify the eAxC ID for type1 message -->
RRH_EAXC_ID_TYPE1 = 0x0, 0x1, 0x2, 0x3
<!-- RRH_EAXC_ID_TYPE3: Specify the eAxC ID for type3 message -->
RRH_EAXC_ID_TYPE3 = 0x4, 0x5, 0x6, 0x7
<!-- RRH_EN_SPC: Enable SPC or not, 0:OFF, 1:ON -->
RRH_EN_SPC = 1
<!-- RRH_LTE_OR_NR: Indicate the spec of xRAN, 0:LTE, 1:NR -->
RRH_LTE_OR_NR = 1
<!-- RRH_TRX_EN_BIT_MASK: Bit-mask of 4 TRx, bit 0: TRx0, bit1: TRx1, bit2: TRx2, bit3: TRx3 -->
RRH_TRX_EN_BIT_MASK = 0xf
<!-- RRH_RF_EN_BIT_MASK: Bit-mask of 4 PA/LNA, bit0: PA0/LNA0, bit1: PA1/LNA1, bit2: PA2/LNA2, bit3: PA3/LNA3 -->
RRH_RF_EN_BIT_MASK = 0xf
<!-- RRH_CMPR_HDR_PRESENT: Indicate the UdCompHdr/reserved field is present or not, 0:no present; 1:present -->
RRH_CMPR_HDR_PRESENT = 0
<!-- RRH_CMPR_TYPE: Indicate compress type. 1st for PDSCH/PUSCH, 2nd for PRACH. 0: No Cmpr; 1:block-floating -->
RRH_CMPR_TYPE = 1, 1
<!-- RRH_CMPR_BIT_LENGTH: Indicate the bit length after compression. 1st for PDSCH/PUSCH, 2nd for PRACH. -->
RRH_CMPR_BIT_LENGTH = 9, 9
<!-- RRH_TX_TRUNC_BITS: The extra truncation in fractional part of IFFT output -->
RRH_TX_TRUNC_BITS = 4
<!-- RRH_RX_TRUNC_BITS: The extra truncation in fractional part of FFT output -->
RRH_RX_TRUNC_BITS = 5
<!-- RRH_MAX_PRB: Maximum PRBs -->
RRH_MAX_PRB = 273
<!-- RRH_C_PLANE_VLAN_TAG: C-plane V-LAN tag express by hex number -->
RRH_C_PLANE_VLAN_TAG = 0x0004
<!-- RRH_U_PLANE_VLAN_TAG: U-plane V-LAN tag express by hex number -->
RRH_U_PLANE_VLAN_TAG = 0x0004
<!-- RRH_SLOT_TICKS_IN_SEC: Number of slot tick in a second (2000 slots for u=1) -->
RRH_SLOT_TICKS_IN_SEC = 2000
<!-- RRH_SLOT_PERIOD_IN_SAMPLE: Slot period in 122.88MHz (61440 for u=1) -->
RRH_SLOT_PERIOD_IN_SAMPLE = 61440
<!-- RRH_LO_FREQUENCY_KHZ: Tx and Rx PLL LO Frequency in kHz(internal or external LO) -->
RRH_LO_FREQUENCY_KHZ = 3750000, 0
<!-- RRH_TX_POWER: Target Tx power (Default=24dBm. Range:24dBm ~ 4dBm. It can be applied only when Tx power of a RRH is calibrated) -->
RRH_TX_POWER = 24, 24
<!-- RRH_TX_ATTENUATION: Tx attenuation value with 1-digit fraction for each layer (>10dB. NOTE: The attenuation value must be larget than 10dB) -->
RRH_TX_ATTENUATION = 24.0, 24.0, 24.0, 24.0
<!-- RRH_RX_ATTENUATION: Rx attenuation value with 1-digit fraction for each layer (<30dB) -->
RRH_RX_ATTENUATION = 0.0, 0.0, 0.0, 0.0
<!-- RRH_BB_GENERAL_CTRL: General control words for Baseband -->
<!-- Bit[0] of 1st word: Enable the filtering of MAC address -->
<!-- Bit[1] of 1st word: Enable the UL slot tick packets per port -->
<!-- Others: Reserved -->
RRH_BB_GENERAL_CTRL = 0x3, 0x0, 0x0, 0x0
<!-- RRH_RF_GENERAL_CTRL: General control words for RF -->
<!-- Bit[2:0] of 1st word: 7=DPD ON and init port by RRH_RF_EN_BIT_MASK, 3=DPD ON, 0=DPD off -->
<!-- Bit[0] of 2st word: 1=CLGC ON, 0=CLGC off -->
<!-- Bit[0] of 4th word: 1=for N77, 0=else -->
RRH_RF_GENERAL_CTRL = 0x3, 0x1, 0x0, 0x0
<!-- -->
<!-- PTPV2 Related -->
<!-- -->
<!-- RRH_PTPV2_GRAND_MASTER_MODE: 0: Unicast over 1G, 1:Multicast over 1G; 2: Unicast over 10G; 3: Multicast over 10G -->
RRH_PTPV2_GRAND_MASTER_MODE = 3
<!-- RRH_PTPV2_JITTER_LEVEL: The estimated jitter of PTP time packets. 0:direct connection to GM/BC, 1:light, 2:medium, 3:heavy -->
RRH_PTPV2_JITTER_LEVEL = 0
<!-- RRH_PTPV2_VLAN_ID: VLAN ID of PTPv2. 0/1: No VLAN of PTPv2; [2~4092]: valid VLAN of PTPv2; >4092: Invalid and no VLAN will be applied -->
RRH_PTPV2_VLAN_ID = 1
<!-- RRH_PTPV2_IP_MODE: 4: IPv4 (default); 6: IPv6. Note: this configuration must be defined before RRH_PTPV2_GRAND_MASTER_IP -->
RRH_PTPV2_IP_MODE = 4
<!-- RRH_PTPV2_GRAND_MASTER_IP: IP address of grand-master -->
RRH_PTPV2_GRAND_MASTER_IP = 192.167.27.150
<!-- RRH_PTPV2_SUB_DOMAIN_NUM: The sub-domain number -->
RRH_PTPV2_SUB_DOMAIN_NUM = 24
<!-- RRH_PTPV2_ACCEPTED_CLOCK_CLASS: The acceptable clockClass threshold [6~248] -->
RRH_PTPV2_ACCEPTED_CLOCK_CLASS = 135
<!-- RRH_TRACE_PERIOD: The period of trace log. It can be applied only when the start-trace-logs of M-plane is enabled -->
RRH_TRACE_PERIOD = 0
<!-- RRH_CLGC_EXPECTED_LOOP_GAIN: The clgc excepted loop gain: 0xFF: enable clgc after receive cu-plane data 300s, other value: use this value to enable clgc on dpd init -->
RRH_CLGC_EXPECTED_LOOP_GAIN = 0xFF, 0xFF, 0xFF, 0xFF
<!-- RRH_DL_IQ_SCALING: Set DL iq scaling value that 0x0: disable dl iq scaling-->
RRH_DL_IQ_SCALING = 0x10001
<!-- RRH_CFR_PEAK_THRESHOLD: Set CFR Peak Threshold -->
RRH_CFR_PEAK_THRESHOLD = 0.5
Notes on the file:
RRH_PTPV2_GRAND_MASTER_MODE = 3 selects multicast over 10 G, so RRH_PTPV2_GRAND_MASTER_IPRRH_EAXC_ID_TYPE3 = 0x4 … 0x7 names eAxC 4–7 for PRACH, but on the wire the RU has been measuredRRHconfig_xran_default.xml:0x8, 0x9, 0xA, 0xB). See Fronthaul mapping.RRH_BB_GENERAL_CTRL bit 0 enables destination-MAC filtering: the RU accepts only frames addressedRRH_DST_MAC_ADDR.| Parameter | Value |
|---|---|
| Band | n78 |
| Centre / DL ARFCN | 3750 MHz, dl_arfcn 650000 (= RU RRH_LO_FREQUENCY_KHZ 3750000) |
| SSB | ARFCN 647328 (3709.92 MHz, on the sync raster: 3000 + 493 × 1.44 MHz) |
| PointA | ARFCN 646724 |
| SSB derived parameters (from OCUDU for this carrier) | k_SSB 4, offset pointA 30, CORESET#0 index 11, SearchSpace#0 index 0 |
| Bandwidth | 100 MHz, 273 PRB, 30 kHz SCS |
| TDD (Duranta) | 5 ms period (dl_UL_TransmissionPeriodicity = 6): 7 DL slots, special slot 6 DL / 4 UL symbols, 2 UL slots |
| TDD (OCUDU) | no tdd_ul_dl_cfg in the config — OCUDU's default pattern for this band and SCS |
| PRACH | configuration index 159, root sequence 1, zero-correlation zone 0 |
| PCI / cell id | 3 |
| RU gains | TX 24 dBm target, TX attenuation 24.0 dB per layer, RX attenuation 0.0 dB |
| UE band lock | 77:78 — the Quectel reports 3709.92 MHz as band 77, so a bare 78 lock blocks the cell |
PointA and the SSB are coupled. Take both from OCUDU's derived values (OCUDU prints "SSB derived
parameters" for any dl_arfcn) rather than adjusting either by hand: OAI refuses an SSB ARFCN that
is off the sync raster, and a PointA two ARFCN steps off (646722) leaves the SSB one subcarrier off
the grid, where a PSS correlator still sees it but no UE decodes SSS/PBCH.
| Item | OCUDU | Duranta (OAI fhi_72) |
RU file |
|---|---|---|---|
| DL eAxC | dl_port_id: [0, 1, 2, 3] |
0–3 | RRH_EAXC_ID_TYPE1 = 0x0 … 0x3 |
| UL eAxC | ul_port_id: [0, 1, 2, 3] |
0–3 | RRH_EAXC_ID_TYPE1 |
| PRACH eAxC | prach_port_id: [4, 5, 6, 7] |
prach_config = { eAxC_offset = 8; } — the RU was measured emitting PRACH on eAxC 8 and 9 |
RRH_EAXC_ID_TYPE3 = 0x4 … 0x7 |
| Compression | BFP 9 for DL, UL and PRACH | iq_width = 9, iq_width_prach = 9 |
RRH_CMPR_TYPE = 1, 1, RRH_CMPR_BIT_LENGTH = 9, 9 |
| Compression header | enable_ul_static_compr_hdr: true, enable_dl_static_compr_hdr: false |
xran default | RRH_CMPR_HDR_PRESENT = 0 |
| VLAN | vlan_tag_cp: 4, vlan_tag_up: 4 |
VLAN 4 set as the VF's port VLAN (ip link set <PF> vf 0 … vlan 4); the vlan_tag key in fhi_72 is M-Plane only |
RRH_C_PLANE_VLAN_TAG = 0x0004, RRH_U_PLANE_VLAN_TAG = 0x0004 |
| Priority (PCP) | not set | not set | not set |
| DU MAC | du_mac_addr: 00:11:22:33:44:66 on the physical function DATA1a (raw socket) |
the VF's hardware MAC, set to 00:11:22:33:44:66 after the vfio-pci bind |
RRH_DST_MAC_ADDR = 00:11:22:33:44:66 |
| DL C-plane window (T1a_cp_dl, µs) | 250–420 | 258–470 | — |
| UL C-plane window (T1a_cp_ul, µs) | 250–420 | 258–470 | — |
| DL U-plane window (T1a_up, µs) | 80–196 | 80–196 | — |
| UL reception window (Ta4, µs) | 25–1960 | 0–1960 | — |
The DL windows are srsRAN's reference values for the RPQN; ta4_max 1960 is the same value the
LiteOn needs. Under the Duranta windows the RU reports c_early=0, c_late=0.
The PRACH eAxC is not settled. The eAxC table in the RU file and the value OCUDU uses (4–7) agree,
and OCUDU completed an attach with them on 2026-08-19. A raw eAxC probe in the Duranta DU's xran
receive path (2026-08-30) read PRACH on eAxC 8 and 9 (ruPortId 8, 9), and PRACH was accepted only
with eAxC_offset = 8; only two of the four PRACH streams (prach0, prach1) carried data. Measure
the PRACH eAxC on the wire before relying on either value.
OCUDU drives the RU through its Open Fronthaul (ru_ofh) block, which sends and receives eCPRI on a
raw AF_PACKET socket bound to the physical function DATA1a — no DPDK, no VFs. The NIC must be in
promiscuous mode or the socket receives nothing (see
Real-time host preparation).
Where it lives. configs/ocudu-foxconn-72/gnb-ocudu-foxconn.yml in the duranta-cosmos
repository, copied to /root/ocudu/gnb-ocudu-foxconn.yml on the OCUDU DU host (srv18.osc). Its
expert_execution CPU sets are that host's (isolated CPUs 3-11,27-35); re-derive them for any other
host.
The config (exact, header comment omitted):
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:
t1a_max_cp_dl: 420
t1a_min_cp_dl: 250
t1a_max_cp_ul: 420
t1a_min_cp_ul: 250
t1a_max_up: 196
t1a_min_up: 80
ta4_max: 1960
ta4_min: 25
is_prach_cp_enabled: true
ignore_ecpri_payload_size: true
ignore_ecpri_seq_id: false
compr_method_ul: bfp
compr_bitwidth_ul: 9
compr_method_dl: bfp
compr_bitwidth_dl: 9
compr_method_prach: bfp
compr_bitwidth_prach: 9
enable_ul_static_compr_hdr: true
enable_dl_static_compr_hdr: false
iq_scaling: 1.0
cells:
- network_interface: DATA1a
ru_mac_addr: 6c:ad:ad:00:0d:60
du_mac_addr: 00:11:22:33:44:66
vlan_tag_cp: 4
vlan_tag_up: 4
prach_port_id:
- 4
- 5
- 6
- 7
dl_port_id:
- 0
- 1
- 2
- 3
ul_port_id:
- 0
- 1
- 2
- 3
cell_cfg:
dl_arfcn: 650000
band: 78
channel_bandwidth_MHz: 100
common_scs: 30
plmn: '00101'
tac: 7
pci: 3
sector_id: 3
nof_antennas_dl: 4
nof_antennas_ul: 4
prach:
prach_config_index: 159
prach_root_sequence_index: 1
zero_correlation_zone: 0
prach_frequency_start: 2
metrics:
enable_log: true
layers:
enable_ru: true
enable_sched: true
enable_mac: true
periodicity:
du_report_period: 1000
log:
filename: /tmp/ocudu-foxconn.log
all_level: info
ofh_level: info
pcap:
mac_enable: false
ngap_enable: false
expert_phy:
max_proc_delay: 10
expert_execution:
threads:
main_pool:
nof_threads: 16
affinities:
main_pool_cpus: 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35
ofh:
txrx_cpus:
- 5,6,7,8
cell_affinities:
- ru_cpus: 3,4
The settings that are specific to this RU:
enable_ul_static_compr_hdr: true — this firmware sends uplink without a compression header.false makes the DU drop every uplink symboldropped received Open Fronthaul message as no section was decoded correctly).ta4_max: 1960 and expert_phy.max_proc_delay: 10 — the timing values the LiteOn also needs; aboveCould not transmit RAR within the window).iq_scaling: 1.0 — see Tuning and open items.RU side for OCUDU. The same RRHconfig_xran.xml as above.
Launch. After the RU sequence in How the radio is configured, start
the DU once under a CPU mask that includes the isolated cores (srsRAN validates configured cores
against the process mask, and isolcpus removes the isolated ones from the default mask), with stdin
held open and detached from the SSH session:
cd /opt/ocudu/build
nohup setsid bash -c 'sleep 1800 | taskset -c 0-47 \
./apps/gnb/gnb -c /root/ocudu/gnb-ocudu-foxconn.yml > /tmp/g.log 2>&1' & disown
0-47 is for a 48-CPU host; use 0-$(( $(nproc --all) - 1 )) elsewhere. fx_relatch.sh does the RU
sequence and this launch in one step (through ocudu-liteon-bringup.sh with CFG= pointing at this
file).
Duranta drives the RU through OAI's fhi_72 transport: the Intel xran library on a DPDK-bound Intel
E810 virtual function (VF). The RU is in file mode, so the DU uses the static fronthaul library
(liboai_transpro.so -> liboran_fhlib_5g.so), not the M-Plane build used for the Benetel.
Where it lives. On the Duranta DU host srv19.osc: config /root/oru/gnb-foxconn-static.conf,
bring-up /root/foxconn-du-bringup.sh, RU latch /root/ru_latch.sh. The xran build on that host
carries two local changes this RU needs: a section-trailer length tolerance in xran_common.c
(num_bytes > nSectionLen + 4) and a NULL guard before the PRACH PRB-map dereference in
xran_rx_proc.c (the "frame-0" DU crash).
The config (/root/oru/gnb-foxconn-static.conf, exact; its comments were inherited from the
Benetel config and still name the Benetel, but the values — RU MAC, PCI 3, PointA, eAxC_offset 8 —
are the Foxconn's):
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
# MONOLITHIC Duranta/OAI gNB (CU+DU) + Benetel RAN650 O-RU over O-RAN 7.2, single server (srv19.osc)
# Base: osc monolithic FHI72 gNB. Radio+fhi_72 grafted from the confirmed-working sb1 Benetel config.
Active_gNBs = ( "gNB-OAI");
Asn1_verbosity = "none";
gNBs =
(
{
gNB_ID = 0xe00;
gNB_name = "gNB-OAI";
tracking_area_code = 1;
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; }) });
nr_cellid = 3L;
////////// Physical parameters (4x4, 2 layers — matches Benetel RAN650):
pdsch_AntennaPorts_XP = 2;
pdsch_AntennaPorts_N1 = 2;
pusch_AntennaPorts = 4;
maxMIMO_layers = 2;
min_rxtxtime = 6;
servingCellConfigCommon = (
{
physCellId = 3;
# SSB @ 3750.24 MHz (ARFCN 650016), band n78, 273 PRB (100 MHz), PointA 646724
absoluteFrequencySSB = 647328;
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 = 159;
prach_msg1_FDM = 0;
prach_msg1_FrequencyStart = 12;
zeroCorrelationZoneConfig = 0;
preambleReceivedTargetPower = -100;
preambleTransMax = 7;
powerRampingStep = 2;
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15;
ra_ContentionResolutionTimer = 7;
rsrp_ThresholdSSB = 19;
prach_RootSequenceIndex_PR = 2;
prach_RootSequenceIndex = 1;
msg1_SubcarrierSpacing = 1,
restrictedSetConfig = 0,
msg3_DeltaPreamble = 2;
p0_NominalWithGrant = -100;
pucchGroupHopping = 0;
hoppingId = 0;
p0_nominal = -96;
ssb_PositionsInBurst_Bitmap = 0x1;
ssb_periodicityServingCell = 2;
dmrs_TypeA_Position = 0;
subcarrierSpacing = 1;
referenceSubcarrierSpacing = 1;
dl_UL_TransmissionPeriodicity = 6;
nrofDownlinkSlots = 7;
nrofDownlinkSymbols = 6;
nrofUplinkSlots = 2;
nrofUplinkSymbols = 4;
ssPBCH_BlockPower = 0;
}
);
SCTP :
{
SCTP_INSTREAMS = 2;
SCTP_OUTSTREAMS = 2;
};
////////// AMF parameters (local OAI CN5G core, demo-oai bridge):
amf_ip_address = ({ ipv4 = "192.168.70.135"; });
NETWORK_INTERFACES :
{
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129";
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129";
GNB_PORT_FOR_NGU = 2152;
};
}
);
MACRLCs = (
{
tr_s_preference = "local_L1";
tr_n_preference = "local_RRC";
pusch_TargetSNRx10 = 200;
pucch_TargetSNRx10 = 200;
pusch_FailureThres = 100;
ul_max_mcs = 28;
}
);
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 = 9;
L1_rx_thread_core = 11;
L1_tx_thread_core = 27;
phase_compensation = 0; # needs to match O-RU configuration
}
);
RUs = (
{
local_rf = "no";
ru_thread_core = 9;
nb_tx = 4;
nb_rx = 4;
att_tx = 0;
att_rx = 0;
bands = [78];
max_pdschReferenceSignalPower = -27;
max_rxgain = 75;
sf_extension = 0;
eNB_instances = [0];
sl_ahead = 5;
tr_preference = "raw_if4p5"; # important: activate FHI7.2
do_precoding = 0; # needs to match O-RU configuration
}
);
security = {
ciphering_algorithms = ( "nea0" );
integrity_algorithms = ( "nia2", "nia0" );
drb_ciphering = "yes";
drb_integrity = "no";
};
log_config :
{
global_log_level = "info";
hw_log_level = "info";
phy_log_level = "info";
mac_log_level = "info";
rlc_log_level = "info";
pdcp_log_level = "info";
rrc_log_level = "info";
ngap_log_level = "info";
f1ap_log_level = "info";
};
# ---- 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);
du_addr = ("00:11:22:33:44:66");
ru_addr = ("6c:ad:ad:00:0d:60"); # Benetel RAN650
vlan_tag = (4);
mtu = 9216;
file_prefix = "fhi_72";
fh_config = ({
T1a_cp_dl = (258, 470);
T1a_cp_ul = (258, 470);
T1a_up = (80, 196);
Ta4 = (0, 1960);
ru_config = {
iq_width = 9;
iq_width_prach = 9;
};
prach_config = {
eAxC_offset = 8;
};
});
};
The AMF address is the one Docker assigned to oai-amf when the OAI CN5G core was last started;
Docker assigns the demo-oai addresses in start order, so check it after every core restart:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' oai-amf.
RU side for Duranta. The same RRHconfig_xran.xml as above; no per-stack RU state.
Launch. foxconn-du-bringup.sh creates four VFs on DATA1a, binds VF0 (0000:12:01.0) to
vfio-pci, sets the VF MACs after the bind and verifies them, sets hugepages, starts ptp4l
(G.8275.1) and phc2sys, purges DPDK runtime state, selects the static fronthaul library and launches
the DU. The launch line it runs (from the build directory
/opt/duranta/cmake_targets/ran_build/build):
taskset -c 7,9,11,27,28,29,30,31,32,33,34 ./nr-softmodem -O /root/oru/gnb-foxconn-static.conf --thread-pool 28,29,30,31,32,33,34
Health: the DU log /tmp/du_dlchase.log prints [o-du 0][rx … pps …] and
[o_du0][RX Timing][on time …]; rx 0 pps with every error counter at 0 means the VF is not receiving
at all (see Known problems and fixes). The drop/up/pusch errors counters
run at roughly half of the received count on this RU even when the fronthaul is healthy; they are not
the attach blocker.
Starting conditions. On this RU the Duranta DU streams reliably only on the first bring-up after
a clean host boot: warm DU restarts (kill + SR-IOV teardown + vfio-pci rebind) leave the E810 VF
receive path wedged and the DU stalls at first_call set from phy cb. One configuration change
therefore costs one host reboot and one RU reset.
| Setting | OCUDU | Duranta | Why they differ |
|---|---|---|---|
| Fronthaul transport | raw AF_PACKET socket on the PF DATA1a, promiscuous |
DPDK on E810 VF 0000:12:01.0 (vfio-pci) |
the two stacks' OFH implementations |
| DU source MAC | du_mac_addr from the config |
the VF's hardware MAC; du_addr is ignored in O-DU mode |
OAI takes the MAC from rte_eth_macaddr_get() |
| VLAN | in the config (vlan_tag_cp/up: 4) |
the VF's port VLAN | same reason |
| PRACH eAxC | prach_port_id: [4, 5, 6, 7] |
eAxC_offset = 8 |
OAI measured PRACH on eAxC 8, 9 on the wire; unresolved (see Fronthaul mapping) |
| PRACH frequency start | prach_frequency_start: 2 |
prach_msg1_FrequencyStart = 12 |
not recorded |
| UL compression header | enable_ul_static_compr_hdr: true set explicitly |
xran default | required by this firmware on OCUDU; not isolated on OAI |
| DL IQ amplitude | iq_scaling: 1.0 (near full scale) |
no scaling; OAI's DL peaks at −12 dBFS before BFP | OAI's 7.2 path copies txdataF into the compressor unchanged |
| C-plane windows (T1a_cp, µs) | 250–420 | 258–470 | srsRAN reference vs the OAI config's values |
| Ta4 (µs) | 25–1960 | 0–1960 | — |
| TDD pattern | OCUDU default (no tdd_ul_dl_cfg) |
7 DL / S 6+4 / 2 UL, 5 ms | set independently |
| MIMO | nof_antennas_dl/ul: 4 |
nb_tx/nb_rx 4, maxMIMO_layers 2, pusch_AntennaPorts 4 |
Duranta config inherited from the Benetel rig |
| Tracking area / core | TAC 7, Open5GS on the DU host | TAC 1, OAI CN5G (Docker) on the DU host | each image's own core |
Host phc2sys |
phc2sys -s DATA1a -w -n 24 |
phc2sys -s DATA1a -n 24 -O 0 -S 0.0 -F 0.0 (in foxconn-du-bringup.sh) |
OCUDU needs -w: with -O 0 the system clock runs 37 s ahead of the RU and the two derive frame numbers 3700 frames apart |
| Restart discipline | RU reset → PTP → cuplane → one DU start | clean host boot → RU reset → latch → one DU start | E810 VF receive wedges on warm DPDK restarts |
Throughput is iperf3, receiver line. Only one run on this RU has carried user data.
| Stack (core) | DU CPU platform | Logical CPUs | DL / UL (Mbit/s) | UE | Date | Image |
|---|---|---|---|---|---|---|
| OCUDU (Open5GS) | 2× Intel Xeon Gold 6126, 24 cores | 48 | 24.8 / 16.0 | Quectel RM520N-GL, RSRP −68, SINR 30 | 2026-08-19 | ocudu.ndz of that date (OCUDU commit 3118ae5) |
| OCUDU (Open5GS) | 2× Intel Xeon Gold 6126, 24 cores | 48 | not attaching | — | 2026-09-14 | ocudu-20260909b (OCUDU 7238f4f) |
| Duranta (OAI CN5G) | 2× Intel Xeon Gold 6126, 24 cores | 48 | not attaching (camps, no registration) | — | 2026-09-05 | not recorded |
iq_scaling: 1.0. The RU transmits (TX −2 / +2.5 / +7 / +2 dBm perAD9025 PA protection error, and no UE sees the cell. Atiq_scaling: 0.5 the trips stop, but on that latch the RU did not stream uplink to the DU. Open:RRH_TX_ATTENUATION above 24 dB with iq_scaling: 1.0, has not beenLIMSRV and never start registration. eAxC_offset 4 and 8,q_RxLevMin = -70, a cold RU cycle and a clean host boot did not change it. Open question: why thetx_amp_backoff_dB, att_tx andssPBCH_BlockPower do not change 7.2 DL power. A DL iq_scaling multiply in OAI'sxran_fh_tx_send_slot (about ×3.98 for this RU, saturating at ±32767) is the candidate fix; it isdo_CSIRS = 1,first_call, RU reportsLatch status: 1). Running reset_cuplane on the RU before the latch made three consecutive| Symptom | Cause | Fix |
|---|---|---|
RU does not answer ping although omf stat says POWERON |
the RU's management daemon crashed, or the watchdog reset it | omf tell -a reset -t foxconn-oru1.instrument.orbit-lab.org on your fronthaul console; if still silent after a minute, offh, ~25 s, on |
ssh root@10.3.16.1 → Connection refused |
port 22 is never open on this RU | use the SSH shell on port 830 with the legacy algorithms shown above |
RU PTP never reaches state=3 |
the boot-time ptp4l does not lock, or ptp4l was restarted before /tmp/ptp4l_user_gen.cfg existed (failed to open configuration file) |
wait for the file, restart the RU's ptp4l once, check exactly one instance runs, wait for state=3 |
| RU resets every 10–15 min during setup | hardware watchdog (rrh_hw_watchdog) |
run reset → PTP → cuplane → DU without gaps |
| DU start under an already-latched RU stops streaming or resets the RU | the RU does not tolerate a DU restart | go back to the RU reset |
OCUDU drops every UL symbol: no section was decoded correctly |
this firmware sends static UL compression headers | enable_ul_static_compr_hdr: true |
OCUDU receives nothing while tcpdump shows the frames |
the AF_PACKET socket needs a promiscuous NIC |
ip link set DATA1a promisc on |
Duranta: perfect DL, [o-du 0][rx 0 pps …][Total Msgs_Rcvd 0], all error counters 0 |
binding the VF to vfio-pci wipes its MAC; DPDK then uses a random (deterministic) MAC such as f2:99:ef:ef:10:44, and the RU's uplink goes to 00:11:22:33:44:66 |
set the VF MAC after the bind and verify it (foxconn-du-bringup.sh step [2b]) |
Duranta: DU stalls at first_call set from phy cb after a restart |
E810 VF receive state wedged by warm SR-IOV teardown / vfio-pci rebind / DU kill |
reboot the DU host, reset the RU, latch once, start once |
| Duranta: DU segfault at frame 0 | NULL PRACH buffer dereference in xran (xran_rx_proc.c) |
the pBuffers guard in the host's xran build |
| UE never lists the cell although an SDR sees a PSS peak | PointA off by two ARFCN, SSB one subcarrier off the grid | PointA 646724 with SSB 647328 (OCUDU's derived values) |
Quectel with band lock 78 never finds the cell |
3709.92 MHz enumerates as band 77 on the Quectel | AT+QNWPREFCFG="nr5g_band",77:78 |
c_on flat between two reads |
the RU log is stale (not being written) | check the log's timestamp before concluding anything |
Vendor and upstream
ru_ofh configuration reference): https://docs.srsran.com/projects/project/en/latest/fhi_72 configuration):ptp4l, phc2sys): https://linuxptp.sourceforge.net/On this wiki
COSMOS files (duranta-cosmos repository): configs/foxconn-rru/RRHconfig_xran.xml,
configs/ocudu-foxconn-72/ (gnb-ocudu-foxconn.yml, fx_relatch.sh, fxru.sh),
configs/oru-profiles/foxconn-rpqn.yml.
Author(s): COSMOS team · Last verified: 2026-09-14 (OCUDU, not attaching), 2026-09-05 (Duranta, not attaching) · page written 2026-09-25 · Tags: oran, o-ru, 7.2, fronthaul, foxconn, rpqn, file-mode, ocudu, duranta, ptp, hardware