Skip to main content

Types of xApps

There are two kinds of xApps that BubbleRAN offers:

  • Cluster xApps
  • Bare metal xApps

Cluster xApps​

BubbleRAN offers ready to deploy containerized xApps facilitating their integration within the product. Cluster xApps are ideal when the use case matches the ones already developed by BubbleRAN. It's ease of deployment is an asset for such use cases.

ToDO (Khai): List of xApps

Bare Metal xApps​

However, sometimes the proposed use case needs to be extended and/or modified, and therefore, some flexibility is required. For those use cases, BubbleRAN offers bare metal xApp deployments. Due to the ambition to cover as many use cases as possible, the O-RAN standard easily becomes cumbersome and tedious for developers, representing an unnecessary burden and time consuming task on the xApp developer's shoulders. Thus, two modes for developing are proposed by BubbleRAN: usr and dev. Following the xApp list provided by BubbleRAN in the usr and dev SDKs.

List of xApps

usr SDK​

c xApps​

  • xapp_sdk_moni.c
  • xapp_sdk_moni_cb.c
  • xapp_sdk_moni_ue.cu
  • xapp_sdk_moni_ue_cb.c
  • xapp_slice_sdk.c
  • xapp_ho_sdk.c
  • xapp_bwp_sdk.c

python xApps​

  • mntr_cb.py
  • mntr.py
  • mntr_ue_cb.py
  • mntr_ue.py
  • slicing.py
  • ho.py
  • bwp.py

dev SDK​

  • xapp_all_moni.c
  • xapp_cust_moni.c
  • xapp_oran_moni.c
  • xapp_cust_slice_moni_ctrl.c
  • xapp_oran_rc_slice_ctrl.c
  • xapp_oran_rc_handover_ctrl.c
  • get_mcs.c
  • mcs.c
  • isac_srs.c
  • xapp_oran_ccc_bwp_ctrl.c

usr​

This should be the default starting point for any developer. The interface has been simplified, enhancing xApp developers productivity.
A simple program to fetch one variable value from a gNB looks like the following:

  • Example:
    import sys
    import xapp_usr_sdk as xapp

    xapp.init(sys.argv)
    nodes = xapp.e2_nodes(xapp.MONITOR_USE_CASE_e)

    v = xapp.mntr(nodes[0].node, xapp.PDCP_SDU_VOLUME_DL)
    print("Value " + str(v))

And can be invoked typing

python3 mntr.py xapp.yaml

The last messages that appear in the terminal should like something similar to the following:

10:00:24.536471 [INFO]:  e42_xapp.c:191 NearRT-RIC Server IP Address = 127.0.0.1, PORT = 36422
10:00:24.536496 [INFO]: e42_xapp.c:192 xApp IP Address = 127.0.0.1
10:00:24.536706 [INFO]: endpoint_xapp.c:74 [xApp]: SCTP client bind to IP 127.0.0.1, Port 37369
10:00:24.536779 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
10:00:24.536826 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
10:00:24.537602 [INFO]: msg_handler_xapp.c:533 E42 SETUP-REQUEST tx
10:00:24.538184 [INFO]: msg_handler_xapp.c:374 E42 SETUP-RESPONSE rx xApp ID 7
10:00:24.538224 [INFO]: msg_handler_xapp.c:390 Connected E2 Node(s) 1
10:00:24.538479 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
10:00:24.539334 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 1
10:00:24.541063 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 1
10:00:24.541616 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 1
10:00:24.542089 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
10:00:24.542678 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 2 RIC_REQ_ID 2
10:00:24.543955 [INFO]: msg_handler_xapp.c:581 RIC_SUBSCRIPTION_DELETE_REQUEST tx RAN_FUNC_ID 2 RIC_REQ_ID 2
10:00:24.544594 [INFO]: msg_handler_xapp.c:195 RIC_SUBSCRIPTION_DELETE_RESPONSE RAN_FUNC_ID 2 rx RIC_REQ_ID 2
Value 536.0

The first 3 messages indicate information regarding the localization of the NearRT-RIC and the IP address of the xApp. The E42 setup request and setup response can be seen, where the xApp ID 7 is being assigned to the current xApp. Later, the number of connected E2 nodes is printed, followed by a susbcription request to gather the information regarding the E2 Node, and its subscription delete. Afterward, the subscription request to fetch the value is sent, and after the value arrives at the xApp, the subscription is deleted.

As seen, the logic is quite complex. Fortunately, the usr interface provides the developer with the right abstraction so that it can focus on its use case rather than how these messages flow under the hood.

Due to its simplicity it is the recommended starting point.

For a complete usr signature please check the xApp usr API section.

dev

This is a more advanced mode, where the developer needs to have a basic understanding of how O-RAN is defined. However, it also provides more flexibility, and while the interfaces to the SDK are simple, the user needs to fulfill the Service Model Message itself, generating a considerable burden for the developer and typically generating xApps with orders of magnitudes more lines of code than usr. As an example, we propose a simple xapp that subscribes to the MAC custom service model.

#include "../../../../src/xApp/e42_xapp_api.h"
#include "../../../../src/util/alg_ds/alg/defer.h"
#include "../../../../src/util/time_now_us.h"

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

static
void sm_cb_mac(sm_ag_if_rd_t const* rd)
{
assert(rd != NULL);
assert(rd->type ==INDICATION_MSG_AGENT_IF_ANS_V0);
assert(rd->ind.type == MAC_STATS_V0);

int64_t now = time_now_us();
printf("MAC ind_msg latency = %ld Ξs\n", now - rd->ind.mac.msg.tstamp);
}

int main(int argc, char *argv[])
{
//Init the xApp
init_xapp_api(argv[1]);
sleep(1);

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

// MAC indication
const char* i_0 = "1_ms";
sm_ans_xapp_t* mac_handle = NULL;

if(nodes.len > 0){
mac_handle = calloc( nodes.len, sizeof(sm_ans_xapp_t) );
assert(mac_handle != NULL);
}
for (int i = 0; i < nodes.len; i++) {
e2_node_connected_xapp_t* n = &nodes.n[i];

mac_handle[i] = report_sm_xapp_api(&nodes.n[i].id, 142, (void*)i_0, sm_cb_mac);
assert(mac_handle[i].success == true);
}

sleep(10);

for(int i = 0; i < nodes.len; ++i){
// Remove the handle previously returned
if(mac_handle[i].u.handle != 0 )
rm_report_sm_xapp_api(mac_handle[i].u.handle);
}

if(nodes.len > 0){
free(mac_handle);
}

//Stop the xApp
while(try_stop_xapp_api() == false)
usleep(1000);

printf("Test xApp run SUCCESSFULLY\n");
}

As shown, the dev SDK is more tedious and difficult to manage, while it gives more control to the developer.

Note:​

BubbleRAN xApps support extremely low-latency use cases, as indication messages arrive at a latency lower than one millisecond. It effectively supports all the real time use cases that are emerging (e.g., ISAC https://www.youtube.com/watch?v=m_adp09yvIc) while being 100% O-RAN E2AP protocol compliant.

Note II:​

usr SDK is built upon dev SDK, and thus, it is a superset.