210 lines
8.9 KiB
ReStructuredText
210 lines
8.9 KiB
ReStructuredText
|
.. This work is licensed under a Creative Commons Attribution 4.0 International License.
|
||
|
.. SPDX-License-Identifier: CC-BY-4.0
|
||
|
.. Copyright (C) 2020 AT&T
|
||
|
|
||
|
============================================================================================
|
||
|
HelloWorld xAPP (C++)
|
||
|
============================================================================================
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
User's Guide
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
|
||
|
Introduction
|
||
|
============================================================================================
|
||
|
|
||
|
The RIC platform provides set of functions that the xAPPs can use to accomplish their tasks.
|
||
|
The HW xAPP is envisioned to provide xAPP developers, examples of implementing these sets of functions.
|
||
|
Note, HW xAPP does not address/implement any RIC Usecases.
|
||
|
|
||
|
HelloWorld xAPP Features
|
||
|
============================================================================================
|
||
|
|
||
|
RIC Platform provides many APIs and libraries to aid the development of xAPPs. All xAPPs will have some custom
|
||
|
processing functional logic core to the xApp and some additional non-functional platform related processing using
|
||
|
these APIs and libraries. HW xAPP attempts to show the usage of such additional platform processing using RIC platform APIs and libraries.
|
||
|
|
||
|
|
||
|
The Hello World xApp demonstrates how an xApp uses the A1, and E2 interfaces and persistent database read-write operations.
|
||
|
The following paragraphs cover the various steps involved to create an HelloWorld xApp instance, setting its configuration,
|
||
|
retrieving R-NIB data, sending subscription, connecting SDL, RME & A1 Healthcheck and usage of "Hello World SM"
|
||
|
|
||
|
HelloWorld Creation
|
||
|
============================================================================================
|
||
|
|
||
|
The creation of the xApp instance is as simple as invoking
|
||
|
the object's constructor with two required parameters:
|
||
|
|
||
|
|
||
|
HW xAPP, may choose to create following objects for obtaining desired set of functionalities provided under xapp-utils:
|
||
|
|
||
|
XappRmr
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
An xAPP can have the capability of receiving and sending rmr messages. This is achieved by creating an XappRmr object. The constructor of xAPPRMR object requires xAPP developer to provide
|
||
|
xAPP's listening port and developer configurable number of attempts need to be made to send the message. The key functionalities of the class being :
|
||
|
|
||
|
1. Setting RMR initial context: ...xapp_rmr_init(...)
|
||
|
|
||
|
2. Sending RMR message: ...xapp_rmr_send(xapp_rmr_header, void*)
|
||
|
|
||
|
3. Receiving RMR message: ...xapp_rmr_receive(msghandler,...)
|
||
|
|
||
|
The RMR Header can be defined using xapp_rmr_header :
|
||
|
::
|
||
|
|
||
|
typedef struct{
|
||
|
struct timespec ts;
|
||
|
int32_t message_type; //mandatory
|
||
|
int32_t state;
|
||
|
int32_t payload_length; //mandatory
|
||
|
unsigned char sid[RMR_MAX_SID];
|
||
|
unsigned char src[RMR_MAX_SRC];
|
||
|
unsigned char meid[RMR_MAX_MEID];
|
||
|
|
||
|
} xapp_rmr_header;
|
||
|
|
||
|
Except for message type and payload length, its developers prerogative to use remaining header information.
|
||
|
The XappMsgHandler (msghandler) instance in xapp_rmr_receive function handles received messages. The handling of messages is based on
|
||
|
the usecase catered by a xAPP. Hence, XappMsgHandler class used in HW xAPP is not very comprehensive and addresses only Healthcheck Messages.
|
||
|
|
||
|
XappSettings
|
||
|
-------------------------------------------------------------------------------------------
|
||
|
An xAPP has the capability to use environment variables or xapp-descriptor information as its configuration settings
|
||
|
creating XappSettings object, whose key functions being :
|
||
|
|
||
|
1. Loading Default Settings: ...loadDefaultSettings()
|
||
|
|
||
|
2. Loading Environment Variables: ...loadEnvVarSettings()
|
||
|
|
||
|
3. Loading Command Line Settings: ...loadCmdlineSettings(argc, argv)
|
||
|
|
||
|
XappSDL
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
An xAPP can have the capability to read and write into a persistent storage (key-value store) creating XappSDL object.
|
||
|
for a namespace. The key functionalities available currently are:
|
||
|
|
||
|
|
||
|
1. Getting Data from SDL: ... get_data(...);
|
||
|
|
||
|
2. Setting Data to SDL: ... set_data(...);
|
||
|
|
||
|
The HW xAPP can be instantiationed as following:
|
||
|
::
|
||
|
|
||
|
HW_Xapp = Xapp(XappRmr object, XappSettings object,...);
|
||
|
|
||
|
|
||
|
HelloWorld E2 and A1 Message Handling
|
||
|
============================================================================================
|
||
|
Helper Objects
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
HW xAPP creates wrapper datastructures mirroring ASN and JSON messages. These datastructures facilitate processing of
|
||
|
E2 and A1 messages in the xAPP. A sample helper object for A1 Health Check message being:
|
||
|
::
|
||
|
|
||
|
struct a1_policy_helper{
|
||
|
std::string operation;
|
||
|
std::string policy_type_id;
|
||
|
std::string policy_instance_id;
|
||
|
std::string handler_id;
|
||
|
std::string status;
|
||
|
};
|
||
|
|
||
|
And a sample E2AP Control datastructure:
|
||
|
::
|
||
|
|
||
|
struct ric_control_helper{
|
||
|
ric_control_helper(void):req_id(1), req_seq_no(1), func_id(0), action_id(1), control_ack(-1), cause(0), sub_cause(0), control_status(1), control_msg(0), control_msg_size(0), control_header(0), control_header_size(0), call_process_id(0), call_process_id_size(0){};
|
||
|
long int req_id, req_seq_no, func_id, action_id, control_ack, cause, sub_cause, control_status;
|
||
|
|
||
|
unsigned char* control_msg;
|
||
|
size_t control_msg_size;
|
||
|
|
||
|
unsigned char* control_header;
|
||
|
size_t control_header_size;
|
||
|
|
||
|
unsigned char *call_process_id;
|
||
|
size_t call_process_id_size;
|
||
|
|
||
|
};
|
||
|
|
||
|
As mentioned, these datastructures are very much tied to the message specifications.
|
||
|
|
||
|
|
||
|
|
||
|
ASN Encoding/Decoding
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
RIC platform provided ASN1C (modified) library is used for processing ASN1 messages. HW xAPP, for each
|
||
|
ASN message type, uses a class which is responsible for handling a particular message type.
|
||
|
The class encapsulates, the APIs and datastructures used in ASN1C using helper objects. For example:
|
||
|
::
|
||
|
|
||
|
class ric_control_response{
|
||
|
...
|
||
|
bool encode_e2ap_control_response(..., ric_control_helper &);
|
||
|
bool set_fields(..., ric_control_helper &);
|
||
|
bool get_fields(..., ric_control_helper &);
|
||
|
...
|
||
|
}
|
||
|
|
||
|
Note, the helper objects and message type processing classes can be found under xapp-asn subdirectories.
|
||
|
|
||
|
E2AP Subscription
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
In HW xAPP, we consider sunny-side scenario, in which for a E2AP subscription request sent, it is assumed,
|
||
|
that HW xAPP will be receiving E2AP subscription response. Handling advanced subscription (class SubscriptionHandler) flows is out of the
|
||
|
scope of HW xAPP. Current form of class SubscriptionHandler has following key functionalities:
|
||
|
|
||
|
1. manage_subscription_request(...)
|
||
|
|
||
|
2. manage_subscription_response(...)
|
||
|
|
||
|
|
||
|
The manage_subscription_request function waits for the response for a specified time for subscription response
|
||
|
and if no response is received within a specified time, gives a time out error message. A subscription message
|
||
|
is created using ASN Encodong/Decoding and Helper classes. (Refer test_sub.h). HW xAPP sends the subscriptions based
|
||
|
on the gNodeB IDs received from RNIB. Please refer following function in xapp.* for RNIB transactions: set_rnib_gnblist(...)
|
||
|
|
||
|
|
||
|
E2SM Subscription, Indication, Control
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
HellowWorld E2SM (e2sm-HelloWorld-v001.asn) is an example E2SM available in the docs directory. The Helper and
|
||
|
encoding/decoding classes are in xapp-asn/e2sm. Sample code for control message E2SM:
|
||
|
::
|
||
|
|
||
|
//ControlHeader
|
||
|
unsigned char header_buf[128];
|
||
|
size_t header_buf_len = 128;
|
||
|
|
||
|
//ControlMessage
|
||
|
unsigned char msg_buf[128];
|
||
|
size_t msg_buf_len = 128;
|
||
|
|
||
|
bool res;
|
||
|
|
||
|
e2sm_control_helper e2sm_cntrldata; //helper object
|
||
|
e2sm_control e2sm_cntrl; //encoding/decoding object
|
||
|
|
||
|
unsigned char msg[20] = "HelloWorld";
|
||
|
|
||
|
e2sm_cntrldata.header = 1001;
|
||
|
e2sm_cntrldata.message = msg;
|
||
|
e2sm_cntrldata.message_len = strlen((const char*)e2sm_cntrldata.message);
|
||
|
|
||
|
|
||
|
// Encode the control header
|
||
|
res = e2sm_cntrl.encode_control_header(&header_buf[0], &header_buf_len, e2sm_cntrldata);
|
||
|
if(!res)
|
||
|
std::cout << e2sm_cntrl.get_error() << std::endl;
|
||
|
|
||
|
// Encode the control message
|
||
|
res = e2sm_cntrl.encode_control_message(&msg_buf[0], &msg_buf_len, e2sm_cntrldata);
|
||
|
if(!res)
|
||
|
std::cout << e2sm_cntrl.get_error() << std::endl;
|
||
|
|
||
|
|
||
|
RMR and A1 Healtcheck
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
On receiving health check request message types (A1_HEALTHCHECK_REQ, RMR_HEALTHCHECK_REQ), HW xAPP sends RMR
|
||
|
response (A1_HEALTHCHECK_RES, RMR_HEALTHCHECK_RESP) adding appropriate responses using RMR Return to Sender
|
||
|
functionality.
|