Skip to main content

Lab 10: Custom ISAC E2SM xApp

This experiment is to 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 an ISAC (Integrated Sensing and Communication) xApp for extracting uplink Sounding Reference Signal (SRS) I/Q samples will be deployed on bare-metal connecting to the RIC.

warning

This lab is only meant to be performed using OAI RAN on Over-the-Air deployments (i.e. using USRP, LITEON RU or Benetel RU) The sample network template file is for a deployment with LITEON RU, for USRP refer to this template and for Benetel RU refer to this template.

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.

tip

Please refer to this guide for detailed steps to run pre-checks before deploying networks using O-RAN 7.2 FHI with LITEON RU.

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 and the deployed database. To do so you may execute the update_conf.py script which automatically extract the IPs from the cluster and updates the specified configuration file:

cd /path/to/xapp_sdk/conf
python3 update_conf.py xapp.yaml
tip

Once the network is deployed, traffic can be generated between the UEs and the network with the following commands:

brc test throughput ue1 dl gateway -- -t 600
brc test throughput ue2 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.

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). Since xapp_all_sm.conf also defines the database information, the script will prompt the user to specify which database in the deployed network to connect to.

After selecting a RIC and database to connect, an output as the following is obtained:

Select the RIC to configure:
1) flexric.ric.oran (10.244.1.202)
Choice [1-1]: 1
Select the Database to configure:
1) mysql-db.sdl.oran (10.244.1.193)
Choice [1-1]: 1
Config 'xapp.yaml' updated: ip_ric=10.244.1.202, ip_xapp=10.244.0.158, db.ip=10.244.1.193

Once the configuration file has been updated accordingly, now the ISAC xApp can be run.

ISAC xApp​

This xApp uses the our ISAC Service Model to subscribe to aperiodic SRS event triggers. In its callback unpacks each indication to read the SRS I/Q buffer length (len_srs_iq) and raw 16-bit I/Q pairs, to then timestamp each batch to compute end-to-end latency.

xapp_isac_srs.c
#include "../include/src/xApp/e42_xapp_api.h"
#include "../include/src/util/alg_ds/alg/defer.h"
#include "../include/src/util/time_now_us.h"
#include "../include/src/sm/isac_sm/isac_sm_id.h"
#include <poll.h>
#include <stdio.h>

void cb(sm_ag_if_rd_t const *rd, global_e2_node_id_t const *n)
{
assert(n != NULL);
assert(rd != NULL);
assert(rd->type == INDICATION_MSG_AGENT_IF_ANS_V0);
assert(rd->ind.type == ISAC_STATS_V0);

isac_ind_data_t const* ind = &rd->ind.isac;
isac_ind_msg_t const* msg = ind->msg; // needed for flexible array member
printf("Timestamp %ld latency %ld \n", msg->tstamp, time_now_us() - msg->tstamp);
printf("len_srs_iq %lu \n", msg->len_srs_iq);

// int16_t const* srs_iq = msg->srs_iq;
for(size_t i = 0; i < msg->len_srs_iq; ++i){
// printf("re %d im %d noise_re %d noise_im %d \n",srs_iq[4*i], srs_iq[4*i+1], srs_iq[4*i+2], srs_iq[4*i+3]);
}
}

static
isac_sub_data_t gen_isac_sub_data(void)
{
isac_sub_data_t dst = {0};
dst.et.type = APERIODIC_ISAC_EVENT;
dst.et.aper = SRS_ISAC_EVENT_TRIGGER_APER;

return dst;
}

int main(int argc, char *argv[])
{
assert(argc == 2);

//Init the xApp
init_xapp_api(argv[1]);
poll(NULL, 0, 1000);

e2_node_arr_xapp_t arr = e2_nodes_xapp_api();
defer({ free_e2_node_arr_xapp(&arr); });

assert(arr.len > 0);
sm_ans_xapp_t* hndl = calloc(arr.len, sizeof(sm_ans_xapp_t));
defer({ free(hndl); });

// Generate RAN CONTROL Subscription
isac_sub_data_t isac_sub = gen_isac_sub_data();
defer({ free_isac_sub_data(&isac_sub); });

// Retrieve information about the E2 Nodes in the callback func (cb)
for(size_t i = 0; i < arr.len; ++i){
hndl[i] = report_sm_xapp_api(&arr.n[i].id, SM_ISAC_ID, &isac_sub, cb);
assert(hndl[i].success == true);
}

poll(NULL, 0, 2000);

for(size_t i = 0; i < arr.len; ++i){
rm_report_sm_xapp_api(hndl[i].u.handle);
}

// stop the xApp
while(try_stop_xapp_api() == false)
poll(NULL, 0, 1000);

return 0;
}

The user can compile the this xApp doing in the terminal:

cd /path/to/xapp_sdk/build
cmake ..
make -j
sudo make install
sudo ldconfig

Then in order to run it:

cd build
./src/dev/c/xapp_isac_srs ../conf/xapp.yaml

If ran successfully the output should be as follows:

$ ./src/dev/c/xapp_isac_srs ../conf/xapp.yaml
09:03:32.754060 [INFO]: e42_xapp_api.c:83
##########################################################################################
##########################################################################################
##########################################################################################
Copyright (C) 2021-2025 BubbleRAN SAS
Project: MX-RIC
Full License: https://bubbleran.com/resources/files/BubbleRAN_Licence-Agreement-1.3.pdf
##########################################################################################
##########################################################################################
##########################################################################################
09:03:32.754446 [INFO]: e42_xapp_api.c:87 Git SHA1 5f638f14d1b2f0bac3e291c635b72f70b12175a1
09:03:32.754450 [INFO]: xapp_conf.c:165 Configuration file path ../conf/xapp.yaml
09:03:32.755148 [INFO]: xapp_conf.c:170 ---------------------------------------------------
09:03:32.755151 [INFO]: xapp_conf.c:171 Configuration file encoded in base64. To decode use $base64 --decode tmp.txt
09:03:32.755151 [INFO]: xapp_conf.c:172 ---------------------------------------------------
09:03:32.755152 [INFO]: xapp_conf.c:173
eGFwcDoKICAgIGlwX3JpYzogMTAuMjQ0LjAuMTc0CiAgICBlNDJfcG9ydDogMzY0MjIKICAgICMgSVAgdG8gYmluZCBTQ1RQIGNsaWVudAogICAgIyBOZWVkcyB0byBiZSBpbiB0aGUgcmFuZ2Ugb2YKICAgICMgaXBfcmljLiBJdCBpcyB0aGUgaW50ZXJmYWNlCiAgICAjIGZyb20gaWZjb25maWcgY21kCiAgICBpcF94YXBwOiAxMC4yNDQuMC4xMgogICAgc21fZGlyOiAvdXNyL2xvY2FsL2xpYi9mbGV4cmljLwogICAgbG9nOiAyCiAgICAgICAgIyB0cmFjZTogMAogICAgICAgICMgZGVidWc6IDEKICAgICAgICAjIGluZm86IDIKICAgICAgICAjIHdhcm46IDMKICAgICAgICAjIGVycm9yOiA0CiAgICAgICAgIyBmYXRhbDogNQogICAgICAgICMgZS5nLiwgbGV2ZWwgPSAyIC0+IGxldmVsID0gaW5mbwogICAgIyBDb21tZW50IHRoZSBkYXRhYmFzZSBzZWN0aW9uCiAgICAjIGlmIG5vIGRhdGFiYXNlIGlzIG5lZWRlZC91c2VkCiAgICBkYjoKICAgICAgICBpcDogMTAuMjQ0LjAuMjM2CiAgICAgICAgZGlyOiAvdG1wLwogICAgICAgIGZpbGVuYW1lOiB0ZXN0ZGIKICAgICAgICB1c3I6IHhhcHAKICAgICAgICBwc3c6IEJ1YmJsZVJBTgogICAgICAgICMgQ29tbWFuZHMgZm9yIHNldHRpbmcgdXAgbXlzcWwKICAgICAgICAjICQgc3VkbyBteXNxbAogICAgICAgICMgJCBteXNxbD4gQ1JFQVRFIFVTRVIgJ3VzZXJuYW1lJ0AnbG9jYWxob3N0JyBJREVOVElGSUVEIEJZICdwYXNzd29yZCc7CiAgICAgICAgIyAkIG15c3FsPiBncmFudCBhbGwgcHJpdmlsZWdlcyBvbiAqLiogdG8gJ3VzZXJuYW1lJ0AnbG9jYWxob3N0JzsKICAgICAgICAjICQgbXlzcWw+IGV4aXQKCg==
09:03:32.755156 [INFO]: xapp_conf.c:174 ---------------------------------------------------
09:03:32.755157 [INFO]: xapp_conf.c:175 ---------------------------------------------------
09:03:32.755158 [INFO]: xapp_conf.c:176 ---------------------------------------------------
09:03:32.755513 [INFO]: e42_xapp.c:191 NearRT-RIC Server IP Address = 10.244.0.174, PORT = 36422
09:03:32.755516 [INFO]: e42_xapp.c:192 xApp IP Address = 10.244.0.12
09:03:32.755533 [INFO]: endpoint_xapp.c:74 [xApp]: SCTP client bind to IP 10.244.0.12, Port 49406
09:03:32.755844 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
09:03:32.755854 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
09:03:32.756916 [INFO]: msg_handler_xapp.c:552 E42 SETUP-REQUEST tx
09:03:32.757513 [INFO]: msg_handler_xapp.c:393 E42 SETUP-RESPONSE rx xApp ID 7
09:03:32.757533 [INFO]: msg_handler_xapp.c:409 Connected E2 Node(s) 1
09:03:33.758641 [INFO]: msg_handler_xapp.c:587 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 147 RIC_REQ_ID 1
09:03:33.767637 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 147 RIC_REQ_ID 1
Timestamp 1754643813802881 latency -152
len_srs_iq 3264
Timestamp 1754643813802908 latency -17
len_srs_iq 3264
Timestamp 1754643813802939 latency 115
len_srs_iq 3264
Timestamp 1754643813802958 latency 254
len_srs_iq 3264
Timestamp 1754643813802977 latency 386
len_srs_iq 3264
Timestamp 1754643813802995 latency 646
len_srs_iq 3264
Timestamp 1754643813803014 latency 774
len_srs_iq 3264
Timestamp 1754643813803036 latency 939
len_srs_iq 3264
...
09:03:35.769672 [INFO]: msg_handler_xapp.c:600 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 147 RIC_REQ_ID 1
09:03:35.769994 [INFO]: msg_handler_xapp.c:196 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 147 rx RIC_REQ_ID 1