Skip to main content
Version: v4.0.0 [Denim]

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.

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 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.

lab1.c
/*
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 💬

  1. What is the IP address and port of the Near-RT RIC?
  2. What is the IP address and port of gNB?
  3. Measure how much time it takes between subscription to a service model (e.g. KPM) and the reception of the indication.
  4. What is the meaning of RAN_FUNC_ID and RIC_REQ_ID?
  5. Describe the xApp lifecycle.
  6. What are the different types of xApps?
tip

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

  1. 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.
  2. Identify the interface between the xApp and the Near-RT RIC.