Skip to main content

Lab 2: KPM Monitoring xApp using callbacks

In this experiment we will deploy a 5G Standalone (SA) network using OpenAirInterface (OAI) RF Simulator gNB and OAI minimal 5GC. We also deploy FlexRIC as the Near-RT RIC. Finally a monitoring xApp using callback leveraging the Python SDK will be deployed on bare-metal connecting to the RIC.

open-ran.yaml
apiVersion: athena.trirematics.io/v1
kind: Network
metadata:
name: bubbleran
namespace: trirematics
spec:
slices:
- plmn: "00101"
dnn: "internet"
network-mode: "IPv4"
service-type: eMBB
differentiator: 0x000000
ipv4-range: "12.1.1.0/24"
ipv6-range: "2001:db8:1::/64"
access:
- name: oai-gnb
stack: 5g-sa
model: oai-ran/monolithic-gnb
identity:
an-id: 50
radio:
device: rf-sim
cells:
- band: n78
arfcn: 641280
bandwidth: 40MHz
subcarrier-spacing: 30kHz
tdd-config:
period: 5ms
dl-slots: 7
dl-symbols: 6
ul-slots: 2
ul-symbols: 4
controller: flexric.bubbleran
core-networks:
- minimal.bubbleran
core:
- name: minimal
stack: 5g-sa
model: oai-cn/minimal
identity:
region: 0
cn-group: 4
cn-id: 5
dns:
ipv4:
default: 8.8.8.8
secondary: 8.8.4.4
edge:
- name: flexric
stack: 5g-sa
model: mosaic5g/flexric
---
apiVersion: athena.trirematics.io/v1
kind: Terminal
metadata:
name: ue1
namespace: trirematics
spec:
vendor: oai
stack: 5g-sa
model: terminal/nr-rfsim
preferred-access: oai-gnb.bubbleran
target-cores:
- minimal.bubbleran
identity:
imsi: "001010000000001"
pin: "1234"
opc: "0xc42449363bbad02b66d16bc975d77cc1"
key: "0xfec86ba6eb707ed08905757b1bb44b8f"
sqn: "0xff9bb4000001"
slice:
dnn: "internet"
network-mode: "IPv4"
service-type: eMBB
differentiator: 0x000000
radio:
bands:
- n78
readiness-check:
method: ping
target: google-ip
interface-name: oaitun_ue0

---
apiVersion: athena.trirematics.io/v1
kind: Terminal
metadata:
name: ue2
namespace: trirematics
spec:
vendor: oai
stack: 5g-sa
model: terminal/nr-rfsim
preferred-access: oai-gnb.bubbleran
target-cores:
- minimal.bubbleran
identity:
imsi: "001010000000002"
pin: "1234"
opc: "0xc42449363bbad02b66d16bc975d77cc1"
key: "0xfec86ba6eb707ed08905757b1bb44b8f"
sqn: "0xff9bb4000001"
slice:
dnn: "internet"
network-mode: "IPv4"
service-type: eMBB
differentiator: 0x000000
radio:
bands:
- n78
readiness-check:
method: ping
target: google-ip
interface-name: oaitun_ue0

Deployment​

Use the command brc install network open-ran.yaml to deploy the network. It should finish without errors and printout the three Kubernetes resource names that were created. Check for the status of the deployment using the command brc observe. Wait until all the Elements other than the UE are in the STATUS set to 1/1 Y state.

After deploying the network, before running the xApp, you should update the xApp configuration file with the IP of the deployed Near-RT RIC, the local source IP in the cluster subnet. To do so you may execute the update_conf.sh script which automatically extract the IPs from the cluster and updates the specified configuration file:

cd /path/to/xapp-source/conf_files
./update_conf.sh -c default.conf

The script will prompt the user for selecting which Near-RT RIC the xApp should connect to (in case of multiple RICs and/or networks currently deployed). After selecting a RIC to connect an output as the follwing is obtained:

Select the RIC to configure (enter number):
1) flexric.flexric.bubbleran (10.244.0.251)
Choice [1-1]: 1
Selected RIC: flexric.flexric.bubbleran with IP 10.244.0.251
Local IP for xApp: 10.244.0.218
Config file 'default.conf' updated successfully.

Once the configuration file has been updated accordingly, now the coding challenge can be tackled.

lab2.py
#/*
#Copyright (C) 2021-2025 BubbleRAN SAS
#External application
#Last Changed: 2025-05-02
#Project: MX-XAPP
#Full License: https://bubbleran.com/resources/files/BubbleRAN_Licence-Agreement-1.3.pdf)
#*/

import time
import xapp_usr_sdk as xapp
import sys

class Monitor(xapp.mntr_cb_fn):
# Inherit C++ mntr_cb_fn class
def __init__(self):
xapp.mntr_cb_fn.__init__(self)

# Override C++ method
def cb(self,v):
print("Value " + str(v))

xapp.init(sys.argv)
nodes = xapp.e2_nodes(xapp.MONITOR_USE_CASE_e)
assert(len(nodes) > 0 and "Needed at least one E2 node to monitor")

call_back = Monitor().__disown__()

n = nodes[0].node
ue = nodes[0].ue_ho[0].ue
# Step 1
# Call the signature xapp.mntr_ue_cb with the correct arguments

time.sleep(10)

# Step 2
# Stop monitoring to delete the E2AP Subscription


print("Test xApp run SUCCESSFULLY")

Single UE variable callback in Python​

For running an xApp monitoring that monitors a value in a UE presented:

cd build/labs
python3 lab2.py -c ../../conf/default.conf

If steps 1 and 2 of the coding challenge are completed successfully an output like the following should be obtained:

17:24:09.918355 [INFO]:  conf_file.c:443 Config -c file to ../conf_files/default.conf
17:24:09.918411 [INFO]: e42_xapp_api.c:81 Git SHA1 fea7dffd78de11f0d97ef16a0fda2937cbab544e
17:24:09.918417 [INFO]: e42_xapp.c:191 NearRT-RIC Server IP Address = 10.244.0.251, PORT = 36422
17:24:09.918463 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
17:24:09.918478 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
17:24:09.918768 [INFO]: msg_handler_xapp.c:533 E42 SETUP-REQUEST tx
17:24:09.918945 [INFO]: msg_handler_xapp.c:374 E42 SETUP-RESPONSE rx xApp ID 17
17:24:09.918953 [INFO]: msg_handler_xapp.c:390 Connected E2 Node(s) 1
17:24:09.919105 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
17:24:09.919471 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 1
17:24:09.920552 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
17:24:09.920750 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 1
17:24:09.920892 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
17:24:09.921064 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 2
Value 0.0
Value 0.0
Value 0.0
...
Value 0.0
Test xApp run SUCCESSFULLY
tip

In order to get values different from 0.0, traffic needs to be generated. To do so, the following command can be leveraged:

brc test throughput ue1 dl gateway -- -t 600

With the brc test throughput tool the user can generate iperf traffic from the UPF (gateway) to the UE for downlink traffic (dl) or vice-versa for uplink (ul). For more details you may check the BubbleRAN CLI reference.

If traffic is generated in the network the output should be as follows:

16:06:42.001090 [INFO]:  conf_file.c:443 Config -c file to ../conf_files/default.conf
16:06:42.001139 [INFO]: e42_xapp_api.c:81 Git SHA1 fea7dffd78de11f0d97ef16a0fda2937cbab544e
16:06:42.001146 [INFO]: e42_xapp.c:191 NearRT-RIC Server IP Address = 10.244.0.25, PORT = 36422
16:06:42.001190 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
16:06:42.001204 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
16:06:42.001504 [INFO]: msg_handler_xapp.c:533 E42 SETUP-REQUEST tx
16:06:42.001649 [INFO]: msg_handler_xapp.c:374 E42 SETUP-RESPONSE rx xApp ID 16
16:06:42.001656 [INFO]: msg_handler_xapp.c:390 Connected E2 Node(s) 1
16:06:42.001825 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
16:06:42.002449 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 1
16:06:42.003701 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
16:06:42.003896 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 1
16:06:42.004043 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
16:06:42.004204 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 2
Value 213110.9375
Value 216798.640625
Value 215967.59375
Value 208414.203125
Value 214072.515625
Value 215906.4375
Value 216903.140625

Single UE variable callback in C​

For running an xApp monitoring that monitors a value in a UE presented here:

cd build
./src/usr/c/xapp_sdk_moni_ue_cb -c ../conf/default.conf

If traffic is generated in the network the output should be as follows:

16:08:27.174426 [INFO]:  conf_file.c:443 Config -c file to ../conf_files/default.conf
16:08:27.174500 [INFO]: e42_xapp_api.c:81 Git SHA1 fea7dffd78de11f0d97ef16a0fda2937cbab544e
16:08:27.174506 [INFO]: e42_xapp.c:191 NearRT-RIC Server IP Address = 10.244.0.25, PORT = 36422
16:08:27.174545 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
16:08:27.174553 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
16:08:27.174803 [INFO]: msg_handler_xapp.c:533 E42 SETUP-REQUEST tx
16:08:27.174953 [INFO]: msg_handler_xapp.c:374 E42 SETUP-RESPONSE rx xApp ID 8
16:08:27.174958 [INFO]: msg_handler_xapp.c:390 Connected E2 Node(s) 1
16:08:27.175073 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
16:08:27.176145 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 1
16:08:27.177261 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
16:08:27.177713 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 1
16:08:27.177763 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
16:08:27.179251 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 2
RIC_REQ_ID 2 UE_THP_UL 32103.423828
RIC_REQ_ID 2 UE_THP_UL 2899.736084
RIC_REQ_ID 2 UE_THP_UL 2602.600098
RIC_REQ_ID 2 UE_THP_UL 3019.271973
RIC_REQ_ID 2 UE_THP_UL 2884.023926
RIC_REQ_ID 2 UE_THP_UL 2775.216064
RIC_REQ_ID 2 UE_THP_UL 2842.743896
RIC_REQ_ID 2 UE_THP_UL 2818.343994
RIC_REQ_ID 2 UE_THP_UL 2816.528076
16:08:37.179287 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
16:08:37.180132 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 2

Uninstall​

To uninstall the network, use the following command:

brc remove network open-ran.yaml

Checking via the brc observe command, you should see that all the elements are removed.

đź’¬ Lab Questions đź’¬

  1. What is the purpose of the callback.
  2. How can we set the periodicity of the monitoring.
  3. Dump the monitored data received through callback.
  4. What is the structure behind MONITOR_USE_CASE_e.
  5. Dump the data received for nodes[0].ue_ho[0].ue.

Advanced (optional)

This lab can also be performed leveraging an over-the-air deployment. In this section, we provide a sample deployment with a LITEON RU. Similarly to the previous deployment, this includes a 5G Standalone (SA) network with OpenAirInterface (OAI) gNB using a LITEON RU device, and Open5GS core network.

open-ran-liteon.yaml
apiVersion: athena.trirematics.io/v1
kind: Network
metadata:
name: bubbleran
namespace: trirematics
spec:
slices:
- plmn: "00101"
dnn: internet
network-mode: IPv4
service-type: eMBB
differentiator: 0x000000
ipv4-range: 12.1.1.0/24
ipv6-range: 2001:db8:1::/64
access:
- name: oai-gnb
stack: 5g-sa
model: oai-ran/monolithic-gnb-ru #cu-du-ru
identity:
an-id: 30
tracking-area: 1
radio:
device: oran-7.2
antenna:
formation: 4x4
scheduling:
nodeName: bubble2 # Change with any other CU-DU node
annotations:
# PCI IDs obtained by running `dpdk-devbind.py --status` in the CU-DU node
extras.t9s.io/pci-ids: '["0000:01:11.0", "0000:01:11.1"]'
# VF MACs obtained for dpdk0 interface by running `ip link show` in CU-DU node
extras.t9s.io/du-macs: '["02:11:22:33:44:66", "02:11:22:33:44:67"]'
# RU MAC (repeated) obtained by logging into RU and running `show eth-info`
extras.t9s.io/ru-macs: '["e8:c7:4f:25:80:f9", "e8:c7:4f:25:80:f9"]'
extras.t9s.io/mtu: '9000'
# RU IP used for logging into it
extras.t9s.io/o1-remote-ipv4: 192.168.1.40
# Flag for reboot, after first use, it can be set to `false` if values in 'cells' is not changed
extras.t9s.io/liteon-ru-reboot: 'true' #'false'
cells:
- band: n78
arfcn: 643296
bandwidth: 100MHz
subcarrier-spacing: 30kHz
tdd-config:
period: 2.5ms
dl-slots: 3
dl-symbols: 6
ul-slots: 1
ul-symbols: 4
controller: flexric.bubbleran
core-networks:
- ogscore.bubbleran
core:
- name: ogscore
stack: 5g-sa
model: open5gs/5gc
profiles:
- debug
identity:
region: 128
cn-group: 4
cn-id: 5
edge:
- name: flexric
stack: 5g-sa
model: mosaic5g/flexric
dns:
ipv4:
default: 8.8.8.8
secondary: 8.8.4.4

Deployment​

Use the command brc install network open-ran-liteon.yaml to deploy the network. It should finish without errors and printout the three Kubernetes resource names that were created. Check for the status of the deployment using the command brc observe. Wait until all the Elements other than the UE are in the STATUS set to 1/1 Y state.

After the network has been successfully deployed, the monitoring xApp can be deployed following the exact same steps previously detailed.

warning

Before deploying this network first make sure:

  1. The CU-DU node name specified in the deployment file (in this case bubble2 on the section scheduling) is correct.
  2. The CU-DU node is able to reach the RU IP specified in the deployment file. If not sure about the IP, please check the Google Sheet (provided to all customers) with all IPs of your MX-PDK. To do so you may try to ssh into the RU from the node with the command ssh user@RU-IP replacing RU-IP with the actual IP.
  3. The CU-DU node is properly synchronized with the PTP grandmaster switch. To do so you may check the status with
sudo systemctl status ptp4l.service
sudo systemctl status phc2sys.service
  1. The CU-DU node's DPDK has been setup with
sudo dpdk-setup