Skip to main content

Lab 6: Advanced RAN Slicing

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 a KPM+RC xApp for RAN Slicing will be deployed on bare-metal connecting to the RIC.

open-ran.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
identity:
an-id: 50
radio:
device: rf-sim
cells:
- band: n78
arfcn: 641280
bandwidth: 40MHz
subcarrier-spacing: 30kHz
tdd-config:
period: 5ms
dl-slots: 7
dl-symbols: 6
ul-slots: 2
ul-symbols: 4
controller: flexric.bubbleran
core-networks:
- minimal.bubbleran
core:
- name: minimal
stack: 5g-sa
model: oai-cn/minimal
identity:
region: 0
cn-group: 4
cn-id: 5
dns:
ipv4:
default: 8.8.8.8
secondary: 8.8.4.4
edge:
- name: flexric
stack: 5g-sa
model: mosaic5g/flexric
---
apiVersion: athena.trirematics.io/v1
kind: Terminal
metadata:
name: ue1
namespace: trirematics
spec:
vendor: oai
stack: 5g-sa
model: terminal/nr-rfsim
preferred-access: oai-gnb.bubbleran
target-cores:
- minimal.bubbleran
identity:
imsi: "001010000000001"
pin: "1234"
opc: "0xc42449363bbad02b66d16bc975d77cc1"
key: "0xfec86ba6eb707ed08905757b1bb44b8f"
sqn: "0xff9bb4000001"
slice:
dnn: "internet"
network-mode: "IPv4"
service-type: eMBB
differentiator: 0x000000
radio:
bands:
- n78
readiness-check:
method: ping
target: google-ip
interface-name: oaitun_ue0

---
apiVersion: athena.trirematics.io/v1
kind: Terminal
metadata:
name: ue2
namespace: trirematics
spec:
vendor: oai
stack: 5g-sa
model: terminal/nr-rfsim
preferred-access: oai-gnb.bubbleran
target-cores:
- minimal.bubbleran
identity:
imsi: "001010000000002"
pin: "1234"
opc: "0xc42449363bbad02b66d16bc975d77cc1"
key: "0xfec86ba6eb707ed08905757b1bb44b8f"
sqn: "0xff9bb4000001"
slice:
dnn: "internet"
network-mode: "IPv4"
service-type: eMBB
differentiator: 0x000000
radio:
bands:
- n78
readiness-check:
method: ping
target: google-ip
interface-name: oaitun_ue0

Deployment​

Use the command brc install network open-ran.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.

After deploying the network you should update the xApp configuration file with the IP of the deployed Near RT-RIC and the local source IP in the cluster subnet.

To do so you may deploy the update_conf.sh script which automatically extract the IPs from the cluster and updated the specified configuration file:

cd /path/to/xapp-source/conf_files
./update_conf.sh default.conf

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). After selecting a RIC to connect an output as the follwing is obtained:

Select the RIC to configure (enter number):
1) flexric.flexric.bubbleran (10.244.0.251)
Choice [1-1]: 1
Selected RIC: flexric.flexric.bubbleran with IP 10.244.0.251
Local IP for xApp: 10.244.0.218
Config file 'default.conf' updated successfully.

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

KPM+RC RAN Slicing xApp​

lab6.c
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/

#include "../include/src/xApp/e42_xapp_api.h"
#include "../include/src/sm/agent_if/write/sm_ag_if_wr.h"
#include "../include/src/util/alg_ds/alg/defer.h"
#include "../include/src/sm/slice_sm/slice_sm_id.h"

#include <stdatomic.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <poll.h>

static uint8_t pr_slice_0_lst[9] = {90, 80, 70, 60, 50, 40, 30, 20, 10};
static bool exit_flag = false;
static void sigint_handler(int sig)
{
printf("signal %d received !\n", sig);
exit_flag = true;
}

_Atomic uint16_t assoc_rnti = 0;

static
void sm_cb_slice(sm_ag_if_rd_t const* rd, global_e2_node_id_t const* e2_node)
{
assert(rd != NULL);
assert(rd->type == INDICATION_MSG_AGENT_IF_ANS_V0);
assert(rd->ind.type == SLICE_STATS_V0);

int64_t now = time_now_us_xapp_api();
printf("SLICE ind_msg latency = %ld from E2-node type %d ID %d\n",
now - rd->ind.slice.msg.tstamp, e2_node->type, e2_node->nb_id.nb_id);
if (rd->ind.slice.msg.ue_slice_conf.len_ue_slice > 0)
assoc_rnti = rd->ind.slice.msg.ue_slice_conf.ues[0].rnti;
}

static
void fill_add_mod_slice(slice_conf_t* add)
{
assert(add != NULL);

uint32_t dl_len_slices = 2;
uint32_t dl_slice_id[] = {0, 1};
char* dl_slice_label[] = {"s1", "s2"};
slice_algorithm_e dl_type = SLICE_ALG_SM_V0_PR;
//slice_algorithm_e dl_type = SLICE_ALG_SM_V0_NONE;
assert(dl_type >= 0);

char dl_name[10];
size_t len_dl_name;
switch (dl_type){
case SLICE_ALG_SM_V0_PR:
strcpy(dl_name, "PR");
len_dl_name = strlen("PR");
break;
case SLICE_ALG_SM_V0_NONE:
default:
strcpy(dl_name, "NULL");
len_dl_name = strlen("NULL");
break;
}

/// SET DL PR SLICE PARAMETER///
uint32_t pr_max[] = {pr_slice_0_lst[0], 100 - pr_slice_0_lst[0]};
uint32_t pr_min[] = {pr_slice_0_lst[0], 100 - pr_slice_0_lst[0]};
uint32_t pr_ded[] = {pr_slice_0_lst[0], 100 - pr_slice_0_lst[0]};

/// DL SLICE CONTROL INFO ///
ul_dl_slice_conf_t* add_dl = &add->dl;
add_dl->len_sched_name = len_dl_name;
add_dl->sched_name = malloc(strlen(dl_name));
assert(add_dl->sched_name != NULL && "memory exhausted");
memcpy(add_dl->sched_name, dl_name, len_dl_name);


add_dl->len_slices = dl_len_slices;
if (add_dl->len_slices > 0) {
add_dl->slices = calloc(add_dl->len_slices, sizeof(fr_slice_t));
assert(add_dl->slices != NULL && "memory exhausted");
}

for (uint32_t i = 0; i < add_dl->len_slices; ++i) {
fr_slice_t* s = &add_dl->slices[i];
s->id = dl_slice_id[i];

const char* label = dl_slice_label[i];
s->len_label = strlen(label);
s->label = malloc(s->len_label);
assert(s->label != NULL && "Memory exhausted");
memcpy(s->label, label, s->len_label );

const char* sched_str = "PF";
s->len_sched = strlen(sched_str);
s->sched = malloc(s->len_sched);
assert(s->sched != NULL && "Memory exhausted");
memcpy(s->sched, sched_str, s->len_sched);

s->params.type = SLICE_ALG_SM_V0_PR;
s->params.u.pr.max_ratio = pr_max[i];
s->params.u.pr.min_ratio = pr_min[i];
s->params.u.pr.dedicated_ratio = pr_ded[i];
printf("ADD PR DL SLICE: id %u, max_ratio %d, min_ratio %d, dedicated_ratio %d\n", s->id, s->params.u.pr.max_ratio, s->params.u.pr.min_ratio, s->params.u.pr.dedicated_ratio);
}

uint32_t ul_len_slices = 0;
uint32_t ul_slice_id[] = {0, 2};
char* ul_slice_label[] = {"s1", "s2"};

slice_algorithm_e ul_type = SLICE_ALG_SM_V0_NONE;
assert(ul_type >= 0);
if (ul_type != 0)
ul_len_slices = 2;
else
printf("RESET UL SLICE, algo = NONE\n");

char ul_name[10];
size_t len_ul_name;
switch (ul_type){
case SLICE_ALG_SM_V0_NVS:
strcpy(ul_name, "NVS");
len_ul_name = strlen("NVS");
break;
case SLICE_ALG_SM_V0_NONE:
default:
strcpy(ul_name, "NULL");
len_ul_name = strlen("NULL");
break;
}

/// SET UL NVS SLICE PARAMETER///
nvs_slice_conf_e ul_nvs_conf[] = {SLICE_SM_NVS_V0_CAPACITY, SLICE_SM_NVS_V0_CAPACITY};
float ul_mbps_rsvd = 2;
float ul_mbps_ref = 10.0;
float ul_pct_rsvd = 0.5;
/// UL SLICE CONTROL INFO ///
ul_dl_slice_conf_t* add_ul = &add->ul;
add_ul->len_sched_name = len_ul_name;
add_ul->sched_name = malloc(len_ul_name);
assert(add_ul->sched_name != NULL && "memory exhausted");
memcpy(add_ul->sched_name, ul_name, len_ul_name);

add_ul->len_slices = ul_len_slices;
if (add_ul->len_slices > 0) {
add_ul->slices = calloc(add_ul->len_slices, sizeof(fr_slice_t));
assert(add_ul->slices != NULL && "memory exhausted");
}

for (uint32_t i = 0; i < add_ul->len_slices; ++i) {
fr_slice_t* s = &add_ul->slices[i];
s->id = ul_slice_id[i];

const char* label = ul_slice_label[i];
s->len_label = strlen(label);
s->label = malloc(s->len_label);
assert(s->label != NULL && "Memory exhausted");
memcpy(s->label, label, s->len_label );

const char* sched_str = "PF";
s->len_sched = strlen(sched_str);
s->sched = malloc(s->len_sched);
assert(s->sched != NULL && "Memory exhausted");
memcpy(s->sched, sched_str, s->len_sched);

if (ul_type == SLICE_ALG_SM_V0_NVS) {
s->params.type = SLICE_ALG_SM_V0_NVS;
if (ul_nvs_conf[i] == SLICE_SM_NVS_V0_RATE) {
s->params.u.nvs.conf = SLICE_SM_NVS_V0_RATE;
s->params.u.nvs.u.rate.u1.mbps_required = ul_mbps_rsvd;
s->params.u.nvs.u.rate.u2.mbps_reference = ul_mbps_ref;
printf("ADD NVS UL SLICE: id %u, conf %d(rate), mbps_required %f, mbps_reference %f\n", s->id, s->params.u.nvs.conf, s->params.u.nvs.u.rate.u1.mbps_required, s->params.u.nvs.u.rate.u2.mbps_reference);
} else if (ul_nvs_conf[i] == SLICE_SM_NVS_V0_CAPACITY) {
s->params.u.nvs.conf = SLICE_SM_NVS_V0_CAPACITY;
s->params.u.nvs.u.capacity.u.pct_reserved = ul_pct_rsvd;
printf("ADD NVS UL SLICE: id %u, conf %d(capacity), pct_reserved %f\n", s->id, s->params.u.nvs.conf, s->params.u.nvs.u.capacity.u.pct_reserved);
} else {
assert(0 != 0 && "Unkown NVS conf type\n");
}
} else {
assert(0 != 0 && "Unknown type encountered");
}
}
}

static
void fill_del_slice(del_slice_conf_t* del)
{
assert(del != NULL);

/// SET DL ID ///
uint32_t dl_ids[] = {2};
del->len_dl = sizeof(dl_ids)/sizeof(dl_ids[0]);
if (del->len_dl > 0)
del->dl = calloc(del->len_dl, sizeof(uint32_t));
for (uint32_t i = 0; i < del->len_dl; i++) {
del->dl[i] = dl_ids[i];
printf("DEL DL SLICE: id %u\n", dl_ids[i]);
}

/// SET UL ID ///
uint32_t ul_ids[] = {2};
del->len_ul = sizeof(ul_ids)/sizeof(ul_ids[0]);
if (del->len_ul > 0)
del->ul = calloc(del->len_ul, sizeof(uint32_t));
for (uint32_t i = 0; i < del->len_ul; i++){
del->ul[i] = ul_ids[i];
printf("DEL UL SLICE: id %u\n", ul_ids[i]);
}

}

static
void fill_assoc_ue_slice(ue_slice_conf_t* assoc)
{
assert(assoc != NULL);

/// SET ASSOC UE NUMBER ///
assoc->len_ue_slice = 1;
if(assoc->len_ue_slice > 0){
assoc->ues = calloc(assoc->len_ue_slice, sizeof(ue_slice_assoc_t));
assert(assoc->ues);
}

/// SET RNTI ///
assoc->ues[0].rnti = assoc_rnti;
/// SET DL ID ///
assoc->ues[0].dl_id = 1; // dl_id = -1 means UE will not perform DL association
if ((int32_t)assoc->ues[0].dl_id != -1){
printf("ASSOC DL SLICE: 0x%x, id %u\n", assoc->ues[0].rnti, assoc->ues[0].dl_id);
}
/// SET UL ID ///
assoc->ues[0].ul_id = -1; // ul_id = -1 means UE will not perform UL association
if ((int32_t)assoc->ues[0].ul_id != -1){
printf("ASSOC UL SLICE: 0x%x, id %u\n", assoc->ues[0].rnti, assoc->ues[0].ul_id);
}
}

static
sm_ag_if_wr_t fill_slice_sm_ctrl_req(uint16_t ran_func_id, slice_ctrl_msg_e type)
{
assert(ran_func_id == 145);

sm_ag_if_wr_t wr = {.type =CONTROL_SM_AG_IF_WR };

if (ran_func_id == 145) {
wr.ctrl.type = SLICE_CTRL_REQ_V0;
wr.ctrl.slice_req_ctrl.hdr.dummy = 0;

if (type == SLICE_CTRL_SM_V0_ADD) {
/// ADD MOD ///
wr.ctrl.slice_req_ctrl.msg.type = SLICE_CTRL_SM_V0_ADD;
fill_add_mod_slice(&wr.ctrl.slice_req_ctrl.msg.u.add_mod_slice);
} else if (type == SLICE_CTRL_SM_V0_DEL) {
/// DEL ///
wr.ctrl.slice_req_ctrl.msg.type = SLICE_CTRL_SM_V0_DEL;
fill_del_slice(&wr.ctrl.slice_req_ctrl.msg.u.del_slice);
} else if (type == SLICE_CTRL_SM_V0_UE_SLICE_ASSOC) {
/// ASSOC SLICE ///
wr.ctrl.slice_req_ctrl.msg.type = SLICE_CTRL_SM_V0_UE_SLICE_ASSOC;
fill_assoc_ue_slice(&wr.ctrl.slice_req_ctrl.msg.u.ue_slice);
} else {
assert(0 != 0 && "Unknown slice ctrl type");
}
} else {
assert(0 !=0 && "Unknown RAN function id");
}
return wr;
}

int main(int argc, char *argv[])
{
fr_args_t args = init_fr_args(argc, argv);
defer({ free_fr_args(&args); });

//Init the xApp
init_xapp_api(&args);
signal(SIGINT, sigint_handler); // we override the signal mask set in init_xapp_api()
signal(SIGTERM, sigint_handler);
sleep(1);

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

assert(nodes.len > 0);
printf("Connected E2 nodes len = %d\n", nodes.len);

// SLICE indication
const char* inter_t = "1000_ms";

size_t node_idx = 0;
for (size_t j = 0; j < nodes.n[node_idx].len_rf; ++j)
printf("Registered ran func id = %d \n ", nodes.n[node_idx].rf[j].id);

sm_ans_xapp_t* slice_handle = NULL;
slice_handle = calloc(1, sizeof(sm_ans_xapp_t));
assert(slice_handle != NULL);

slice_handle[0] = report_sm_xapp_api(&nodes.n[node_idx].id, SM_SLICE_ID, (void*)inter_t, sm_cb_slice);
assert(slice_handle[0].success == true);
sleep(5);

// Control ADD slice
sm_ag_if_wr_t ctrl_msg_add = fill_slice_sm_ctrl_req(SM_SLICE_ID, SLICE_CTRL_SM_V0_ADD);
defer({ free_slice_ctrl_msg(&ctrl_msg_add.ctrl.slice_req_ctrl.msg); });
control_sm_xapp_api(&nodes.n[node_idx].id, SM_SLICE_ID, &ctrl_msg_add);

sleep(5);

// Control ASSOC slice
sm_ag_if_wr_t ctrl_msg_assoc = fill_slice_sm_ctrl_req(SM_SLICE_ID, SLICE_CTRL_SM_V0_UE_SLICE_ASSOC);
defer({ free_slice_ctrl_msg(&ctrl_msg_assoc.ctrl.slice_req_ctrl.msg); });
control_sm_xapp_api(&nodes.n[node_idx].id, SM_SLICE_ID, &ctrl_msg_assoc);

sleep(5);

size_t pr_list_idx = 0;
while(!exit_flag) {
// Control ADD slice
assert(ctrl_msg_add.ctrl.slice_req_ctrl.msg.type == SLICE_CTRL_SM_V0_ADD);
pr_slice_t* pr_slice_0 = &ctrl_msg_add.ctrl.slice_req_ctrl.msg.u.add_mod_slice.dl.slices[0].params.u.pr;
pr_slice_t* pr_slice_1 = &ctrl_msg_add.ctrl.slice_req_ctrl.msg.u.add_mod_slice.dl.slices[1].params.u.pr;

pr_slice_0->max_ratio = pr_slice_0_lst[pr_list_idx];
pr_slice_0->min_ratio = pr_slice_0_lst[pr_list_idx];
pr_slice_0->dedicated_ratio = pr_slice_0_lst[pr_list_idx];
printf("Slice 0 ratio is : %d \n", ctrl_msg_add.ctrl.slice_req_ctrl.msg.u.add_mod_slice.dl.slices[0].params.u.pr.dedicated_ratio);

pr_slice_1->max_ratio = 100 - pr_slice_0_lst[pr_list_idx];
pr_slice_1->min_ratio = 100 - pr_slice_0_lst[pr_list_idx];
pr_slice_1->dedicated_ratio = 100 - pr_slice_0_lst[pr_list_idx];
printf("Slice 1 ratio is : %d \n", ctrl_msg_add.ctrl.slice_req_ctrl.msg.u.add_mod_slice.dl.slices[1].params.u.pr.dedicated_ratio);

if (pr_slice_0_lst[pr_list_idx] == 10){
pr_list_idx = 0;
} else {
pr_list_idx += 1;
}

control_sm_xapp_api(&nodes.n[node_idx].id, SM_SLICE_ID, &ctrl_msg_add);

// Control ASSOC slice
assert(ctrl_msg_assoc.ctrl.slice_req_ctrl.msg.type == SLICE_CTRL_SM_V0_UE_SLICE_ASSOC);
control_sm_xapp_api(&nodes.n[node_idx].id, SM_SLICE_ID, &ctrl_msg_assoc);
sleep(5);
}

// Remove the handle previously returned
rm_report_sm_xapp_api(slice_handle[0].u.handle);

free(slice_handle);

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

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

In order to compile this xApp you should run:

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

Then in order to run it:

./build/labs/lab6 -c conf/default.conf

If run successfully, the output should be as follows:

br@mate:~/LABS/xapp-source/build$ python3 xapp/dev_python/xapp_sdk/xapp_slice_moni_ctrl.py  -c ../conf_files/default.conf
10:20:07.723592 [INFO]: conf_file.c:443 Config file path ../conf_files/default.conf. To change the path add -c path_to_file e.g., python3 mntr.py -c default.conf
10:20:07.723641 [INFO]: e42_xapp_api.c:81 Git SHA1 e7a9fa37e4f056ffd8ca49533e30acf2d4371ce0
10:20:07.723645 [INFO]: e42_xapp.c:191 NearRT-RIC Server IP Address = 10.244.2.155, PORT = 36422
10:20:07.724449 [INFO]: emb_sm_ag.c:93 Loaded SM(s) 10, custom SMs true
10:20:07.724576 [INFO]: emb_sm_ric.c:93 Loaded SM(s) 10, custom SMs true
10:20:07.725617 [INFO]: msg_handler_xapp.c:533 E42 SETUP-REQUEST tx
10:20:07.725831 [INFO]: msg_handler_xapp.c:374 E42 SETUP-RESPONSE rx xApp ID 9
10:20:07.725837 [INFO]: msg_handler_xapp.c:390 Connected E2 Node(s) 1
10:20:07.726143 [INFO]: msg_handler_xapp.c:568 RIC_SUBSCRIPTION_REQUEST tx RAN_FUNC_ID 145 RIC_REQ_ID 1
10:20:07.726429 [INFO]: msg_handler_xapp.c:155 RIC_SUBSCRIPTION_RESPONSE rx RAN_FUNC_ID 145 RIC_REQ_ID 1
ADD PR DL SLICE: id 0, label s1, max_ratio 90, min_ratio 90, dedicated_ratio 90
ADD PR DL SLICE: id 1, label s2, max_ratio 10, min_ratio 10, dedicated_ratio 10
RESET UL SLICE, algo = NONE
10:20:12.730912 [INFO]: msg_handler_xapp.c:613 E42_RIC_CONTROL_REQUEST RAN_FUNC_ID 145 RIC_REQ_ID 2 tx
10:20:12.731207 [INFO]: msg_handler_xapp.c:306 CONTROL ACK rx RIC_REQ_ID 2
ASSOC DL SLICE: rnti e0f1, to slice id 1
10:20:17.732309 [INFO]: msg_handler_xapp.c:613 E42_RIC_CONTROL_REQUEST RAN_FUNC_ID 145 RIC_REQ_ID 3 tx
10:20:17.732662 [INFO]: msg_handler_xapp.c:306 CONTROL ACK rx RIC_REQ_ID 3
ADD PR DL SLICE: id 0, label s1, max_ratio 50, min_ratio 50, dedicated_ratio 50
ADD PR DL SLICE: id 1, label s2, max_ratio 14, min_ratio 14, dedicated_ratio 14
RESET UL SLICE, algo = NONE
10:20:17.735474 [INFO]: msg_handler_xapp.c:613 E42_RIC_CONTROL_REQUEST RAN_FUNC_ID 145 RIC_REQ_ID 4 tx
10:20:17.735783 [INFO]: msg_handler_xapp.c:306 CONTROL ACK rx RIC_REQ_ID 4
ASSOC DL SLICE: rnti e0f1, to slice id 1
10:20:17.735817 [INFO]: msg_handler_xapp.c:613 E42_RIC_CONTROL_REQUEST RAN_FUNC_ID 145 RIC_REQ_ID 5 tx
10:20:17.735962 [INFO]: msg_handler_xapp.c:306 CONTROL ACK rx RIC_REQ_ID 5
ADD PR DL SLICE: id 0, label s1, max_ratio 46, min_ratio 46, dedicated_ratio 46
ADD PR DL SLICE: id 1, label s2, max_ratio 1e, min_ratio 1e, dedicated_ratio 1e
RESET UL SLICE, algo = NONE

Uninstall​

To uninstall the network, use the following command:

brc remove network open-ran.yaml

Checking via the brc observe command, you should see that all the elements are removed.

Advanced (optional)

This lab can also be performed leveraging an over-the-air deployment. In this section, we provide a sample deployment with a LITEON RU. Similarly to the previous deployment, this includes a 5G Standalone (SA) network with OpenAirInterface (OAI) gNB using a LITEON RU device, and Open5GS core network.

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.

After the network has been successfully deployed, the monitoring xApp can be deployed following the exact same steps previously detailed.

warning

Before deploying this network first make sure:

  1. The CU-DU node name specified in the deployment file (in this case bubble2 on the section scheduling) is correct.
  2. The CU-DU node is able to reach the RU IP specified in the deployment file. If not sure about the IP, please check the Google Sheet (provided to all customers) with all IPs of your MX-PDK. To do so you may try to ssh into the RU from the node with the command ssh user@RU-IP replacing RU-IP with the actual IP.
  3. The CU-DU node is properly synchronized with the PTP grandmaster switch. To do so you may check the status with
sudo systemctl status ptp4l.service
sudo systemctl status phc2sys.service
  1. The CU-DU node's DPDK has been setup with
sudo dpdk-setup