# Cloud-Enabled Deployment of 5G Core Network with Analytics Features
## 4 The Testbed
### Slicing Configuration
{'S_NSSAI[SST:1 SD:000001]': {

'ALL_SUPPORTING_IMSIS': [

'66601000000001',

'666011',

'666012',

'PER_DNN_AGGREGATED_BITRATE': {

'ims': {

'TOTAL_AMBR_DL': '260096 Kbps',

'TOTAL_AMBR_UL': '260096 Kbps'},

'internet': {

'TOTAL_AMBR_DL': '1506304 Kbps',

'TOTAL_AMBR_UL': '1506304 Kbps'},

'PER_DNN_COMMON_SUPPORTED_SSC': {

'ims': {'SSC_MODE_3',

'SSC_MODE_1',

'internet': ['SSC_MODE_3',

'SSC_MODE_1',

'SER_MODE_2']},

'PER_DNN_DEFAULT_REQUIRED_SSC': {

'ims': {'SSC_MODE_1'},

'internet': {'SSC_MODE_1'},

'TOTAL_AMBR_DL': '1766400 Kbps',

'TOTAL_IMSIS': 4}}

### Implementation Details of the Proposed Extension

The main class that acts as an intermediary between UDR and the rest of quasi-NEF components is _PycurlClient_. It is a Singleton implementation of an overloaded _Curl_ class provided by the _pycurl_ module. Although the class may seem as a simple replacement of curl CLI utility, it provides additional features useful in our implementation: buffering the HTTP responses, altering the pycurl-defined parameters, custom exception handling. Listings 8 and 9 highlight the core part of PycurlClient, which interacts with UDR and extracts data. The overridden _perform_ method allows for on-demand buffer initialization, as _pycurl_ does not have a built-in data storing mechanism. While CLI curl by default delivers the query result to the standard output, _pycurl_ requires defining a buffer to store the returned data. It has been implemented by assigning a BytesIO object to which _pycurl_ writes the results of the query. The _setup_ method ensures that any entered configuration parameters (usually the URL) are of the correct type. It also stores the accepted parameters to facilitate access to the _pycurl_ configuration (e.g., for retrieving the type of NFs or the SBI resource). ```
@override defperform(self): \"\"\"Methodtoexecutehttp/2 querytowardsNFSBIservers\"\"\" self._buffer=BytesIO() assert'URL'inself._curl_options,f'urlunset' self.setopt(pycurl.WRITEDATA,self._buffer) try: super().perform() exceptpycurl.erroraserr: _message=f'Unabletoperformhttp/2 requestto{self._curl_options. get(\"URL\")}\
+Error:{err}' raiseInvalidQueryException( message=_message, errors=err)
```
**Listing 9** An overridden pycurl's _setup_ method featuring option logging. ```
@override defsetopt(self,option,value): \"\"\"SetsanoptionofCurlclient\"\"\" assertoptioninself._libcurl_acceptable,f'invalidoptiontosetup: {option}' try: super().setopt(option,value) self._curl_options.update({self._libcurl_acceptable.get(option):value}) exceptTypeErroraserr: print(f'invalidvalue:{value}tooption:{option};{err}') exceptpycurl.erroraserr: print(f'libcurlrejectedoption||value:{err}')
```
Listing 8: A PycurlClient _perform_ method to perform HTTP/2 request with custom Exception handling. ```
@override defperform(self): \"\"\"Methodtoexecutehttp/2 querytowardsNFSBIservers\"\"\" self._buffer=BytesIO() assert'URL'inself._curl_options,f'urlunset' self.setopt(pycurl.WRITEDATA,self._buffer) try: super().perform() exceptpycurl.erroraserr: _message=f'Unabletoperformhttp/2 requestto{self._curl_options. get(\"URL\")}\
+Error:{err}' raiseInvalidQueryException( message=_message, errors=err)
```
**Listing 10** An overridden pycurl's _setup_ method featuring option logging. BaseClass uses both _perform_ and _setup_ in its class _send_query_ method. The BaseClass _send_query_ method (see Listing 10) enables dynamic generation of HTTP/2 requests via a common handle (PycurlClient Singleton) and decoding the response into a JSON format. The method is inherited by remaining NFs specific agents: AmfClient, UdrClient and NrfClient. The BaseClass _send_query_ method provides an acceptable data format for undergoing a feature extraction process. The JSON-encapsulated data are aggregated with the help of _map/filter/reduce_ Python functions and presented in both human and further-processing friendly format.