The near-real-time RAN Intelligent Controller (near-RT RIC) is the O-RAN component that observes a live radio access network and, where the base station allows it, steers it. This page explains what a near-RT RIC is and is not, how it talks to a gNB over the E2 interface, what service models and xApps are, and which of the two open RICs on COSMOS to use. It ends with the measurements taken on COSMOS and the open problems. Read it before the E2 KPM tutorial.
A classic base station is a closed box: its scheduler, handover and power decisions are made inside the vendor's software, and an operator sees only the counters the vendor chose to export. The O-RAN architecture opens that box. It defines two controllers that sit beside the RAN and act on it through standard interfaces:
Figure — The O-RAN architecture. The near-RT RIC connects to the O-CU and O-DU over E2; the SMO and non-RT RIC above it reach it over A1 and manage the RAN over O1. Notice that neither RIC is on the path between the UE and the core.
What a near-RT RIC is not. It does not carry user traffic: the UE's packets flow from the gNB to the core's UPF exactly as they do without a RIC. It does not replace the gNB's scheduler, which makes decisions every slot (0.5 ms at 30 kHz subcarrier spacing) — far faster than any RIC loop. It is not part of the 5G core, and removing it changes nothing about registration or PDU sessions. It is a platform for applications that watch the RAN and, within the limits the RAN exposes, adjust its behaviour.
The architecture is specified by the O-RAN ALLIANCE (specifications); open implementations come from the O-RAN Software Community (O-RAN SC) and from the Aether project's SD-RAN.
Figure — E2 between an OCUDU gNB and a near-RT RIC. The gNB's E2 agent opens an SCTP association to the RIC's E2 termination; KPM indications flow up to the xApps (working on COSMOS), RC control requests flow down (rejected by the current OCUDU build). The user plane to the core runs alongside, untouched. SD-RAN is drawn as the alternative RIC.
E2 is the interface between the near-RT RIC and an E2 node — a gNB, or its CU and DU separately. It runs over SCTP (port 36421 on COSMOS). The E2 Application Protocol (E2AP) defines the procedures that travel over it:
| Procedure | Direction | What it does |
|---|---|---|
| E2 Setup | E2 node → RIC | The gNB opens the association and lists its RAN functions — one per service model it supports, each identified by an object identifier (OID). The RIC acknowledges; until it does, nothing else can happen. |
| RIC Subscription | RIC → E2 node | An xApp asks for data: which RAN function, an event trigger (for example "every 1000 ms") and an action definition (which measurements, for which cell or UEs). The gNB admits or rejects it. |
| RIC Indication | E2 node → RIC | The gNB's report, sent each time the trigger fires, carrying the requested measurements. |
| RIC Control | RIC → E2 node | An xApp asks the gNB to change something. The gNB answers with an acknowledgement or a RIC Control Failure. |
An established SCTP association is not proof that E2 works: the link is usable only after E2 Setup completes, which the RIC's E2 manager reports as CONNECTED.
E2AP is a generic envelope; an E2 service model (E2SM) defines what the measurements and controls mean.
DRB.UEThpDl and DRB.UEThpUl — downlink and uplink throughput on the data radio bearers. Its report styles choose the scope: style 1 reports for the whole E2 node (cell level); style 5 reports for a list of UEs named in the subscription.An xApp is an application that runs on the near-RT RIC and implements the logic: subscribe, read indications, decide, and optionally send control requests. The RIC platform supplies the plumbing. In the O-RAN SC RIC as deployed on COSMOS it is seven containers:
| Container | Role |
|---|---|
e2term |
E2 termination — the SCTP endpoint the gNB connects to (port 36421); decodes E2AP |
e2mgr |
E2 manager — tracks connected E2 nodes (/v1/nodeb/states) |
submgr |
Subscription manager — turns an xApp's REST subscription into E2 messages and routes the resulting indications back |
rtmgr |
Routing manager (simulator build) — RMR message routing between platform and xApps |
appmgr |
xApp manager |
dbaas |
Redis-backed shared state |
python_xapp_runner |
the Python xApp framework and the example xApps (kpm_mon_xapp.py for KPM monitoring, a reference RC control xApp) |
COSMOS has two open near-RT RICs.
| O-RAN SC near-RT RIC | Aether SD-RAN (ONOS) | |
|---|---|---|
| Origin | O-RAN Software Community, i-release; packaged by srsRAN as oran-sc-ric |
ONF/ONOS µONOS architecture, part of Aether |
| Deployment | Docker Compose, one host | Kubernetes (RKE2) + Helm, via Aether OnRamp |
| E2AP | the generation the srsRAN/OCUDU E2 agent speaks | E2AP v2 |
| Service models | E2SM-KPM, E2SM-RC (plus CCC on the gNB side) | KPM v2 and ONF-specific models (RC-PRE, MHO, RSM) |
| xApps shipped | KPM monitors (report styles 1–5), an RC control example | KPIMON, PCI, MHO, MLB, RSM, traffic steering |
| Default RAN | a real gNB — this is what srsRAN tests against | RANSim, a simulator |
| Upstream activity | maintained; OnRamp's deps/oscric updated through 2026-05 |
in maintenance: chart 1.5.2 (2024-11), OnRamp's aether-sdran repo archived 2026-03 |
| Status on COSMOS | working with OCUDU — KPM monitoring on soft, LiteOn and Benetel rigs | deployed, working with its own RAN simulator; a real gNB cannot complete E2 Setup |
The RIC runs in Docker on a RIC host, and the OCUDU gNB on another host connects to it across the data network. OCUDU carries its E2 agent in the DU; a block in the gNB YAML turns it on, chooses the service models it offers and names the RIC:
e2:
enable_du_e2: true
e2sm_kpm_enabled: true
e2sm_rc_enabled: true
e2sm_ccc_enabled: true
addrs: 10.59.1.19 # RIC host
bind_addrs: 10.59.1.18 # this host
port: 36421
A metrics: block with the scheduler, MAC and RLC layers enabled supplies the counters; the per-UE throughput comes from RLC. Two changes adapt the upstream RIC packaging to COSMOS: its Docker network moves from 10.0.2.0/24, which lies inside COSMOS NJ address space, to 10.130.2.0/24, and the E2 port 36421/sctp is published on the host so that a gNB on another machine can reach it. The E2 KPM tutorial gives every command. The RIC changes nothing on the radio, the core or the UE, so it can be added to any working OCUDU rig; on an O-RAN 7.2 rig the gNB's own start procedure, including the golden O-RU check, stays unchanged.
SD-RAN runs on the same Kubernetes cluster as Aether SD-Core, in its own namespace sdran, as eleven pods: the E2 termination (onos-e2t), topology, configuration and UE databases, the A1 termination, the KPI-monitor xApp, the CLI, the RAN simulator and a three-node consensus store. With its bundled simulator it works: the topology lists the simulated E2 nodes and their cells, and the E2 termination decodes KPM indications. A real OCUDU gNB does not complete E2 Setup with it (see below).
The Aether SD-RAN page describes every component and compares the two RICs in depth; the SD-RAN with RANSim tutorial gives the install commands and the checks.
For work with the real COSMOS radios, use the O-RAN SC RIC. It pairs with the E2 agent built into OCUDU (both are srsRAN lineage), it is maintained upstream, and it is proven on COSMOS end to end for monitoring. Use SD-RAN to study xApp logic and the ONOS northbound interfaces — it has the larger xApp catalogue (handover, PCI assignment, load balancing, traffic steering) — but on COSMOS it drives only its own RAN simulator, and upstream it is in maintenance.
For either RIC, plan for monitoring, not control: E2SM-KPM works on every rig tried; E2SM-RC control is not accepted by the current OCUDU build. Duranta and Amarisoft rigs are not connected to a RIC on COSMOS.
| Step | Tutorial | What it covers | Status |
|---|---|---|---|
| 6 | Near-RT RIC + OCUDU — E2 KPM monitoring of a live 5G SA rig | deploy the O-RAN SC RIC, enable OCUDU's E2 agent, read cell and per-UE KPIs from soft, LiteOn and Benetel rigs | verified 2026-09-22 |
| 6 | Aether SD-RAN with RANSim | install SD-RAN on the SD-Core cluster; read its topology and confirm KPM indications from the simulated RAN | working with RANSim, verified 2026-09-22; real-gNB E2 Setup open |
The rigs it runs on are built in earlier steps: the OCUDU soft-only tutorial, the OCUDU O-RAN 7.2 tutorial and the two-server SD-Core tutorial.
E2 monitoring is verified on three rigs, each reporting through one O-RAN SC RIC while the gNB carried its normal 5G SA service. All on platform B = 2× Intel Xeon Gold 6126 @ 2.60 GHz (24 cores / 48 threads), ocudu.ndz (OCUDU commit 7238f4f407), O-RAN SC RIC i-release, measured 2026-09-22.
| Rig | Core | KPM cell DL (report style 1) | KPM per-UE DL (style 5) | iperf3 DL |
|---|---|---|---|---|
| OCUDU soft (ZMQ), no radio | Open5GS | — | 10.7–10.9 Mbit/s | 10 (offered) |
| OCUDU + LiteOn FlexFi, O-RAN 7.2 | SD-Core | 122–140 Mbit/s | 136–148 Mbit/s | 115–118 |
| OCUDU + Benetel RAN650, O-RAN 7.2 | SD-Core | 226–239 Mbit/s | 188–206 Mbit/s | 195–208 |
The KPM figures read slightly above iperf3 because the RAN counts RLC payload including headers, while iperf3 measures TCP goodput. That agreement is the check that the xApp is reading the right counters.
ue= index in its scheduler log. The reference xApp defaults to UEs [0, 1], which is right only for the first attachment on a freshly started gNB; for a UE that has re-attached, the gNB admits the subscription and sends zero indications, with no error. Subscribe a range (--ue_ids=0,…,7) or prove the path with style 1 first.cell_cfg.slicing RRM policy and matching the xApp's S-NSSAI to the gNB's both leave the result unchanged. The most likely remaining mismatch is the UE's own PDU-session S-NSSAI, which would have to agree across the core, the CU, the cell and the xApp. Monitoring is usable today; control is not.E2: Connection ... established, offers its KPM, RC and CCC functions, and after five seconds logs E2 Setup procedure failed. cause=unknown. The SCTP association itself is healthy — full handshake, ten streams each way, heartbeats exchanged in both directions — and the RIC logs Accepted connection followed by end-of-file, never a decode error or a rejected setup. The Kubernetes NodePort's SCTP translation is the first suspect, but exposing the E2 termination through a Service externalIP (the way SD-Core's AMF carries N2 over SCTP from the same gNB host) fails identically, and neither the size of the Setup Request, SCTP stream counts nor the pod network explains it. The same gNB binary completes E2 Setup against the O-RAN SC RIC, so the gNB's agent works. The cause is open; the SD-RAN page keeps the current evidence.deps/oscric and deps/sdran.Author(s): COSMOS team · Last verified: 2026-09-22 (O-RAN SC RIC i-release + OCUDU commit 7238f4f407; E2/KPM on soft, LiteOn and Benetel rigs) · text revised 2026-09-24 · Tags: ric, oran, e2, kpm, xapp, sd-ran, ocudu, 5g