Skip to content

KPI Monitoring rApp

The KPI Monitoring rApp is an open-source Non-RT RIC application for monitoring a live OCUDU 5G network over standard O-RAN interfaces. It turns the O1 performance stream of each gNB into cell, gNB and UE KPIs, raises threshold alerts, and exposes both to other rApps over R1. It also manages the O-RUs behind each gNB over the O-RAN M-plane, through the SMO SDNR controller.

The rApp runs on the same TOSSI Open RAN O1 Stack as the Cell Congestion Optimization rApp: an OCUDU RAN, the OCUDU O1 Adaptor and the OCUDU NETCONF server, managed by an ONAP-based SMO and the O-RAN Software Community Non-RT RIC. Where the congestion rApp closes a control loop, this rApp gives operators a single view of the RAN and its radios, covering live KPIs, alarms, timing state and a topology of gNBs and the O-RUs they drive.

Architecture

The rApp works with four cooperating components.

OCUDU RAN. A monolithic 5G gNB connected to O-RUs over Open Fronthaul 7.2x. It publishes per-cell and per-UE metrics on its remote-control WebSocket, including the fronthaul MAC addresses of each cell when RU metrics are enabled.

OCUDU O1 Adaptor. Reads the gNB metrics stream and translates it into 3GPP TS 28.554 performance-management envelopes. For each unlocked PerfMetricJob it posts an envelope to the job's streamTarget every granularity period.

OCUDU NETCONF. Presents the gNB as a 3GPP network resource model over O1, and holds the PerfMetricJob that points the performance stream at the rApp.

KPI Monitoring rApp. Receives the performance envelopes on POST /pm and stores KPIs in its own InfluxDB. Alert rules are evaluated on every report. KPI and alert information types are published to other rApps through DME, and the rApp's API is registered through SME. O-RUs are reached through SDNR, using RESTCONF to NETCONF, and their performance notifications arrive on SDNR's device notification stream. The rApp is onboarded onto the O-RAN SC Non-RT RIC over R1 and serves an operator dashboard with admin and viewer roles.

KPI Monitoring rApp architecture. On the left, a Radio Units column holds two LITEON O-RUs named liteon-oru-1 and liteon-oru-2 plus a further O-RU, each reached over NETCONF port 830. In the centre, the SMO Framework and Non-RT RIC runs on Kubernetes with microk8s. Its nonrtric namespace holds platform services: rApp Manager for R1 lifecycle and CSAR, ICS informationservice for R1 DME on port 9082, dmeparticipant as the DME element, ChartMuseum for helm charts, and CAPIF and SME providing capifcore, servicemgr and Kong. A separate ONAP namespace holds the ACM runtime, as policy-clamp-runtime-acm, and the Kubernetes participant. Below these sits the TOSSI KPI Monitoring rApp itself, built with Go and the OTAF rApp SDK and exposed on NodePort 30097 mapping to port 8080. It contains four blocks: an R1 DME producer publishing the metrics and alerts information types with producer-health and callback endpoints; an SME published API exposed through CAPIF and Kong, serving api/metrics/gnb, cell and slices plus api/alerts/list and api/ru/status; a Dashboard with authentication, where operator accounts are bcrypt-hashed and an empty list means no sign-in; and Storage and Config using an InfluxDB statefulset on a 5 GiB volume, a fleet.json file on a 64 MiB volume, and rapp.yaml through Helm and environment variables. A PM path runs in four numbered stages: stage one, httpsrc receives POST /pm and returns 202 Accepted, or 503 when the pipeline is full, with no session needed; stage two, the SDK ingest pipeline takes an ingest message with source http/pm; stage three, Engine.Handle calls ocudu.ParseEnvelope to produce PMData, where cells with no slice or general data are counted only; stage four, record writes PMData to InfluxDB, evaluates PM data into alerts, and sends the latest per gNB to R1. A Radio Fleet and M-plane client block holds a summary poller running every 30 seconds at 16 radios at a time, a Fleet API at api/ru/fleet that adds radios by adopting an existing node or mounting a new one with a duplicate-host guard, gNB links that map each gNB to its O-DU MAC addresses taken from the gNB YAML ru_ofh du_mac_addr field, an RU service using the sdnrPlane with status and config GET, PATCH and DELETE plus a reset RPC that requires allow_writes, an O-DU MAC resolver using vendor CLI over SSH with a 10 minute cache and an M-plane o-du-mac-address fallback that flags disagreements, and a PM notification subscriber that subscribes to device notifications over SSE and re-sends the subscription every 2 minutes, holding 240 samples or about 2 hours in memory. On the right, SDNR, shown as onap-sdnc-0 running ONAP SDN-R, provides NETCONF and RESTCONF with mounted NETCONF nodes for Radio Unit 1, Radio Unit 2, gNb1 and gNb 2, and a southbound NETCONF port 830. Beneath it a Dashboard thumbnail is shown. At the bottom, the OCUDU RAN site holds OCUDU gNb 1, a DU with ru_ofh where ran_node_name is the PM measurement id, containing DU-HIGH with the scheduler, CU-CP with cu-cp metrics, a metrics WebSocket for remote control, and RU_OFH carrying du_mac_addr, alongside gNb 2 and gNb 3. These feed an O1 Adapter over a metrics websocket; the adapter runs a NETCONF loop, a WebSocket loop, PM metrics, alarm to VES conversion, REST health and RRMPolicyRatio. The adapter posts an HTTP JSON envelope to /pm every granularity period up to the rApp. A fronthaul switch with a PTP grandmaster and GNSS feeds timing to the RAN site and the radio units.
The rApp in its SMO. The O1 Adaptor posts a performance envelope to /pm every granularity period; the rApp stores KPIs in InfluxDB, raises alerts, publishes both over R1, and reaches each O-RU through SDNR.
Topology diagram of the lab. Host 4 runs the SMO on cmicrok8s with a Non-RT RIC, built from O-RAN Software Community and ONAP components, and holds SDNR, the KPI rApp, ICS with CAPIF, and rApp Manager, with rApps onboarded over R1 and radios mounted in SDNR. Host 1 runs OCUDU gNB 412 and Host 2 runs OCUDU gNB 411, each with CU-CP, a DU with ru_ofh, an O1 adapter and NETCONF on port 830. Both gNBs reach the SMO over O1, using NETCONF and POST /pm, and reach their radios over the M-plane using NETCONF port 830 via SDNR. Host 5 runs a Near-RT RIC hosting xApps for 10 millisecond to 1 second control, with an E2 termination, xApps and an A1 mediator; it takes policy in over A1 from the SMO and sends control out over E2 to both gNBs using E2AP. Host 3 runs an SD-Core 5G core with AMF, SMF and UPF, connected to both gNBs over N2 for the control plane and N3 for the user plane, using NGAP and GTP-U. At the bottom, a LITEON O-RU connects to gNB 1 over Open Fronthaul 7.2, through a fronthaul switch with a PTP grandmaster fed by GNSS, while a second LITEON O-RU and a Benetel O-RU connect to gNB 2 over Open Fronthaul 7.2. A legend lists the interfaces: O1, A1, E2, N2 and N3, Open Fronthaul, and the M-plane.
The lab topology. Two OCUDU gNBs drive LITEON and Benetel radios over Open Fronthaul 7.2x, peer with an SD-Core, and are managed over O1 by the SMO that hosts the rApp. The M-plane reaches each radio through SDNR.

Features

RAN performance monitoring

  • Ingests 3GPP TS 28.554 performance envelopes from the OCUDU O1 Adaptor on POST /pm, at the granularity period set by the PerfMetricJob.
  • Cell KPIs: DL and UL throughput, connected UEs, PRB utilisation, DL and UL BLER, and serving RSRP.
  • gNB KPIs: totals across each gNB's cells.
  • UE KPIs: CQI, MCS, rank and PUSCH SNR.
  • KPIs the RAN does not report are shown as missing rather than as zero.
  • Time-series history in the rApp's own InfluxDB, with trend charts in the dashboard.
The KPI Monitoring dashboard overview page. A left navigation rail lists Overview, Cell Metrics, Cluster View, KPI Trends, Network Slices, Network Topology, Radio Units, Notifications with 2 pending, Alerts with 2 pending, and Settings. The main panel offers time ranges of 15 minutes, 1 hour, 6 hours and 24 hours, with 1 hour selected. Four summary tiles read 23 active UEs, 126.55 Mbps DL throughput, 8.13 Mbps UL throughput, and 2 active alerts. A throughput trends chart plots network DL and UL throughput from 05:15 pm to 06:12 pm, with a peak of DL 121.38 Mbps and UL 11.40 Mbps and an average of DL 96.29 Mbps and UL 8.56 Mbps. A network health panel shows 2 active gNBs with 2 of 5 connected, 3 active cells with 3 of 7 active, an uptime of 7 days 6 hours 10 minutes, and a last update timestamp. Below are a PRB utilisation chart and an active UEs over time chart, the latter peaking at 26 UEs against an average of 24.4.
The overview page. Live totals for UEs, throughput and alerts, with network health and the trend charts backed by the rApp's InfluxDB history.
The Cell Metrics page, grouped by gNB. Six summary tiles read 2 gNBs, 3 cells, 68 active UEs, 46904.6 average DL kbps, 2816.5 average UL kbps, and 0 critical cells. Below, gNB ran1 is marked active with 1 cell and 1 UE, 13 kbps down and 4.2 kbps up, and PRB usage of 0 and 0.1 percent. Its single cell ran1-2 is listed as NR technology with Good status, 1 UE, 13 kbps DL, 4.2 kbps UL, PRB DL 0, PRB UL 0.1, PRB DL raw 48, PRB UL raw 120, 273 available PRBs, a BLER of 80, PCI 2 and TAC 0. gNB ran2 is active with 2 cells and 23 UEs, 70350.4 kbps down and 4222.7 kbps up, and PRB usage of 18.6 and 4.4 percent. Its cell ran2-3 shows 14 UEs, 76987.6 kbps DL, 4469.3 kbps UL, PRB DL 18.8, PRB UL 4.6, RSRP minus 83.7, BLER 3.316 and 3.095, and PCI 3. Its cell ran2-4 shows 9 UEs, 63713.3 kbps DL, 3976 kbps UL, PRB DL 18.4, PRB UL 4.3, RSRP minus 87.9, BLER 4.529 and 4.798, and PCI 4. Columns with no reported value show a dash rather than a zero.
Cell KPIs grouped by gNB. Values the RAN does not report are shown as a dash, so a missing KPI is never read as a zero.
The KPI Trends throughput page. Tabs offer Last Hour, 6 Hours, 24 Hours and 7 Days. A table titled All gNB Throughput Details lists gNB ran1 with 0.0 kbps current DL and UL, 0.0 kbps total, 0.1 kbps average DL, 0.0 kbps average UL, 0.3 kbps peak DL, 0.1 kbps peak UL, 0 UEs and a downward trend of 100 percent; and gNB ran2 with 194.93 Mbps current DL, 13.07 Mbps current UL, 208.00 Mbps total, 189.45 Mbps average DL, 16.90 Mbps average UL, 242.77 Mbps peak DL, 22.80 Mbps peak UL, 22 UEs and an upward trend of 0.8 percent. Below, a throughput trends chart for ran2 plots DL and UL throughput from 05:15 pm to 06:12 pm, with a peak of DL 242.77 Mbps and UL 22.80 Mbps against an average of DL 189.77 Mbps and UL 16.92 Mbps.
Trends over one hour to seven days, per gNB. Current, average and peak figures sit alongside the series, so a spike can be separated from a sustained change.

Alerting

  • Threshold rules are defined in configuration, so operators can tune them without a rebuild.
  • Alerts are deduplicated while a condition persists, and cleared when it recovers.

R1 data exposure

  • Publishes two DME information types, KPI reports and active alerts, so other rApps can consume them through ICS.
  • Registers its service API with SME (CAPIF) on deployment.
  • Onboarded, primed and deployed through rApp Manager as a standard CSAR.

O-RU management over the M-plane

  • Reaches O-RUs through SDNR, using RESTCONF to NETCONF, or directly over NETCONF when no SDNR is configured.
  • Per radio: inventory, PTP and sync state, delay profile, FM alarms, and live PM covering power, temperature, transceiver and fronthaul receive-window counters.
  • Edits the standard O-RAN YANG settings a radio advertises in its YANG library, so any O-RAN-compliant O-RU works.
  • LITEON vendor settings and fronthaul status over SSH.
  • Radio reset through the standard o-ran-operations RPC.
  • Radio PM arrives on SDNR's device notification stream, with automatic recovery when the stream goes quiet.
The Radio Units page. A fleet table lists three radios filtered by All 3, Healthy 0, Alarms 3 and Unreachable 0, with an Add radio button. Under gNB ran1 is one radio, liteon-oru, a LITEON O-RU with serial 230236502, reached via SDNR node liteon-oru, O-DU MAC 00:11:22:33:44:55, fronthaul state Ready and 2 alarms. Under gNB ran2 are two radios: liteon-oru-3, a LITEON O-RU with serial 230236517 and O-DU MAC 00:11:22:33:44:66, with 1 alarm; and benetel-oru, a Benetel RAN550 with serial 2245650107 and O-DU MAC 00:11:22:33:44:67, with 1 alarm. Below, a detail panel for LITEON O-RU liteon-oru at 100.126.14.66, software version 02.00.09, serial 230236502, shows status chips reading M-plane connected, PM live 33 seconds ago, Writes enabled and 2 alarms. Tabs offer Health, Timing and Sync, Alarms and Configure. Five tiles read 10.00 watts power draw with a minimum of 9.32 and maximum of 10.81, 55.6 degrees Celsius temperature with a maximum of 56.2, 2 active alarms of which 1 is major or critical, 100.00 percent U-plane on time with 0.000 percent late and 0.001 percent early, and 62.13 percent C-plane on time with 37.87 percent early and 0.000 percent late. Power and temperature charts follow.
The radio fleet, grouped under the gNB that drives each radio. The detail panel carries live M-plane PM: power draw, temperature, alarm counts and the fronthaul receive-window on-time percentages.
The vendor settings page for a LITEON radio. A Radio panel holds TX attenuation set to 11 dB, RX attenuation 14 dB, centre frequency 3450720000 Hz, channel bandwidth 100 MHz, IQ compression 9-bit BFP and subcarrier spacing 30 kHz at numerology 1. A Fronthaul panel holds C-plane and U-plane VLAN 564, DU MAC address 001122334455, PRACH eAxC IDs for ports 0 to 3 reading 4 5 6 7, and jumbo frames at MTU 9600. An Applied after reset panel holds sync source PTP, DPD enabled, phase compensation enabled, TX power target 18 dBm and M-plane supervision disabled. A Management panel lists M-plane VLAN 0, default gateway 192.168.1.1, RJ45 VLAN IP 10.101.131.61, SFP+ VLAN IP 10.101.131.62 and SFP+ static IP 192.168.1.100. A footer reads one pending change, TX attenuation 17 to 11, with Discard, Validate on RU and Apply to RU buttons.
Editing a radio. Changes are staged and validated against the radio before they are applied, and the whole editor can be disabled with one setting.

Discovery and topology

  • O-RUs connected in SDNR join the fleet automatically. Others can be added by name and M-plane address from the dashboard.
  • Each O-RU is linked to the gNB cell that reports its fronthaul MAC address, with the O-DU connection state shown.
  • A network topology page shows every gNB and the radios it drives, with key figures on hover and a click-through to each gNB or radio.
  • The radio fleet is kept on a persistent volume and survives restarts and redeploys.
The Network Topology page. A legend distinguishes gNB nodes, radio unit nodes, a solid line for fronthaul where MACs match, a dashed line for links matched by O-DU MAC only, a red dashed line for an O-DU MAC mismatch, and a dotted line for PM flowing to this rApp. At the top centre, a KPI Monitoring node is marked as this rApp on the SMO, with dotted lines reaching five gNB nodes: ran5 with 2 cells, ran6 with 1 cell, ran1 with 1 cell, ran2 with 2 cells and ran4 with 1 cell. Nodes ran5, ran6 and ran4 carry a red status dot, while ran1 and ran2 carry a green one. Below, three radio units hang off their gNBs: liteon-oru at PCI 2 under ran1 on a solid fronthaul line, and liteon-oru-3 at PCI 3 and benetel-oru at PCI 4 under ran2, the first on a solid line and the second on a dashed line. Each radio carries an amber status dot.
The topology page. Each radio is placed under the gNB cell that reports its fronthaul MAC, and the line style records how firmly the link was established.

Access control

  • Operator sign-in for the whole rApp, with bcrypt-hashed accounts.
  • Admin and viewer roles: only admins can add, remove or configure radios.
  • Radio changes can be disabled entirely with a single setting.

Operations

  • /health, /ready, /status and Prometheus /metrics endpoints.
  • Configuration through a YAML file, with environment variable overrides for secrets. Settings that are still empty are logged at startup.
  • Packaged as a Helm chart with its own InfluxDB.

Prerequisites

  • A Linux host for the RAN, with a DPDK-capable fronthaul NIC and access to O-RUs.
  • Python 3 for the O1 adapter.
  • Docker Engine 24.0 or newer, for the NETCONF server and the rApp image.
  • An O-RAN SC Non-RT RIC with rApp Manager, ChartMuseum and ICS, and an ONAP SDNR with the O-RUs mounted or reachable. This is the primary deployment target, using R1-based onboarding.
  • Go 1.23 or newer, Helm 3 and rappctl from the OTAF rApp SDK, to build the rApp package.
sudo apt install python3 python3-venv python3-pip
go install github.com/coranlabs/OTAF/otaf-rapp-sdk/cmd/rappctl@latest

Deployment

Clone the TOSSI components into a working directory:

git clone -b xnap_handover https://github.com/TOSSI-Foundation/OCUDU-RAN.git
git clone -b main https://github.com/TOSSI-Foundation/OCUDU-Netconf.git
git clone -b main https://github.com/TOSSI-Foundation/OCUDU-O1-Adaptor.git
git clone -b main https://github.com/TOSSI-Foundation/kpi-monitoring-rapp.git

NETCONF server (start first)

cd OCUDU-Netconf
docker build -t ocudu-netconf/ocudu-netconf:latest .
docker run -it --name ocudu-netconf -p 830:830 ocudu-netconf/ocudu-netconf:latest --config gnb
cd ..

The server is ready when it logs that it is listening for connections on port 830.

RAN (gNB)

Build the gNB, installing the build dependencies listed in the OCUDU-RAN README first, including DPDK:

cd OCUDU-RAN
mkdir -p build && cd build
sudo cmake -DDU_SPLIT_TYPE=SPLIT_7_2 -DENABLE_DPDK=True -DASSERT_LEVEL=MINIMAL -DENABLE_UHD=OFF ../
make -j "$(nproc)"
cd ../..

Edit a LITEON example configuration under OCUDU-RAN/configs/ for your site, covering the core and AMF address, the fronthaul NIC, the O-RU parameters and the CPU affinities. Enable JSON metrics and the RU metrics layer, which carries the fronthaul MAC addresses the rApp uses to link each O-RU to its gNB:

remote_control:
  enabled: true
  bind_addr: 0.0.0.0
  port: 8001

metrics:
  enable_json: true
  layers:
    enable_ru: true

If the gNB does not report fronthaul MACs, the rApp still monitors its KPIs and its O-RUs, but lists the O-RUs under no gNB.

Then run the gNB:

sudo ./OCUDU-RAN/build/apps/gnb/gnb -c OCUDU-RAN/configs/<your-gnb-config>.yml

O1 adapter

cd OCUDU-O1-Adaptor
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/python src/o1_adapter.py \
  --netconf_host localhost --netconf_port 830 \
  --netconf_username root --netconf_password root \
  --profile gnb --ws_host localhost --ws_port 8001
cd ..

KPI Monitoring rApp

Primary path: R1-based deployment through the O-RAN SC Non-RT RIC rApp Manager.

The ACM Kubernetes participant installs the chart from ChartMuseum and ignores instance values, so site configuration and secrets have to be built into the package. scripts/package.py writes them into a git-ignored copy of the chart and runs rappctl package.

Create the operator accounts. Each entry is name:bcrypt-hash, and rappctl hashpw prints the hash for a password:

rappctl hashpw   # once per account

Build the image and push it to the SMO's local registry, which the chart pulls from by default at localhost:5000. To use another registry, set global.registry.url in deploy/helm/kpi-monitoring-rapp/values.yaml before packaging:

cd kpi-monitoring-rapp
docker build -t localhost:5000/kpi-monitoring-rapp:1.0.0 .
docker push localhost:5000/kpi-monitoring-rapp:1.0.0

Build the CSAR with your site's values:

SDNR_PASSWORD=<sdnr-admin-password> \
FLEET_KEY_ID=<sdnr-keystore-key> \
RU_KEY_FILE=<ssh-key-for-o-rus> \
RU_ALLOW_WRITES=true \
OPERATOR_ACCOUNTS='admin:<hash>,viewer:<hash>' \
ADMIN_ACCOUNTS=admin \
NODE_PORT=30096 \
python3 scripts/package.py
rappctl validate dist/kpi-monitoring-rapp-1.0.0.csar
VariablePurpose
SDNR_PASSWORD, SDNR_ADDRReach O-RUs through SDNR. SDNR_ADDR defaults to http://sdnc.onap.svc.cluster.local:8282
FLEET_KEY_IDSDNR keystore key used when the rApp mounts a new O-RU
RU_KEY_FILESSH key for O-RUs reached directly, and for LITEON vendor settings
RU_ALLOW_WRITESAllow adding, removing and configuring O-RUs from the dashboard
OPERATOR_ACCOUNTSDashboard accounts. With any set, the whole rApp requires sign-in
ADMIN_ACCOUNTSAccounts allowed to change O-RUs. The others can only view
NODE_PORTDashboard NodePort

Upload the chart, then onboard, prime, create an instance and deploy:

RM=$(kubectl get svc rappmanager -n nonrtric -o jsonpath='{.spec.clusterIP}')
CM=$(kubectl get svc chartmuseum -n nonrtric -o jsonpath='{.spec.clusterIP}')

# upload the chart
unzip -o -j dist/kpi-monitoring-rapp-1.0.0.csar \
  Artifacts/Deployment/HELM/kpi-monitoring-rapp-1.0.0.tgz -d dist/
curl --data-binary @dist/kpi-monitoring-rapp-1.0.0.tgz http://$CM:8080/api/charts

# onboard
curl -X POST http://$RM:8080/rapps/kpi-monitoring-rapp \
  -F file=@dist/kpi-monitoring-rapp-1.0.0.csar

# prime
curl -X PUT http://$RM:8080/rapps/kpi-monitoring-rapp \
  -H 'Content-Type: application/json' -d '{"primeOrder":"PRIME"}'

# create instance (ACM + SME + DME), capture the instance id
IID=$(curl -s -X POST http://$RM:8080/rapps/kpi-monitoring-rapp/instance \
  -H 'Content-Type: application/json' \
  -d @dist/kpi-monitoring-rapp-instance-body.json \
  | python3 -c 'import json,sys;print(json.load(sys.stdin)["rappInstanceId"])')
echo "instance: $IID"

# deploy
curl -X PUT http://$RM:8080/rapps/kpi-monitoring-rapp/instance/$IID \
  -H 'Content-Type: application/json' -d '{"deployOrder":"DEPLOY"}'

The instance body creates the ACM instance kpimonitoringrapp-instance, the SME provider and API kpi-monitoring-rapp-provider and kpi-monitoring-rapp-api, and the DME producer kpi-monitoring-rapp-producer with the information types kpi-monitoring-rapp-metrics and kpi-monitoring-rapp-alerts.

When the instance reports DEPLOYED, open the dashboard at http://<node-ip>:30096 and sign in.

The example configuration ships two accounts, one per role:

UsernamePasswordRole
adming_Ski2att3kWHGXaFull access, including adding, removing and configuring radios
viewerANrhsROhVS7yjqKlRead-only

Optional: manual Helm deployment, standalone and without R1.

docker build -t <registry>/kpi-monitoring-rapp:1.0.0 .
docker push <registry>/kpi-monitoring-rapp:1.0.0
helm install kpi-monitoring-rapp deploy/helm/kpi-monitoring-rapp -n <namespace> \
  --set global.registry.url=<registry> --set image.tag=1.0.0 \
  --set ru.sdnr.endpoint=<sdnr-restconf-url> \
  --set secrets.sdnrPassword=<password> \
  --set ru.allowWrites=true --set fleet.mountKeyId=<sdnr-keystore-key> \
  --set secrets.operatorAccounts='admin:<hash>' --set adminAccounts=admin \
  --set secrets.influxdbAdminPassword=<password> \
  --set secrets.influxdbAdminToken=<token> --set secrets.influxdbToken=<token>

The chart deploys the rApp's own InfluxDB alongside it.

Provision O1 performance streaming

The NETCONF server re-seeds its factory config on every start, so run this once after it comes up, and again after any restart, to point the gNB's O1 performance stream at the rApp. It is an idempotent merge and is safe to re-run.

STREAM_TARGET="http://<node-ip>:30096/pm" ./OCUDU-O1-Adaptor/venv/bin/python - <<'PY'
import os
from ncclient import manager
t = os.environ["STREAM_TARGET"]
cfg = f"""<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><ManagedElement xmlns="urn:3gpp:sa5:_3gpp-common-managed-element"><id>ran1</id><GNBCUCPFunction xmlns="urn:3gpp:sa5:_3gpp-nr-nrm-gnbcucpfunction"><id>cucp1</id><PerfMetricJob><id>kpi-monitoring-rapp</id><attributes><administrativeState>UNLOCKED</administrativeState><performanceMetrics>DRB.MaxActiveUeDl</performanceMetrics><granularityPeriod>5</granularityPeriod><streamTarget>{t}</streamTarget></attributes></PerfMetricJob></GNBCUCPFunction></ManagedElement></config>"""
with manager.connect(host="localhost", port=830, username="root", password="root", hostkey_verify=False, allow_agent=False, look_for_keys=False, timeout=20) as m:
    m.edit_config(target="running", config=cfg, default_operation="merge")
    print("PerfMetricJob:", "PROVISIONED" if "kpi-monitoring-rapp" in m.get_config(source="running").data_xml else "FAILED")
PY

Prints PerfMetricJob: PROVISIONED on success. The adapter picks up the job over its NETCONF subscription, so no restart is required. Inside the cluster, the target can be http://kpi-monitoring-rapp.<namespace>.svc.cluster.local:8080/pm.

Verify

  • The gNB appears in the dashboard's cell and gNB views within one granularity period.
  • O-RUs connected in SDNR appear under Radio Units and on the Network Topology page, grouped under the gNB that drives them.
  • GET /health on the rApp returns 200.

References