C SDK Signatures
xApp configuration
Support .conf
file for xApp configuration with the following information.
General configuration
- Mandatory setting of xApp
# Set your SM directory path
SM_DIR = "/usr/local/lib/flexric/"
Name = "xApp"
NearRT_RIC_IP = "127.0.0.1"
E42_Port = 36422
- Setting of database
xApp_DB = {
enable = "OFF"
}
Note: assume we disable writing to database by default
Customized SMs' configuration
- Supported options:
name
:MAC, RLC, PDCP, GTP, SLICE
time
:1_ms, 2_ms, 5_ms, 10_ms, 100_ms, 1000_ms
- Example:
Sub_CUST_SM_List = (
{ name = "MAC", time = "10_ms" },
{ name = "RLC", time = "100_ms" },
{ name = "PDCP", time = "1000_ms" }
)
O-RAN SMs' configuration
- Supported options:
name
:KPM, RC
time
(ms):1, 2, 5, 10, 100, 1000
- Note: no need timer for RC Report Service , set as
0
- Note: no need timer for RC Report Service , set as
format
for action definition:name = "KPM"
:1, 4
name = "RC"
:1
ran_type
:ngran_gNB, ngran_gNB_CU, ngran_gNB_DU
- Example:
# FOR EXAMPLE
Sub_ORAN_SM_List = (
{ name = "RC", time = 0,
format = 1,
ran_type = "ngran_gNB",
actions = ( # 8.2.2 RAN Parameters for Report Service Style 2
{ id = 1 }, # Current UE ID
{ id = 6 }, # Cell Global ID
{ id = 21528 } # List of Neighbor cells
)
},
{ name = "KPM", time = 1000,
format = 4,
ran_type = "ngran_gNB_CU",
actions = (
{ name = "DRB.PdcpSduVolumeDL" }
)
}
)
Overview
Introducing C SDK signature functions that oversee the entire lifecycle of an xApp. The table below provides a brief description with the following item:
Signature | Description |
---|---|
init_fr_args() | Initialize the xApp configuration |
init_xapp_api() | Initializes the xApp and sends an E42-Setup-Request to NearRT-RIC based on the given configurations |
e2_nodes_xapp_api() | Get connected E2-Nodes' information (e.g., NodeB ID, RAN type and supported RAN functions, etc) |
report_sm_xapp_api() | Sends a RIC-Subscription-Request to subscribe the RAN function on the specific E2-Node via the service model |
sm_cb_{SM-NAME}() | A callback function of service model(s) for handling indication messages received by the xApp |
control_sm_xapp_api() | Sends a RIC-Conctrol-Request to the RAN function at the specific E2-Node via the service model |
rm_report_sm_xapp_api() | Sends a RIC-Delete-Subscription-Request to unsubscribes the subscribed RAN functions |
try_stop_xapp_api() | Terminate the xApp |
Note:
{SM-NAME}
serves as a placeholder for the name of a specific service model, for example: if{SM-NAME} = kpm
which stands for Key Performance Measurement service model, the function names will besm_cb_kpm()
. The supported{SM-NAME}
s in C SDK include:
- Customized service models: mac, rlc, pdcp, gtp, slice
- O-RAN standardized service models: kpm, rc
Sequence Diagram
The following figures illustrates the sequence diagram of lifecycle in a Python xApp, including:
- Init: initialize xApp (from step 2 to 6)
- Report Service: subscribe RAN function via service model (from step 7 to 13)
- xApp Logic: store or process receiving data from RAN functions (from step 14 to 15)
- Control Service: control RAN function via service model (from step 16 to 20)
- Exit: terminate xApp (from step 21 to 26)
Detail of Signatures
Init - Step 2 to 6
- Used functions
init_fr_args()
-
Example:
// Read xApp configuration file
fr_args_t args = init_fr_args(argc, argv);
defer({ free_fr_args(&args); }); -
Input:
Parameter Type in C Comment argc
int
The count of command-line arguments argv
char* argv[]
An array of strings holding the command-line arguments -
Output:
Parameter Type in C Comment args
fr_args_t
Argument custom structure containing configuration properties
init_xapp_api()
-
Example:
// Initialize xApp using the settings from configuration file
init_xapp_api(&args); -
Input:
Parameter Type in C Comment &args
fr_args_t const*
A consta struct containing parameters sourced from xapp.conf -
Output: N/A
e2_nodes_xapp_api()
-
Example:
// Get connected E2-Nodes
e2_node_arr_t nodes = e2_nodes_xapp_api();
defer({ free_e2_node_arr(&nodes); });
// Case 1: if no E-Node connected, do no excuting xApp anymore
assert(nodes.len > 0);
# Case 2: if the number of connected E2-Nodes is greater than 0
printf("Connected E2 nodes = %d\n", nodes.len); -
Input: N/A
-
Output:
Parameter Type in C Comment nodes
e2_node_arr_t
A struct contains a array of E2-Nodes' information
Report service - Step 7 to 13
- Used functions
report_sm_xapp_api()
-
Example - Customized SMs
// Define a handler as pointer to store the RIC Request ID
sm_ans_xapp_t* cust_sm_handle = NULL;
// Note: we assume the number of handler will be the same as the number of connected E2-Node,
// therefore, we allocate the memory to the handler based on nodes.len
cust_sm_handle = calloc(nodes.len, sizeof(sm_ans_xapp_t) );
assert(cust_sm_handle != NULL);
// Subscribe to all the connected E2-Nodes
for (int i = 0; i < nodes.len; i++) {
// Get the current E2-Node
e2_node_connected_t* n = &nodes.n[i];
// Get the supported RAN function's ID from the current E2-Node
for (size_t j = 0; j < n->len_rf; j++) {
printf("Registered node %d ran func id = %d \n ", i, n->ack_rf[j].id);
// Get the current RAN functions's ID
uint32_t rf_id = n->ack_rf[j].id;
// Send subscription request to n by giving:
// global E2-Node ID, service model's ID, transmission time intervale of indicaiton message, and defined callback function
cust_sm_handle[i] = report_sm_xapp_api(n->id, sm_id, (void*)args.sub_cust_sm[j].time, sm_cb_{SM-NAME});
assert(cust_sm_handle[i].success == true);
}
} -
Input:
Parameter Type in C Comment n->id
global_e2_node_id_t*
Stands for Global E2-Node ID rf_id
uint32_t
RAN function's ID (void*)args.sub_cust_sm[j].time
void*
Time duration of each RIC Indication read from xapp.conf sm_cb_{SM-NAME}
sm_cb
Defined callback function in xApp, e.g., sm_cb_mac -
Output:
Parameter Type in C Comment cust_sm_handle[i]
int
RIC Request ID -
Example - O-RAN Standarized SM
// Define a handler as pointer to store the RIC Request ID
sm_ans_xapp_t* oran_sm_handle = NULL;
// Note: we assume the number of handler will be the same as the number of connected E2-Node,
// therefore, we allocate the memory to the handler based on nodes.len
oran_sm_handle = calloc(nodes.len, sizeof(sm_ans_xapp_t) );
assert(oran_sm_handle != NULL);
// Subscribe to all the connected E2-Nodes
for (int i = 0; i < nodes.len; i++) {
// Get the current E2-Node
e2_node_connected_t* n = &nodes.n[i];
// Get the supported RAN function's ID from the current E2-Node
for (size_t j = 0; j < n->len_rf; j++) {
printf("Registered node %d ran func id = %d \n ", i, n->ack_rf[j].id);
// Get the current RAN functions's ID
uint32_t rf_id = n->ack_rf[j].id;
// Generate subscription data based on the union type in sm_ag_if_wr_subs_t
// Note: generate event trigger definition and action definition for KPM SM
kpm_sub_data_t kpm_sub = {0}
kpm_sub.ev_trg_def = gen_kpm_ev_trig()
kpm_sub.sz_ad = 1;
kpm_sub.ad = calloc(1, sizeof(kpm_act_def_t));
kpm_sub.ad = gen_kpm_act()
// Send subscription request to n by giving:
// global E2-Node ID, service model's ID, subscription data, and defined callback function
oran_sm_handle[i] = report_sm_xapp_api(n->id, sm_id, &kpm_sub, sm_cb_{SM-NAME});
assert(oran_sm_handle[i].success == true);
}
} -
Input:
Parameter Type in C Comment n->id
global_e2_node_id_t*
Stands for Global E2-Node ID rf_id
uint32_t
RAN function's ID &kpm_sub
void*
Subscription data including event trigger definition and action definition sm_cb_{SM-NAME}
sm_cb
Defined callback function in xApp, e.g., sm_cb_kpm -
Output:
Parameter Type in C Comment oran_sm_handle[i]
int
RIC Request ID
xApp Logic - Step 14 to 15
- Used functions
sm_cb_{SM-NAME}()
-
Example - Customized SM:
{SM-NAME} = gtp
// Define a callback function for GTP SM
static void sm_cb_gtp(sm_ag_if_rd_t const* rd, global_e2_node_id_t const* e2_node)
{
// Use assert function to check the coming indication message is not NULL and its type is correct
assert(rd != NULL);
assert(rd->type == INDICATION_MSG_AGENT_IF_ANS_V0);
assert(rd->ind.type == GTP_STATS_V0);
// Get tstamp value stored in gtp_ind_data_t to calculate the one way latency of indication message
int64_t now = time_now_us();
printf("GTP ind_msg latency = %ld from E2-node type %d ID %d\n",
now - rd->ind.gtp.msg.tstamp, e2_node->type, e2_node->nb_id.nb_id);
} -
Input:
Parameter Type in C Comment rd
sm_ag_if_rd_t const*
A constant pointer to an received indication message e2_node
global_e2_node_id_t const*
A constant pointer to the global E2-Node ID, indicating the source E2-Node -
Output: N/A
Note: Once the RIC Subscription Request is received by the E2-Node, the xApp will continue to receive RIC Indications forwarded from the C SDK. For further development (i.e., ML or AI usage), developers can process the received RIC Indications to analyze/optimize network performance.
Control Service - Step 16 to 20
- Used functions
control_sm_xapp_api()
- Example - Customized SM: slice
// Create slice control message by following the structure sm_ag_if_wr_t
sm_ag_if_wr_t ctrl_msg = fill_slice_sm_ctrl_req();
// Get the slice SM's ID
uint32_t rf_id = SM_SLICE_ID;
// Send control request to nodes.n[i] by giving:
// global E2-Node ID, SM's ID, and predefined contorl message
control_sm_xapp_api(&nodes.n[i].id, sm_id, &ctrl_msg_del);
// Deallocate the contorl message
free_slice_ctrl_msg(&ctrl_msg.ctrl.slice_req_ctrl.msg);
-
Input:
Parameter Type in C Comment &nodes.n[i].id
global_e2_node_id_t*
Stands for Global E2-Node ID rf_id
uint32_t
RAN function's ID &ctrl_msg
void*
Control message written by xApp -
Output: N/A
Exit - Step 21 to 26
- Used functions
rm_report_sm_xapp_api()
- Example
// Loop handler to send subcription delete request to each recorded RIC Request ID
// Note: we assume that we allocate the memory to sm_handle based on the length of connected E2-Node
for (int i = 0; i < nodes.len; ++i)
rm_report_sm_xapp_api(sm_handle[i].u.handle);
// Deallocate the handler
if (nodes.len > 0)
free(sm_handle);
-
Input:
Parameter Type in C Comment sm_handle[i].u.handle
int
RIC Request ID -
Output: N/A
try_stop_xapp_api()
- Example:
// Call the stop function every one second until it recevies a true value
bool ans = try_stop_xapp_api()
while(ans == false) {
usleep(1000);
ans = try_stop_xapp_api()
}
-
Input: N/A
-
Output: N/A
Parameter Type in C Comment ans
bool
The status of terminating an xApp: "TRUE" means the xApp has terminated completely, including freeing the memory; "FALSE" indicates the opposite.