This page drives a commercial Foxconn RPQN-7801 O-RU from the permissively-licensed OCUDU DU (built on
srsRAN Project) over a real O-RAN 7.2 (split-7.2x) fronthaul — eCPRI on VLAN 4, S-plane PTP (G.8275.1) — with a native Open5GS core and a commercial Quectel 5G modem as the UE. It is a status and research page: the fronthaul side works; the UE does not attach.
Current status: not attaching. The RU locks PTP, activates its C/U-plane and exchanges data with the DU with zero fronthaul drops, but no UE sees the cell. Last tested 2026-09-14 (image
ocudu-20260909b, OCUDU7238f4f). For a working OCUDU O-RU rig, use the Benetel or the LiteOn in OCUDU with a commercial O-RU.
This is the production O-RAN shape on the OCUDU (srsRAN) platform: instead of the DU driving its
own USRP, the radio lives in a standalone Foxconn RPQN-7801 O-RU connected by an Open Fronthaul
7.2x link. OCUDU's Open Fronthaul (ru_ofh) block speaks eCPRI (enhanced Common Public Radio Interface) directly to the RU using a raw-socket
backend (no DPDK) over a VLAN-4 tagged interface, with the S-plane synchronised by G.8275.1 PTP (Precision Time Protocol)
against the fabric grandmaster.
The Foxconn RU runs in file mode (a local RRHconfig_xran.xml + an activation script), not M-Plane
NETCONF, so the RU is configured out-of-band and the DU streams C/U-plane to it. Compared with the Benetel and LiteOn, it needs more hands-on work from the O-DU side: its S-plane has to be restarted by hand after every RU reset, its C/U-plane is activated from a shell on the RU, and a hardware watchdog resets it if the sequence stalls. The UE side has two Foxconn-specific points: the real subscriber key (it is not the generic test key) and the modem band lock (n78 at 3.75 GHz enumerates as band 77). PLMN is the testbed standard 00101, and the UE pool is 192.168.100.0/22.
For the radio-less software version see the OCUDU soft-only
tutorial; for the USRP over-the-air version
see the OCUDU cross-vendor
tutorial. The same OCUDU DU over
the Benetel RAN650 and LiteOn FlexFi is covered by the OCUDU O-RAN 7.2
tutorial.
Works
state=3, rms 5–13 ns) when its boot ptp4l is restarted after the RU has written /tmp/ptp4l_user_gen.cfg.RRH_state=DATA_EXCHANGING with c_on climbing, and with enable_ul_static_compr_hdr: true the DU sees 0 OFH drops.Open question: why does no UE see the cell?
iq_scaling: 1.0 the RU transmits (TX −2 / +2.5 / +7 / +2 dBm per branch, 2026-09-14) but logs repeated AD9025 PA protection error, and the Quectel does not see the cell. At iq_scaling: 0.5 the PA-protection trips stop, but the RU does not stream uplink to the DU.ptp4l restart → state=3 → cuplane → one DU start with no gap.Facts that hold for this RU
root/root). Port 22 is always refused; that does not mean the RU application failed.enable_ul_static_compr_hdr: true is required; srsRAN's RPQN reference value false makes the DU drop every UL symbol (no section was decoded correctly).ta4_max: 1960 and expert_phy.max_proc_delay: 10 are the same timing values the LiteOn needs (see the OCUDU O-RAN 7.2 tutorial).c_on climbing in /var/log/rrh_log_print/rrh_log_print.log (grep xRN); core1 is running N is not.console.instrument.cosmos-lab.org: omf tell -a {offh,on,reset} -t foxconn-oru1.instrument.orbit-lab.org.The DU config and a one-shot latch helper are in the duranta-cosmos repo:
configs/ocudu-foxconn-72/gnb-ocudu-foxconn.yml and configs/ocudu-foxconn-72/fx_relatch.sh.
This page exercises two fronthaul ideas explained on O-RAN and the 7.2x fronthaul: eAxC identifiers, which label each fronthaul stream (here DL/UL on 0–3 and PRACH on 4–7) and must agree between the DU config and the RU's RRHconfig_xran.xml; and O-RU management modes — the Foxconn is configured from a file on the RU rather than by the DU over NETCONF, which is why the DU config has to mirror the RU file by hand.
Figure — The C-plane and U-plane share VLAN 4 and the S-plane comes from the fabric grandmaster; each DL, UL and PRACH stream is an eAxC lane whose number must match on both ends.
The outcomes below describe the full procedure. Given the status above, the realistic outcome today is the first three plus a clear picture of where the attach fails.
After completing this tutorial you will be able to:
rrh_log_print c_on counter (not the misleading "core1 is running" line).Authentication failure (MAC failure) as a wrong-key symptom.| Learning path | Step 4 of 7 — O-RAN 7.2 with a commercial O-RU (status/research page). Previous: OCUDU with a commercial O-RU · Next: OCUDU with Aether SD-Core |
| Status | Not attaching (last tested 2026-09-14) |
| Difficulty | Advanced |
| Estimated time | 75–120 min |
| Domain / sandbox | an osc or sb1 E810 fronthaul server + the Foxconn O-RU (instrument domain) |
| Topic group | Cellular (4G/5G/O-RAN) |
| Last verified | 2026-08-19 end to end; re-tested 2026-09-14 on srv18.osc — not attaching (see Status) · text revised 2026-09-24 |
Background knowledge
ssh/ip/iperf3 on Linux.Account & access
Devices / nodes
| Resource | Role | Qty | Notes |
|---|---|---|---|
E810 fronthaul server (osc or sb1) |
OCUDU OFH DU + Open5GS core | 1 | fronthaul NIC on VLAN 4, iface DATA1a (e.g. srv18.osc) |
| Foxconn RPQN-7801 O-RU | commercial O-RU (radio) | 1 | foxconn-oru1.instrument.orbit-lab.org, RU shell/M-Plane SSH 10.3.16.1:830 (port 22 is always refused), RU MAC 6c:ad:ad:00:0d:60 |
| Quectel RM520N-GL | commercial 5G UE | 1 | USB on a UE node; AT /dev/ttyUSB2/3, QMI wwan0/cdc-wdm0 |
Disk images
| Image | Load onto | Provides |
|---|---|---|
ocudu.ndz |
DU node | OCUDU gnb (/opt/ocudu), Open5GS (/opt/open5gs), UHD/qmicli, cosmos-ofh-isolation (the image carries no isolcpus — they are derived per host, see Setup) |
lte5gue.ndz |
UE node | qmicli (libqmi), modem helper scripts |
(ocudu.ndz / lte5gue.ndz are symlinks to the latest dated builds.)
Software components
| Component | Version | Source |
|---|---|---|
| OCUDU gNB (srsRAN Project) | 7238f4f (image ocudu-20260909b); the 2026-08-19 measurement below used commit 3118ae5 (26.04) |
/opt/ocudu/build/apps/gnb/gnb — no license needed, built with ru_ofh raw-socket |
| Open5GS 5GC | build-tree | /opt/open5gs, mongo db open5gs, launcher /root/open5gs/start.sh |
linuxptp (ptp4l/phc2sys) |
distro | S-plane G.8275.1 on the DU host + the RU |
| Foxconn RU firmware | eng_v3_1_15q |
file-mode activation init_rrh_config_enable_cuplane |
Spectrum / RF / special
dl_arfcn 650000 (3750 MHz),00101, slice SST 1 / SD 000001, DNN internet (IPv4), UE pool192.168.100.0/22, gateway 192.168.100.1, internet-NAT'd.Shared RF space. The
sb1fronthaul rig shares one physical RF space, so a Quectel modem on any
co-located node can camp on this cell. If a UE "sees no signal", the RU is not radiating — it is never
an antenna/EIRP problem.
Figure — The DU server's fronthaul NIC reaches the O-RU through the fabric switch, which is also the PTP grandmaster; power control of the O-RU is a separate path through omf tell on the instrument console.
The OCUDU DU + Open5GS core run on one E810 compute node; its fronthaul NIC carries the VLAN-4 eCPRI
link to the Foxconn O-RU, which radiates over the air to the Quectel modem:
DU / core node (sb1) Foxconn RPQN-7801 O-RU Quectel UE
┌────────────────────────┐ eCPRI ┌───────────────────────┐ n78 OTA ┌──────────────┐
│ OCUDU gnb (ru_ofh) │ VLAN 4 │ file-mode RRHconfig │ 3.75 GHz │ RM520N-GL │
│ Open5GS 5GC │═════════════►│ eAxC 0-3 DL/UL, 4-7 RA │────────────►│ wwan0 QMI │
│ ogstun 192.168.100.1 │ + PTP S-pl │ M-Plane 10.3.16.1:830 │ RSRP -68 │ 192.168.100.2│
│ AMF 127.0.0.5:38412 │◄────────────►│ TX 24 dBm, 4T4R │ │ │
└────────────────────────┘ G.8275.1 └───────────────────────┘ └──────────────┘
DATA1a (VLAN 4) PTP GM = fabric switch (G.8275.1)
127.0.0.5:38412 (the N2 interface).ogstun (192.168.100.1) and is NATed to the Internet.DATA1a carries C/U-plane on VLAN 4; eAxC 0–3 are the DL/UL antenna streams and 4–7 the PRACH streams.10.3.16.1:830; nothing else uses that path.OCUDU needs no license server and no DPDK — the ru_ofh block uses a raw AF_PACKET socket on the
named interface.
ssh <username>@console.<domain>.cosmos-lab.org
-r 0):omf load -i ocudu.ndz -t <du-node> -r 0 -o 1200
omf load -i lte5gue.ndz -t <ue-node> -r 0 -o 1200
omf tell -a on -t <du-node>,<ue-node>
sshd and wedges an un-isolated hostocudu.ndz image deliberately carries no isolcpus; derive and apply them for the fronthaul NIC DATA1a with cosmos-ofh-isolation --apply, reboot, and run the checks exactly as in Real-time host preparation — Command 1. Expected on srv18.osc (2026-09-14): isolated CPUs 3-11,27-35 (nine physical cores and their hyperthread siblings), NTP service: inactive, and one phc2sys -s DATA1a -w -n 24 -m, settled to a small offset (s2, tens of ns). Use -w, not -O 0 — see Troubleshooting.There is no Ansible description for the Foxconn OCUDU path yet — the RU activation and its crash-recovery
loop need a human in the loop — so this tutorial is a manual bring-up. Do the steps in order: core →
DU config → RU activate → gNB → verify radiating → attach UE. The core and subscriber come first because they do not depend on the RU; the RU comes last before the DU because its watchdog punishes any gap between activation and the DU start.
The launcher starts all Open5GS network functions, creates the ogstun gateway interface and installs NAT to the Internet.
ssh root@<du-node>
/root/open5gs/start.sh # NFs + ogstun 192.168.100.1/22 + NAT→internet
ip -4 addr show ogstun | grep inet
inet 192.168.100.1/22 scope global ogstun
The core authenticates the SIM with MILENAGE, which needs the same secret key (Ki) and operator key (OPc) on both sides. If the core holds a different key, the UE rejects the network at the first authentication.
The COSMOS test SIMs are not programmed with the generic srsRAN/OAI test key. Each card's real
Ki/OPc lives in the OAI CN5G seed SQL that the monolithic Duranta image uses; find your card there:
grep -rh "'<IMSI>','5G_AKA'" /opt/oai-cn5g/oai-cn5g-fed/docker-compose/database/*.sql
# row format: imsi,'5G_AKA',Ki,Ki,{sqn..},amf,'milenage',OPc,...
('001010000000032','5G_AKA','<Ki>','<Ki>',
'{"sqn":...}','9001','milenage','<OPc>',NULL,...,'001010000000032'),
(The key values are left out of this page on purpose; read them from the seed file on the host.)
Provision it into Open5GS with opc set and no op_type (a stray op_type breaks MILENAGE), plus
the slice and DNN:
mongosh open5gs --quiet --eval '
db.subscribers.updateOne({imsi:"001010000000032"},
{$set:{"security.k":"<Ki>",
"security.opc":"<OPc>",
"security.op":null,"security.amf":"9001",
"slice.0.sst":1,"slice.0.sd":"000001","slice.0.session.0.name":"internet"},
$unset:{"security.op_type":""}})'
Wrong-key symptom. If the AMF logs
Authentication failure(MAC failure)on a fresh attempt
(preceded byUnknown UE by SUCI), the network key ≠ the SIM's — try the OAI-seed value above.
A cached-GUTI re-registration can succeed with a wrong key; aCFUN=0/1on the modem forces the
real MILENAGE test.
Because the Foxconn is configured from its own file rather than by the DU, the DU config has to mirror that file: carrier frequency, bandwidth, MAC addresses, VLAN and eAxC numbers must match value for value. Each comment below names the RU-side key it must equal.
The gNB config carries the cell + a ru_ofh block matched to the RU's RRHconfig_xran.xml. Use configs/ocudu-foxconn-72/gnb-ocudu-foxconn.yml in the duranta-cosmos repo
(copy it to /root/ocudu/ on the DU node — its expert_execution CPU sets are srv18's, re-derive them
for another host). The fields that must agree with the RU:
cell_cfg:
dl_arfcn: 650000 # n78, 3750 MHz (== RU RRH_LO_FREQUENCY_KHZ 3750000)
band: 78
channel_bandwidth_MHz: 100 # RU RRH_MAX_PRB 273
common_scs: 30
plmn: "00101"
tac: 7
pci: 3 # unique per O-RU (Benetel 2, LiteOn 1)
nof_antennas_dl: 4
nof_antennas_ul: 4
ru_ofh:
t1a_max_cp_dl: 420 # timing windows: srsRAN's own RPQN reference
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 # reference 500; 1960 carried over from the LiteOn fix
ta4_min: 25
is_prach_cp_enabled: true
ignore_ecpri_payload_size: true
compr_method_ul: bfp
compr_bitwidth_ul: 9
compr_method_dl: bfp
compr_bitwidth_dl: 9
enable_ul_static_compr_hdr: true # REQUIRED on this firmware — false drops every UL symbol
enable_dl_static_compr_hdr: false
iq_scaling: 1.0
cells:
- network_interface: DATA1a # raw socket, no DPDK
ru_mac_addr: 6c:ad:ad:00:0d:60 # == RU RRH_SRC_MAC_ADDR
du_mac_addr: 00:11:22:33:44:66 # == RU RRH_DST_MAC_ADDR
vlan_tag_cp: 4
vlan_tag_up: 4
prach_port_id: [4, 5, 6, 7] # == RU RRH_EAXC_ID_TYPE3
dl_port_id: [0, 1, 2, 3] # == RU RRH_EAXC_ID_TYPE1
ul_port_id: [0, 1, 2, 3]
expert_phy:
max_proc_delay: 10 # 15 lets the MAC run so far ahead that PRACH misses the RAR window
This step brings the RU from a fresh reset to "PTP locked and C/U-plane enabled". It has to happen with the gNB stopped, and Step 5 has to follow at once.
The RU's shell is its M-Plane SSH on port 830 (legacy KEX, root/root; port 22 is always refused).
Start every attempt from a fresh RU reset, from the instrument console:
# on console.instrument.cosmos-lab.org (as your COSMOS user)
omf tell -a reset -t foxconn-oru1.instrument.orbit-lab.org
If the RU still does not answer ping a minute later, cold-cycle it (omf tell -a offh …, wait ~25 s,
omf tell -a on …).
Then, on the RU (from the DU node via the M-Plane SSH), restart the RU's ptp4l — the one that starts
at boot never locks — and run the cuplane activation. Wait until /tmp/ptp4l_user_gen.cfg exists (a few
minutes after boot) before restarting ptp4l, and check that only one ptp4l is left running. The gNB
must be down for this, and go straight on to Step 5 — the RU watchdog-resets itself if it is left idle:
ssh -p 830 -o KexAlgorithms=+diffie-hellman-group14-sha1 \
-o HostKeyAlgorithms=+ssh-rsa root@10.3.16.1
# on the RU:
ls /tmp/ptp4l_user_gen.cfg # must exist first
killall run_ptp4l.sh ptp4l 2>/dev/null; setsid /usr/utils/run_ptp4l.sh >/tmp/ptp.log 2>&1 &
pgrep -l ptp4l # exactly one
grep -a state=3 /tmp/ptp.log | tail -1 # wait for lock
ptp4l[...]: state=3 rms 6 max 8 freq +60 delay 9 # SLAVE, rms a few ns
The killall above runs inside the O-RU's own embedded Linux, which serves one DU at a time; it stops only the RU's PTP daemons. Do not use killall on COSMOS servers.
What to look for: state=3 is the linuxptp SLAVE state — the RU's clock is following the grandmaster — with rms in single-digit nanoseconds.
# still on the RU — enable C/U-plane (reads RRHconfig_xran.xml):
cd /home/root/test && (./init_rrh_config_enable_cuplane > /tmp/L.out 2>&1 &)
grep -aE 'valid|core1' /tmp/L.out | tail -3
Setting of LO1 and PRB is valid
Setting of Tx attenuation is valid
core1 is running 9
What to look for: the two valid lines — the RU accepted the carrier (LO1/PRB) and transmit attenuation from its file. core1 is running is not proof of radiation; that is checked in Verification.
The ~15-minute RU resets. The RU runs a hardware watchdog (
rrh_hw_watchdog) and resets itself
roughly every 10–15 minutes when it is left idle or mid-setup (PTP not yet locked, no DU streaming);
/var/logis not full, so this is not a disk problem. The in-place truncate loop below is harmless
and keepsrrh_log_print.logsmall, but it does not prevent the resets — only a tight
reset → PTP → cuplane → DU sequence does:setsid sh -c 'while true; do :> /var/log/rrh_log_print/rrh_log_print.log; sleep 15; done' &
configs/ocudu-foxconn-72/fx_relatch.sh(in theduranta-cosmosrepo) runs Steps 4–5 as one
sequence from the DU node after you reset the RU.
The DU is started once, detached from the SSH session so it survives a dropped connection, and under a CPU mask that includes the isolated cores.
With the RU PTP-locked and cuplane activated, start the gNB once on the isolated cores (keep stdin
open, detach from ssh). Do not restart it while the RU stays latched — to retry, go back to the RU reset
in Step 4:
ssh root@<du-node>
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
sleep 30; pgrep -x gnb >/dev/null && echo ALIVE; grep -a 'to AMF completed' /tmp/g.log
ALIVE
N2: Connection to AMF on 127.0.0.5:38412 completed
taskset -c 0-47 (all cores on a 48-core host — use 0-$(( $(nproc --all) - 1 )) elsewhere) is required:
isolcpus hides the isolated cores from srsRAN's affinity validator, so the process must be launched with
a mask that includes them (see the main-pool section of Real-time host preparation).
What to look for: ALIVE (the process survived its first 30 s) and N2: Connection to AMF ... completed — the gNB has registered with the core. Neither says anything yet about the radio.
| Check | Command / where | Expected |
|---|---|---|
| RU PTP | grep -a state=3 /tmp/ptp.log on the RU |
state=3, rms a few ns, exactly one ptp4l |
| DU ↔ core | grep -a 'to AMF completed' /tmp/g.log |
N2: Connection to AMF on 127.0.0.5:38412 completed |
| RU radiating | grep -a xRN /var/log/rrh_log_print/rrh_log_print.log on the RU |
c_on climbing; err_tci/ecpri/port/sct all 0 |
| UE camped | AT+QENG="servingcell" |
NR5G-SA, 001,01, ARFCN 647328 |
| Registered | AMF log | Registration complete for the IMSI |
| Data | ping -I wwan0 |
0 % loss to 192.168.100.1 and 8.8.8.8 |
Today the first three rows pass and the fourth does not — that is the open question in Current status.
c_on, not "core1 is running"The authoritative "is it transmitting" signal is the RU's rrh_log_print counter: c_on climbing with
err_tci/ecpri/port/sct all zero (the srsRAN Foxconn success signature):
# on the RU:
grep -a xRN /var/log/rrh_log_print/rrh_log_print.log | tail -2
xRN: total=734319 c_early=0 c_on=66948 c_late=0 err_tci=0 err_ecpri=0 err_port=0 err_sct=0 err_total=648520
xRN: total=750079 c_early=0 c_on=68372 c_late=0 err_tci=0 err_ecpri=0 err_port=0 err_sct=0 err_total=662457
What to look for: c_on (C-plane messages that arrived on time) growing between the two lines, with c_early and c_late at 0 — the DU's messages are landing inside the RU's receive window.
On the UE node, hard-lock the Quectel to NR5G-SA and force the PLMN. Set band 77:78, not 78 —
3.75 GHz enumerates as band 77, so a bare 78 lock blocks the cell. The general modem procedure is on COTS UE: the Quectel modem; the band lock is the Foxconn-specific part.
ssh root@<ue-node> 'systemctl stop ModemManager'
# via AT on /dev/ttyUSB2 (or ttyUSB3):
AT+CFUN=0
AT+QNWPREFCFG="mode_pref",NR5G
AT+QNWPREFCFG="nr5g_disable_mode",0
AT+QNWPREFCFG="nr5g_band",77:78
AT+CRSM=214,28539,0,0,12,"FFFFFFFFFFFFFFFFFFFFFFFF" # clear forbidden-PLMN list
AT+CFUN=1
AT+COPS=1,2,"00101",12
AT+QENG="servingcell"
+QENG: "servingcell","NOCONN","NR5G-SA","TDD",001,01,00066C000,1,7,647328,78,3,-68,-10,30,1,71
NR5G-SA, PLMN 001/01, RSRP -68, SINR 30. Confirm registration in the AMF log:
ssh root@<du-node> "grep -a 'Registration complete' /tmp/open5gs/amf.log | tail -1"
[gmm] INFO: [imsi-001010000000032] Registration complete
This is the rig's variant (APN 'internet' through qmi-proxy with -p, a /30 address) of the data bring-up explained under Bringing up data; add only scoped routes through wwan0, as shown there.
ssh root@<ue-node>
echo Y > /sys/class/net/wwan0/qmi/raw_ip; ip link set wwan0 up
qmicli -d /dev/cdc-wdm0 -p --wds-start-network="apn='internet',ip-type=4" --client-no-release-cid
qmicli -d /dev/cdc-wdm0 -p --wds-get-current-settings | grep -E 'IPv4 address|gateway'
IPv4 address: 192.168.100.2
IPv4 gateway address: 192.168.100.1
QMI CID-alloc timeout? Reload the driver:
rmmod qmi_wwan; modprobe qmi_wwan(with ModemManager
stopped), then retry--wds-start-network.
ip addr add 192.168.100.2/30 dev wwan0; ip link set wwan0 up mtu 1400
ping -c5 -I wwan0 192.168.100.1 # UPF gateway
ping -c5 -I wwan0 8.8.8.8 # internet via UPF NAT
5 packets transmitted, 5 received, 0% packet loss # rtt avg ~103 ms (gw)
5 packets transmitted, 5 received, 0% packet loss # rtt avg ~77 ms (8.8.8.8)
Throughput — run an iperf3 server on the UPF gateway (192.168.100.1, DU node) and drive it from the UE bound to 192.168.100.2, 8 s per direction (-R for downlink), as in Bringing up data on COTS UE: the Quectel modem:
[ 5] 0.00-8.00 sec 23.6 MBytes 24.8 Mbits/sec receiver # DOWNLINK
[ 5] 0.00-8.25 sec 15.8 MBytes 16.0 Mbits/sec receiver # UPLINK
These outputs are the 2026-08-19 measurement (OCUDU commit 3118ae5): a COTS UE reaching the internet over a commercial O-RU driven by a license-free DU. They are the target, not the current state.
Stop processes as process groups identified by their executable — never with pkill -x or pkill -f, which match by name or command line and can hit another user's process or your own shell. Define this helper in your shell on each node you log into:
stop_exe() { # signal the process GROUP of every process executing exactly $1 (default TERM)
local exe sig=${2:-TERM} d st pgid
exe=$(readlink -f "$1")
for d in /proc/[0-9]*; do
[ "$(readlink "$d/exe" 2>/dev/null)" = "$exe" ] || continue
st=$(cat "$d/stat" 2>/dev/null) || continue
st=${st##*) } # drop "pid (comm) ", safe for any comm
pgid=$(echo "$st" | awk '{print $3}') # remaining fields: state ppid pgrp
kill -"$sig" -- "-$pgid" 2>/dev/null
done
}
The function identifies a process by the binary it is executing (/proc/<pid>/exe), which a command line cannot fake, and signals its whole process group. The gNB was launched with setsid, so its group is exactly that launch. It sends TERM first; if something is still running after a few seconds, repeat the call with KILL as the second argument. /usr/bin/iperf3 matches every iperf3 on the node — on your reserved nodes that is only yours.
ssh root@<ue-node>
stop_exe /usr/bin/iperf3
qmicli -d /dev/cdc-wdm0 -p --wds-stop-network=disable; ip addr flush dev wwan0
ssh root@<du-node>
stop_exe /opt/ocudu/build/apps/gnb/gnb
stop_exe /usr/bin/iperf3
# stop the RU watchdog + return the RU to idle (optional):
omf tell -a offh -t <du-node>,<ue-node>
The Foxconn O-RU is a shared instrument — leave it powered as you found it. Its power control is on
console.instrument.cosmos-lab.org: omf tell -a {offh,on,reset} -t foxconn-oru1.instrument.orbit-lab.org.
Both apply to any O-RU driven by srsRAN's OFH library (measured on a Benetel RAN650 with the same OCUDU DU, 2026-09-09). Each fails silently: every RAN counter
reads healthy while nothing works.
srsRAN's Open Fronthaul receive socket is an AF_PACKET raw socket bound to the eCPRI ethertype, and it sets IFF_PROMISC only when its own configuration tells it to. On a non-promiscuous interface the DU receives zero frames while tcpdump still shows every one of them, so a clean capture proves nothing. The command, the enable_ru metrics block that exposes ether_rx … rx_bytes, and the reasoning are on Real-time host preparation — promiscuous mode. On the Benetel rig (2026-09-09), setting promiscuous mode took rx_bytes from 0 to 1 468 800 and missed PRACH occasions to 0.
On a lab bench the UE is metres from the O-RU. Vendor default gains assume a real cell radius, and
too much gain does not look like too much gain:
| Symptom | Cause | Fix |
|---|---|---|
DL BLER stuck at 20–30 % while the outer-loop dl_olla is already several dB negative |
iq_scaling too high → the DU's IQ clips before compression. It is distortion, not weak signal, so link adaptation can never back away from it |
iq_scaling: 5.5 (10 and 20 both fail here) |
Uplink collapses to a few kbit/s; one RX port in the O-RU's status reads exactly 0.000000 dBFS while the others sit near −60 |
the O-RU's own uplink gain saturates that receive branch | set the RU's ul_gain_correction to 0 in its config and reboot the RU (it is read only at boot) |
| High BLER at high CQI on both links | the 256QAM table keeps the scheduler over-optimistic | pdsch:/pusch: { mcs_table: qam64 } — took DL BLER 21–26 % → 0 % and UL 30.9 → 76.6 Mbit/s |
rx_late a large fraction of rx_total, RTT in the hundreds of ms |
the DU's uplink reception window closes before the O-RU's delivery arrives | ta4_max: 1960 — took rx_late 1798/2400 → 0 and RTT 610 → 30 ms |
| RSRP looks fine but CQI is 2 and DL HARQ exhausts its retransmissions | the O-RU is carrying the other stack's configuration. A shared O-RU keeps whatever the last stack wrote, and the mismatch is silent: the fronthaul counters stay clean while the radio gates TX/RX on the wrong frame | diff the O-RU against its committed golden state and restore it BEFORE starting the DU (see the O-RU tutorial). With its golden state restored the Benetel delivers DL 209–220 Mbit/s |
With all five applied on the Benetel rig: DL 62.5 / UL 76.6 Mbit/s, DL BLER 0 % at MCS 26–27,
0 % packet loss to both a local and a remote target. Before them: 8.0 / 0.8 Mbit/s.
Warning: Do not run a DPD (digital pre-distortion) reset on a radio that is already working: on the RAN650 it has left transmit branches without output until a full power cycle (2026-09-09).
| Symptom | Likely cause | Fix |
|---|---|---|
Modem stuck SEARCH, no SSB seen |
RU not radiating | Check c_on climbing (Verification); if not, stop the gNB and re-do Step 4 from the RU reset, then start the gNB once — a DU restart under a latched RU does not revive it |
RU unpingable at 10.3.16.1 |
the RU's hardware watchdog reset it (idle / mid-setup), or it wedged | from console.instrument.cosmos-lab.org: omf tell -a reset -t foxconn-oru1.instrument.orbit-lab.org; if still unpingable, offh / ~25 s / on; then re-latch without gaps |
ssh root@10.3.16.1 → Connection refused |
port 22 is never open on this RU | use the M-Plane SSH on port 830 (legacy KEX, root/root) |
RU PTP never reaches state=3 |
boot ptp4l doesn't lock; or a restart before /tmp/ptp4l_user_gen.cfg existed (failed to open configuration file), leaving two ptp4l instances fighting after the next boot |
on the RU (its embedded Linux, not a COSMOS server): wait for the cfg file, killall run_ptp4l.sh ptp4l; setsid /usr/utils/run_ptp4l.sh, confirm exactly one ptp4l, wait for state=3 |
DU drops every UL symbol: dropped received Open Fronthaul message as no section was decoded correctly |
UL compression-header mismatch — this RU firmware sends static UL headers | enable_ul_static_compr_hdr: true (srsRAN's RPQN reference false is wrong here) |
RU log repeats AD9025 PA protection error, TX power only −2…+7 dBm |
PA protection tripping at iq_scaling: 1.0 (observed 2026-09-14) |
open — iq_scaling: 0.5 stopped the trips but that latch never streamed uplink; not yet resolved |
gNB: Invalid CPU core selected '8' |
isolcpus hides cores |
launch inside taskset -c 0-<ncpu-1>; see Real-time host preparation |
gNB floods late DL_TTI.request |
L2→L1 slack too tight | raise expert_phy.max_proc_delay — but past ~10 the PRACH can reach the scheduler after the RAR window's last DL slot (Could not transmit RAR within the window); 10 was clean on srv18.osc |
OFH woke up late … skipped N symbols |
the host clock and the O-RU disagree | NTP off, then phc2sys -s DATA1a -w -n 24 (offset s2, tens of ns). Use -w, not -O 0: the G.8275.1 PHC is on the TAI timescale, so -O 0 leaves CLOCK_REALTIME 37 s ahead of a UTC-keeping O-RU and the two derive System Frame Numbers 3700 frames apart. See Real-time host preparation |
ether_rx rx_bytes = 0, no PRACH, tcpdump shows the frames |
the fronthaul NIC is not promiscuous | ip link set <fh-iface> promisc on — see the section above and Real-time host preparation |
DL BLER stuck 20–30 %, dl_olla several dB negative |
iq_scaling clipping |
lower iq_scaling (5.5 at bench range) |
Uplink a few kbit/s, one RX port at exactly 0.000000 dBFS |
O-RU receive branch saturated | ul_gain_correction=0 in the RU config, then reboot the RU |
rx_late a large fraction of rx_total, RTT hundreds of ms |
uplink reception window too tight | ta4_max: 1960 |
| ptp4l never reaches SLAVE and the log fills with management messages | a PTP management-message storm on the fabric | drop them at ingress (tc filter … protocol 0x88f7 … match the management msgType … action drop) and raise announceReceiptTimeout — the full egress filter is on Real-time host preparation |
AMF Authentication failure(MAC failure) on a fresh attempt |
wrong network Ki/OPc | use the OAI-seed key (Step 2); do not set op_type |
Modem camps commercial LTE (LIMSRV,LTE) |
mode_pref drifted to AUTO |
re-assert mode_pref=NR5G and COPS=1,2,"00101",12; see COTS UE: the Quectel modem |
qmicli … CID allocation failed |
ModemManager holds the QMI device / stuck channel | systemctl stop ModemManager; rmmod qmi_wwan; modprobe qmi_wwan; see COTS UE: the Quectel modem |
ping: Network is unreachable |
wwan0 has no IP yet |
wait for --wds-get-current-settings to return an address, then ip addr add |
On this wiki
External
ptp4l, phc2sys): https://linuxptp.sourceforge.net/Author(s): COSMOS team · Last verified: 2026-08-19 (Foxconn path, end to end); re-tested 2026-09-14 on srv18.osc — RU latches and exchanges data but no UE attach (see Status); the "Two settings that decide whether any srsRAN O-RU works at all" section was measured 2026-09-09 on the same OCUDU DU driving a Benetel RAN650 · text revised 2026-09-24 · Tested image/release: ocudu.ndz (OCUDU commit 3118ae5) on 2026-08-19; ocudu-20260909b (OCUDU 7238f4f) on 2026-09-14; Foxconn RPQN-7801 (eng_v3_1_15q) · Tags: ocudu, srsran, oran, 7.2, foxconn, o-ru, quectel, open5gs, promiscuous, gain