Lab 1: “My hello world” monitoring xApp
In this experiment, we will deploy a 5G Standalone (SA) network using OpenAirInterface (OAI) RF Simulator gNB and OAI minimal 5GC. We will also deploy FlexRIC as the Near-RT RIC and a simple "hello world" xApp on bare-metal, which will connect to the deployed RIC.
- OAI
- Amarisoft
- OCUDU
apiVersion: athena.trirematics.io/v1
kind: Network
metadata:
name: bubbleran
namespace: trirematics
spec:
slices:
- plmn: "00101"
dnn: "internet"
network-mode: "IPv4"
service-type: 1
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: 5000
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: 1
differentiator: 0x000000
radio:
bands:
- n78
readiness-check:
method: ping
target: google-ip
interface-name: oaitun_ue1
---
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: 1
differentiator: 0x000000
radio:
bands:
- n78
readiness-check:
method: ping
target: google-ip
interface-name: oaitun_ue1
apiVersion: athena.trirematics.io/v1
kind: Network
metadata:
name: amarisoft
namespace: trirematics
spec:
slices:
- plmn: "00101"
dnn: internet
network-mode: IPV4
service-type: 1
differentiator: 0xFFFFFF
ipv4-range: 12.2.1.0/24
ipv6-range: 2001:db8:1::/64
access:
- name: amr-ran
stack: 5g-sa
model: amarisoft/ran-e2
identity:
an-id: 30
tracking-area: 1
radio:
device: trx-ip
antenna:
tx-gain: "43"
rx-gain: "-50"
formation: "1x1"
cells:
- band: n78
arfcn: 632628
bandwidth: 40MHz
subcarrier-spacing: 30kHz
tdd-config:
period: 5000
dl-slots: 7
dl-symbols: 6
ul-slots: 2
ul-symbols: 4
controller: flexric.amarisoft
core-networks:
- amr-cn.amarisoft
core:
- name: amr-cn
stack: 5g-sa
model: amarisoft/basic-cn
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
---
apiVersion: athena.trirematics.io/v1
kind: Terminal
metadata:
name: amr-ue
namespace: trirematics
annotations:
extras.t9s.io/ssb-nr-arfcn: "631968"
spec:
vendor: amr
stack: 5g-sa
model: amarisoft/amr-ue
preferred-access: amr-ran.amarisoft
target-cores:
- amr-cn.amarisoft
identity:
imsi: "001010000000001"
pin: "1234"
opc: "0xc42449363bbad02b66d16bc975d77cc1"
key: "0xfec86ba6eb707ed08905757b1bb44b8f"
sqn: "0xff9bb4000001"
amr-ue-count: 1
slice:
dnn: "internet"
network-mode: "IPv4"
service-type: 1
differentiator: 0xFFFFFF
radio:
device: trx-ip
formation: "1x1"
tx-gain: "-50"
rx-gain: "0"
bands:
- n78
profiles:
- channel-simulation
apiVersion: athena.trirematics.io/v1
kind: Network
metadata:
name: ocudu
namespace: trirematics
spec:
slices:
- plmn: "00101"
dnn: internet
network-mode: IPV4
service-type: 1
differentiator: 0xFFFFFF
ipv4-range: 12.2.1.0/24
ipv6-range: 2001:db8:1::/64
access:
- name: ocudu-ran
stack: 5g-sa
model: ocudu/monolithic-gnb
identity:
an-id: 30
tracking-area: 1
radio:
device: zmq
cells:
- band: n78
arfcn: 632628
bandwidth: 40MHz
subcarrier-spacing: 30kHz
tdd-config:
period: 5000
dl-slots: 7
dl-symbols: 6
ul-slots: 2
ul-symbols: 4
controller: flexric.ocudu
annotations:
extras.t9s.io/log-level: "debug"
core-networks:
- amr-cn.ocudu
core:
- name: amr-cn
stack: 5g-sa
model: amarisoft/basic-cn
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
---
apiVersion: athena.trirematics.io/v1
kind: Terminal
metadata:
name: amr-ue
namespace: trirematics
annotations:
extras.t9s.io/ssb-nr-arfcn: "631680"
spec:
vendor: amr
stack: 5g-sa
model: amarisoft/amr-ue
preferred-access: ocudu-ran.ocudu
target-cores:
- amr-cn.ocudu
identity:
imsi: "001010000000001"
pin: "1234"
opc: "0xc42449363bbad02b66d16bc975d77cc1"
key: "0xfec86ba6eb707ed08905757b1bb44b8f"
sqn: "0xff9bb4000001"
amr-ue-count: 1
slice:
dnn: "internet"
network-mode: "IPv4"
service-type: 1
differentiator: 0xFFFFFF
radio:
device: zmq
formation: "1x1"
tx-gain: "0"
rx-gain: "0"
bands:
- n78
Prerequisites (Optional for OAI)
apiVersion: v1
kind: Service
metadata:
name: amr-ue-terminal
namespace: trirematics
spec:
publishNotReadyAddresses: true
selector:
athena.t9s.io/vendor: amr-ue-terminal
ports:
- name: trx-rx
protocol: UDP
port: 12000
targetPort: 12000
- name: trx-tx
protocol: UDP
port: 12001
targetPort: 12001
- name: zmq-gnb-rx
protocol: TCP
port: 2101
targetPort: 2101
- name: zmq-gnb-rx
protocol: TCP
port: 2100
targetPort: 2100
- Apply the service
kubectl apply -f amr-ue-terminal.yaml
- Check the service
kubectl get svc -n trirematics | grep amr-ue-terminal
- (Optional) Delete the service
kubectl delete service amr-ue-terminal -n trirematics
Apply the network
-
add spec.edge.profiles.amarisoft in order for xApp to get valid kpm measurement value
-
set terminal.metadata.annotations.extras.ssb-nr-arfcn in order for amarisoft ue connect to the gNB
Deployment
Use the command brc install network open-ran.yaml to deploy the network.
It should finish without errors and print out 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 can execute the update_conf.py script, which automatically extracts the IPs from the cluster and updates the specified configuration file:
cd /path/to/xapp_sdk/conf
python3 update_conf.py xapp.yaml
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 to, an output like the following is obtained:
Select the RIC to configure:
1) flexric.flexric.handover (10.244.2.46)
Choice [1-1]: 1
No entries found for Database.
Skipping database IP update.
Config 'xapp.yaml' updated: ip_ric=10.244.2.46, ip_xapp=10.244.0.158
Once the configuration file has been updated accordingly, you can proceed with the coding challenge of lab 1.
/*
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)
*/
#include "xapp_sdk_api.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv)
{
init_xapp_sdk(argc, argv);
// Step 1
// Retrieve information from the nearRT-RIC
// Don't forget to free it afterwards!!!
// Possible naming convention! Feel free to use it or discard it!
// global_e2_node_id_sdk_t const* node = &arr.n[0].node ;
// ue_id_e2sm_sdk_t const* ue = &arr.n[0].ue_ho[0].ue;
// Step 2
// Select monitoring variable
// e.g., mntr_var_e var = UE_THP_DL;
mntr_var_e var = END_MNTR_VAR_E;
// Step 3
// Call the function ue_mntr_xapp_sdk with
// the appropiate variables and measure the response latency
int64_t const t0 = time_now_us_sdk();
// Code Here!!!
int64_t const t1 = time_now_us_sdk();
printf(" elapsed time %ld\n", t1 - t0);
// Step 4
// Free the resources
return EXIT_SUCCESS;
}
./build/labs/lab1 conf/xapp.yaml
After compiling and running the code successfully, you should get the following output:
22:55:49.395124 [INFO]: e42_xapp.c:191 NearRT-RIC Server IP Address = 10.244.0.46, PORT = 36422
22:55:49.395188 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
22:55:49.395200 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
22:55:49.395238 [INFO]: e42_xapp.c:227 DB_ENABLE = FALSE
22:55:49.395240 [INFO]: e42_xapp.c:232 do not initial database
22:55:49.395658 [INFO]: msg_handler_xapp.c:533 E42 SETUP-REQUEST tx
22:55:49.396094 [INFO]: msg_handler_xapp.c:374 E42 SETUP-RESPONSE rx xApp ID 11
22:55:49.396116 [INFO]: msg_handler_xapp.c:390 Connected E2 Node(s) 1
22:55:49.396559 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
22:55:49.396927 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 1
22:55:49.398374 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
22:55:49.398615 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 1
22:55:49.398724 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
22:55:49.399254 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 2
22:55:49.400355 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
22:55:49.400640 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 2
UE throughput in downlink 389752.000000
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 💬
- What is the IP address and port of the Near-RT RIC?
- What is the IP address and port of gNB?
- Measure how much time it takes between subscription to a service model (e.g. KPM) and the reception of the indication.
- What is the meaning of
RAN_FUNC_IDandRIC_REQ_ID? - Describe the xApp lifecycle.
- What are the different types of xApps?
You can obtain Wireshark captures from a given element, i.e., the ones listed in the dashboard with brc observe.
For example, in this lab, for flexric.flexric.bubbleran:
brc extract pcap flexric.flexric.bubbleran | sudo wireshark -k -i -
For more information on this tool you can check the brc reference
Advanced
- Open Wireshark, filter by E2AP, and draw the message sequence chart of the transaction between the E2 node and the Near-RT RIC. You can leverage this tool.
- Identify the interface between the xApp and the Near-RT RIC.