5G O-RAN End-to-End Simulation
Bringing up Open5GS, srsRAN, and the O-RAN SC RIC as one working chain
01Problem
A 5G stack is four independent programs that only work in one order: core, RIC, base station, handset. Reading about the interfaces between them does not tell you what each one prints when it is ready, or which failure belongs to which layer. The goal of this lab was to bring the whole chain up on a shared server with no radio hardware, and to write down the exact command and the exact confirmation signal for every step.
02What I built
- Brought up the four components in order — Open5GS 5GC under Docker Compose, the O-RAN SC RIC, an srsRAN gNB with E2 enabled, and srsUE in its own network namespace.
- Ran the entire chain over ZMQ radio emulation on a remote lab server reached by SSH, using the upstream gnb_zmq.yaml and ue_zmq.conf configurations rather than hand-written ones.
- Documented a gNB start-up failure end to end: the error, the four things I checked, and the fact that none of them was the cause.
03How it works
srsUE talks to an srsRAN gNB over a ZMQ radio link, so no SDR hardware is involved. The gNB connects north to the Open5GS core — the AMF address it dials has to match the NGAP address inside the core container's amf.yaml — and sideways to the O-RAN SC RIC over E2. The core and the RIC each run as their own Docker Compose stack, and the UE runs in a separate Linux network namespace so its traffic stays separable from the host's.
04Results
- The 5GC container reports its services running before the gNB is started, and amf.yaml inside the container shows the NGAP address the gNB configuration has to match.
- The RIC prints "RMR is ready now...", which is the readiness signal for the E2 termination.
- After the rebuild the gNB and the UE both start, and core, RIC, gNB, and UE run together as one chain.
05What went wrong
06Engineering decisions
- Run every component in its own container or namespace instead of on the host. The core, the RIC, and the UE all want their own network stack, and the namespace is what keeps the UE's traffic separable.
- Use ZMQ radio emulation instead of an SDR front end. There is no radio hardware in the lab, and ZMQ makes the whole chain reproducible over an SSH session on a shared server.
- Take configuration files from the upstream documentation rather than writing my own. When the gNB failed that made my configuration the least likely explanation, which is exactly how the search ended up on the source version.