diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py
index 3cebcb24d7..cd07851319 100644
--- a/ci-scripts/cls_containerize.py
+++ b/ci-scripts/cls_containerize.py
@@ -47,6 +47,7 @@ import helpreadme as HELP
import constants as CONST
import cls_oaicitest
from cls_ci_helper import archiveArtifact
+from collections import deque
#-----------------------------------------------------------
# Helper functions used here and in other classes
@@ -165,25 +166,26 @@ def CopyinServiceLog(ssh, lSourcePath, svcName, wd_yaml, ctx):
ssh.run(f'docker compose -f {wd_yaml} logs {svcName} --no-log-prefix &> {remote_filename}')
return archiveArtifact(ssh, ctx, remote_filename)
-def GetRunningServices(ssh, file):
+def GetDeployedServices(ssh, file):
ret = ssh.run(f'docker compose -f {file} config --services')
if ret.returncode != 0:
+ logging.error("could not get services")
return None
allServices = ret.stdout.splitlines()
- running_services = []
+ deployed_services = []
for s in allServices:
- # outputs the hash if the container is running
- ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}')
+ # outputs the hash if the container has been deployed (but might be stopped)
+ ret = ssh.run(f'docker compose -f {file} ps --all --quiet -- {s}', silent=True)
if ret.returncode != 0:
- logging.info(f"service {s}: {ret.stdout}")
+ # error: should not happen as we iterate over docker-provided service list
+ logging.error(f"service {s}: {ret.stdout}")
elif ret.stdout == "":
- logging.warning(f"could not retrieve information for service {s}")
+ logging.info(f"service {s} not deployed")
else:
c = ret.stdout
- logging.debug(f'running service {s} with container id {c}')
- running_services.append((s, c))
- logging.info(f'stopping services: {running_services}')
- return running_services
+ logging.info(f'service {s} with container id {c}')
+ deployed_services.append(s)
+ return deployed_services
def CheckLogs(self, filename, HTML, RAN):
success = True
@@ -215,6 +217,24 @@ def CheckLogs(self, filename, HTML, RAN):
else:
HTML.CreateHtmlTestRowQueue(opt, 'OK', [HTML.htmleNBFailureMsg])
HTML.htmleNBFailureMsg = ""
+ elif 'xapp' in name:
+ opt = f"Undeploy {name}"
+ with open(f'{filename}', "r") as f:
+ last_line = deque(f, maxlen=1).pop()
+ if ('Test xApp run SUCCESSFULLY' in last_line):
+ HTML.CreateHtmlTestRowQueue(opt, 'OK', ["xApp run successfully"])
+ else:
+ HTML.CreateHtmlTestRowQueue(opt, 'KO', ["xApp didn't run successfully"])
+ success = False
+ elif 'RIC' in name:
+ opt = f"Undeploy {name}"
+ with open(f'{filename}', 'r') as f:
+ last_line = deque(f, maxlen=1).pop()
+ if ('Removing E2 Node' in last_line):
+ HTML.CreateHtmlTestRowQueue(opt, 'OK', ["nearRT-RIC run successfully"])
+ else:
+ HTML.CreateHtmlTestRowQueue(opt, 'KO', ["nearRT-RIC didn't run successfully"])
+ success = False
else:
logging.info(f"Skipping analysis of log '{filename}': no submatch for xNB/UE")
logging.debug(f"log check: file {filename} passed analysis {success}")
@@ -715,7 +735,6 @@ class Containerize():
def DeployObject(self, ctx, node, HTML):
num_attempts = self.num_attempts
lSourcePath = self.eNBSourceCodePath
- logging.debug(f'Deploying OAI Object on server: {node}')
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
wd_yaml = f'{wd}/docker-compose.y*ml'
@@ -726,6 +745,7 @@ class Containerize():
logging.error(msg)
HTML.CreateHtmlTestRowQueue('N/A', 'KO', [msg])
return False
+ logging.info(f'\u001B[1mDeploying object(s) "{services}" on server {node}\u001B[0m')
ExistEnvFilePrint(ssh, wd)
WriteEnvFile(ssh, services, wd, self.deploymentTag, self.flexricTag)
if num_attempts <= 0:
@@ -750,36 +770,68 @@ class Containerize():
imagesInfo = info.stdout.splitlines()[1:]
logging.debug(f'{info.stdout.splitlines()[1:]}')
if deployed:
- HTML.CreateHtmlTestRowQueue('N/A', 'OK', ['\n'.join(imagesInfo)])
+ HTML.CreateHtmlTestRowQueue(self.services, 'OK', ['\n'.join(imagesInfo)])
+ logging.info('\u001B[1m Deploying objects Pass\u001B[0m')
else:
- HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['\n'.join(imagesInfo)])
+ HTML.CreateHtmlTestRowQueue(self.services, 'KO', ['\n'.join(imagesInfo)])
+ logging.error('\u001B[1m Deploying objects Failed\u001B[0m')
return deployed
+ def StopObject(self, ctx, node, HTML):
+ lSourcePath = self.eNBSourceCodePath
+ if not self.services:
+ raise ValueError(f'no services provided')
+ logging.info(f'\u001B[1m Stopping objects "{self.services}" from server: {node}\u001B[0m')
+ reqServices = self.services.split()
+ yaml = self.yamlPath.strip('/')
+ wd = f'{lSourcePath}/{yaml}'
+ wd_yaml = f'{wd}/docker-compose.y*ml'
+ with cls_cmd.getConnection(node) as ssh:
+ ExistEnvFilePrint(ssh, wd)
+ services = GetDeployedServices(ssh, wd_yaml)
+ success = []
+ fail = []
+ for s in reqServices:
+ if s in services:
+ ssh.run(f'docker compose -f {wd_yaml} stop -- {s}')
+ success.append(s)
+ else:
+ logging.error(f"no such service {s}")
+ fail.append(s)
+ if success == reqServices:
+ logging.info('\u001B[1m Stopping object Pass\u001B[0m')
+ HTML.CreateHtmlTestRowQueue(self.services, 'OK', [f'Stopped {self.services}'])
+ else:
+ logging.error('\u001B[1m Stopping object Failed\u001B[0m')
+ HTML.CreateHtmlTestRowQueue(self.services, 'KO', [f'Failed stopping {" ".join(fail)}, succeeded {" ".join(success)}'])
+ return success
+
def UndeployObject(self, ctx, node, HTML, RAN):
lSourcePath = self.eNBSourceCodePath
- logging.debug(f'\u001B[1m Undeploying OAI Object from server: {node}\u001B[0m')
+ logging.info(f'\u001B[1m Undeploying all objects from server {node}\u001B[0m')
yaml = self.yamlPath.strip('/')
wd = f'{lSourcePath}/{yaml}'
+ wd_yaml = f'{wd}/docker-compose.y*ml'
with cls_cmd.getConnection(node) as ssh:
ExistEnvFilePrint(ssh, wd)
- services = GetRunningServices(ssh, f"{wd}/docker-compose.y*ml")
+ services = GetDeployedServices(ssh, wd_yaml)
copyin_res = None
+ ssh.run(f'docker compose -f {wd_yaml} stop')
if services is not None:
- all_serv = " ".join([s for s, _ in services])
- ssh.run(f'docker compose -f {wd}/docker-compose.y*ml stop -- {all_serv}')
- copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, f"{wd}/docker-compose.y*ml", ctx) for s, _ in services]
+ copyin_res = [CopyinServiceLog(ssh, lSourcePath, s, wd_yaml, ctx) for s in services]
else:
logging.warning('could not identify services to stop => no log file')
- ssh.run(f'docker compose -f {wd}/docker-compose.y*ml down -v')
+ ssh.run(f'docker compose -f {wd_yaml} down -v')
ssh.run(f'rm {wd}/.env')
if not copyin_res:
HTML.CreateHtmlTestRowQueue('N/A', 'KO', ['Could not copy logfile(s)'])
- return False
+ logging.error(f"could not copy all files: {copyin_res=} {services=}")
+ success = False
else:
log_results = [CheckLogs(self, f, HTML, RAN) for f in copyin_res]
success = all(log_results)
if success:
- logging.info('\u001B[1m Undeploying OAI Object Pass\u001B[0m')
+ logging.info('\u001B[1m Undeploying objects Pass\u001B[0m')
else:
- logging.error('\u001B[1m Undeploying OAI Object Failed\u001B[0m')
+ logging.error('\u001B[1m Undeploying objects Failed\u001B[0m')
return success
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 2428df83af..8aadad76bb 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -214,7 +214,7 @@ def ExecuteActionWithParam(action, ctx, node):
core_op = getattr(cls_oaicitest.OaiCiTest, action)
success = core_op(cn_id, ctx, HTML)
- elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace":
+ elif action == 'Deploy_Object' or action == 'Undeploy_Object' or action == "Create_Workspace" or action == "Stop_Object":
CONTAINERS.yamlPath = test.findtext('yaml_path')
string_field=test.findtext('d_retx_th')
if (string_field is not None):
@@ -227,6 +227,8 @@ def ExecuteActionWithParam(action, ctx, node):
CONTAINERS.deploymentTag = cls_containerize.CreateTag(CONTAINERS.ranCommitID, CONTAINERS.ranBranch, CONTAINERS.ranAllowMerge)
if action == 'Deploy_Object':
success = CONTAINERS.DeployObject(ctx, node, HTML)
+ elif action == 'Stop_Object':
+ success = CONTAINERS.StopObject(ctx, node, HTML)
elif action == 'Undeploy_Object':
success = CONTAINERS.UndeployObject(ctx, node, HTML, RAN)
elif action == 'Create_Workspace':
diff --git a/ci-scripts/tests/deployment.py b/ci-scripts/tests/deployment.py
index e7efc707bf..10bd2c843f 100644
--- a/ci-scripts/tests/deployment.py
+++ b/ci-scripts/tests/deployment.py
@@ -60,6 +60,33 @@ class TestDeploymentMethods(unittest.TestCase):
self.assertTrue(deploy)
self.assertTrue(undeploy)
+ def test_stop_services(self):
+ self.cont.yamlPath = 'tests/simple-undep/'
+ self.cont.deploymentTag = "noble"
+ # should deploy both testA and testB
+ deploy = self.cont.DeployObject(self.ctx, self.node, self.html)
+ # should fail (no such service)
+ self.cont.services = "testC"
+ stopC = self.cont.StopObject(self.ctx, self.node, self.html)
+ # should stop testA
+ self.cont.services = "testA"
+ stopA = self.cont.StopObject(self.ctx, self.node, self.html)
+ # should (re-)stop testA (no-op)
+ self.cont.services = "testA"
+ stopA2 = self.cont.StopObject(self.ctx, self.node, self.html)
+ # should deploy testB
+ self.cont.services = "testB"
+ stopB = self.cont.StopObject(self.ctx, self.node, self.html)
+ # should not undeploy anything (everything already stopped)
+ self.cont.services = None
+ undeployAll = self.cont.UndeployObject(self.ctx, self.node, self.html, self.ran)
+ self.assertTrue(deploy)
+ self.assertFalse(stopC)
+ self.assertTrue(stopA)
+ self.assertTrue(stopA2)
+ self.assertTrue(stopB)
+ self.assertTrue(undeployAll)
+
def test_deployfails(self):
# fails reliably
old = self.cont.yamlPath
diff --git a/ci-scripts/tests/simple-undep/docker-compose.yml b/ci-scripts/tests/simple-undep/docker-compose.yml
new file mode 100644
index 0000000000..6f88826a9a
--- /dev/null
+++ b/ci-scripts/tests/simple-undep/docker-compose.yml
@@ -0,0 +1,23 @@
+services:
+ testA:
+ image: ubuntu:${TAG:-jammy}
+ container_name: test_container_A
+ cap_drop:
+ - ALL
+ entrypoint: /bin/bash -c "sleep infinity"
+ healthcheck:
+ test: /bin/bash -c "true"
+ interval: 1s
+ timeout: 1s
+ retries: 1
+ testB:
+ image: ubuntu:${TAG:-jammy}
+ container_name: test_container_B
+ cap_drop:
+ - ALL
+ entrypoint: /bin/bash -c "sleep infinity"
+ healthcheck:
+ test: /bin/bash -c "true"
+ interval: 1s
+ timeout: 1s
+ retries: 1
diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml
index 615454bbea..a20b78fc99 100755
--- a/ci-scripts/xml_class_list.yml
+++ b/ci-scripts/xml_class_list.yml
@@ -20,6 +20,7 @@
- Build_Image
- Build_Run_Tests
- Deploy_Object
+ - Stop_Object
- Undeploy_Object
- Cppcheck_Analysis
- Deploy_Run_OC_PhySim
diff --git a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml
index 536952a2bc..135eab6b68 100644
--- a/ci-scripts/xml_files/container_5g_flexric_rfsim.xml
+++ b/ci-scripts/xml_files/container_5g_flexric_rfsim.xml
@@ -42,6 +42,13 @@
002006
444444
100002
+ 100003
+ 100004
+ 100005
+ 100006
+ 100007
+ 100008
+ 100009
100001
222221
222222
@@ -95,10 +102,10 @@
Deploy_Object
- Deploy OAI FlexRIC
+ Deploy OAI nearRT-RIC
localhost
ci-scripts/yaml_files/5g_rfsimulator_flexric
- oai-flexric
+ nearRT-RIC
@@ -151,16 +158,72 @@
+ Stop_Object
+ Stop RC monitoring xApp
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ xapp-rc-moni
+
+
+
+ Stop_Object
+ Stop KPM monitoring xApp
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ xapp-kpm-moni
+
+
+
+ Stop_Object
+ Stop KPM monitoring and RC control xApp
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ xapp-kpm-rc
+
+
+
+ Stop_Object
+ Stop custom SMs monitoring xApp
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ xapp-gtp-mac-rlc-pdcp-moni
+
+
+
+ Stop_Object
+ Stop OAI UEs
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ oai-nr-ue oai-nr-ue2
+
+
+
+ Stop_Object
+ Stop OAI gNB
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ oai-gnb
+
+
+
+ Stop_Object
+ Stop nearRT-RIC
+ localhost
+ ci-scripts/yaml_files/5g_rfsimulator_flexric
+ nearRT-RIC
+
+
+
Undeploy_Object
- Undeploy RAN and Flexric
+ Undeploy RAN and FlexRIC
localhost
ci-scripts/yaml_files/5g_rfsimulator_flexric
true
-
+
Deploy_Object
- RC monitoring
+ Deploy RC monitoring
localhost
ci-scripts/yaml_files/5g_rfsimulator_flexric
xapp-rc-moni
@@ -168,7 +231,7 @@
Deploy_Object
- KPM monitoring
+ Deploy KPM monitoring
localhost
ci-scripts/yaml_files/5g_rfsimulator_flexric
xapp-kpm-moni
@@ -176,7 +239,7 @@
Deploy_Object
- KPM monitoring and RC control
+ Deploy KPM monitoring and RC control
localhost
ci-scripts/yaml_files/5g_rfsimulator_flexric
xapp-kpm-rc
@@ -184,7 +247,7 @@
Deploy_Object
- Custom SMs monitoring
+ Deploy custom SMs monitoring
localhost
ci-scripts/yaml_files/5g_rfsimulator_flexric
xapp-gtp-mac-rlc-pdcp-moni
diff --git a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml
index d563b3aab4..86b9040b63 100644
--- a/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml
+++ b/ci-scripts/xml_files/container_5g_rfsim_u0_25prb.xml
@@ -144,7 +144,6 @@
true
Undeploy all OAI 5G stack
localhost
- oai-vnf oai-pnf
ci-scripts/yaml_files/5g_rfsimulator_u0_25prb
1,0,0,0
1,0,0,0
diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml
index a4d72398e1..ad98afcd32 100644
--- a/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml
+++ b/ci-scripts/xml_files/container_sa_n310_2X2_100MHz_quectel.xml
@@ -146,7 +146,6 @@
Undeploy gNB
matix
ci-scripts/yaml_files/5g_sa_n310_2x2_100MHz
- oai-gnb
10,100,100,100
10,100,100,100
diff --git a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml
index ab7188c023..a809fafa2c 100644
--- a/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml
+++ b/ci-scripts/xml_files/container_sa_n310_2X2_60MHz_quectel.xml
@@ -146,7 +146,6 @@
Undeploy gNB
matix
ci-scripts/yaml_files/5g_sa_n310_2x2_60MHz
- oai-gnb
15,100,100,100
20,100,100,100
diff --git a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml
index d7cf992aa4..d4d0d51258 100644
--- a/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml
+++ b/ci-scripts/xml_files/container_sa_n310_4X4_60MHz_quectel.xml
@@ -146,7 +146,6 @@
Undeploy VNF-PNF
matix
ci-scripts/yaml_files/5g_sa_n310_4x4_60MHz
- oai-vnf oai-pnf
10,100,100,100
10,100,100,100
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml b/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml
index 8e1688dff3..5bb8d0246d 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_flexric/docker-compose.yml
@@ -1,7 +1,7 @@
services:
- oai-flexric:
+ nearRT-RIC:
image: ${REGISTRY-oaisoftwarealliance/}oai-flexric:${FLEXRIC_TAG:-develop}
- container_name: oai-flexric
+ container_name: nearRT-RIC
networks:
public_net:
ipv4_address: 192.168.70.150
@@ -17,7 +17,7 @@ services:
command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_rc_moni"
container_name: xapp-rc-moni
depends_on:
- - oai-flexric
+ - nearRT-RIC
- oai-gnb
networks:
public_net:
@@ -34,7 +34,7 @@ services:
command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_kpm_moni"
container_name: xapp-kpm-moni
depends_on:
- - oai-flexric
+ - nearRT-RIC
- oai-gnb
networks:
public_net:
@@ -51,7 +51,7 @@ services:
command: "stdbuf -o0 /usr/local/flexric/xApp/c/kpm_rc/xapp_kpm_rc"
container_name: xapp-kpm-rc
depends_on:
- - oai-flexric
+ - nearRT-RIC
- oai-gnb
networks:
public_net:
@@ -68,7 +68,7 @@ services:
command: "stdbuf -o0 /usr/local/flexric/xApp/c/monitor/xapp_gtp_mac_rlc_pdcp_moni"
container_name: xapp-gtp-mac-rlc-pdcp-moni
depends_on:
- - oai-flexric
+ - nearRT-RIC
- oai-gnb
networks:
public_net:
@@ -88,7 +88,7 @@ services:
USE_ADDITIONAL_OPTIONS: -E --rfsim --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
depends_on:
- - oai-flexric
+ - nearRT-RIC
networks:
public_net:
ipv4_address: 192.168.70.151
diff --git a/common/utils/telnetsrv/telnetsrv_o1.c b/common/utils/telnetsrv/telnetsrv_o1.c
index ac368885f6..9ff56e3521 100644
--- a/common/utils/telnetsrv/telnetsrv_o1.c
+++ b/common/utils/telnetsrv/telnetsrv_o1.c
@@ -105,10 +105,10 @@ static int get_stats(char *buf, int debug, telnet_printfunc_t prnt)
int bw_index = get_supported_band_index(scs, fr, nrb);
int bw_mhz = get_supported_bw_mhz(fr, bw_index);
- const mac_stats_t *stat = &mac->mac_stats;
- static mac_stats_t last = {0};
- int diff_used = stat->used_prb_aggregate - last.used_prb_aggregate;
- int diff_total = stat->total_prb_aggregate - last.total_prb_aggregate;
+ const dlul_mac_stats_t *stat = &mac->mac_stats;
+ static dlul_mac_stats_t last = {0};
+ int diff_used = stat->dl.used_prb_aggregate - last.dl.used_prb_aggregate;
+ int diff_total = stat->dl.total_prb_aggregate - last.dl.total_prb_aggregate;
int load = diff_total > 0 ? 100 * diff_used / diff_total : 0;
last = *stat;
diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c
index 0c2c9cdf3f..df2f633d95 100644
--- a/executables/nr-cuup.c
+++ b/executables/nr-cuup.c
@@ -51,8 +51,9 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args)
printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip );
- fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL);
- memcpy(args.libs_dir, oai_args.sm_dir, 128);
+ fr_args_t args = {0};
+ memcpy(args.ip, oai_args.ip, FR_IP_ADDRESS_LEN);
+ memcpy(args.libs_dir, oai_args.sm_dir, FR_CONF_FILE_LEN);
sleep(1);
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 0bd583662b..945e7e4cae 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -473,8 +473,9 @@ static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args)
printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip );
- fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL);
- memcpy(args.libs_dir, oai_args.sm_dir, 128);
+ fr_args_t args = {0};
+ memcpy(args.ip, oai_args.ip, FR_IP_ADDRESS_LEN);
+ memcpy(args.libs_dir, oai_args.sm_dir, FR_CONF_FILE_LEN);
sleep(1);
const gNB_RRC_INST* rrc = RC.nrrrc[0];
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c
index 02760c4984..8933b802a0 100644
--- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c
@@ -54,10 +54,12 @@ typedef struct {
ue_id_e2sm_t* ue_id;
// Optional
- // only used to retreive MAC/RLC stats
+ // only used to retrieve MAC/RLC stats
NR_UE_info_t** ue_info_list;
}arr_ue_id_t;
+static e2_node_level_stats_t node_stats[2] = {0}; // [0] node stats collected in previous reporting period; [1] current node stats
+
static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* meas_info_lst, const size_t len, const uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
meas_data_lst_t data_item = {0};
@@ -74,7 +76,7 @@ static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* m
char* meas_info_name_str = cp_ba_to_str(meas_info_lst[i].meas_type.name);
- data_item.meas_record_lst[i] = get_kpm_meas_value(meas_info_name_str, gran_period_ms, ue_info, ue_idx);
+ data_item.meas_record_lst[i] = get_kpm_meas_value(meas_info_name_str, gran_period_ms, ue_info, ue_idx, node_stats);
free(meas_info_name_str);
}
@@ -153,6 +155,8 @@ static kpm_ind_msg_format_3_t fill_kpm_ind_msg_frm_3(arr_ue_id_t* arr_ue_id, con
msg_frm_3.meas_report_per_ue[i].ind_msg_format_1 = fill_kpm_ind_msg_frm_1(ue_info, i, act_def_fr_1);
}
+ node_stats[0] = cp_node_level_stats(&node_stats[1]);
+
return msg_frm_3;
}
@@ -288,8 +292,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst
const ngran_node_t node_type = get_e2_node_type();
+ gNB_MAC_INST *mac = RC.nrmac[0];
+ NR_SCHED_LOCK(&mac->sched_lock);
// Take MAC info
- UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, ue) {
+ UE_iterator(mac->UE_info.connected_ue_list, ue) {
NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl;
// UE matches if any of its DRBs matches
for (size_t l = 0; l < seq_arr_size(&sched_ctrl->lc_config); ++l) {
@@ -316,6 +322,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst
AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n");
}
+ node_stats[1].mac_stats.dl.total_prb_aggregate = mac->mac_stats.dl.total_prb_aggregate;
+ node_stats[1].mac_stats.ul.total_prb_aggregate = mac->mac_stats.ul.total_prb_aggregate;
+ NR_SCHED_UNLOCK(&mac->sched_lock);
+
free(sd); // if NULL, nothing happens
return arr_ue_id;
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c
index 80579e1754..d3381cadd3 100644
--- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c
@@ -23,6 +23,18 @@
#include
+e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src)
+{
+ e2_node_level_stats_t dst = {
+ .mac_stats.dl.total_prb_aggregate = src->mac_stats.dl.total_prb_aggregate,
+ .mac_stats.dl.used_prb_aggregate = src->mac_stats.dl.used_prb_aggregate,
+ .mac_stats.ul.total_prb_aggregate = src->mac_stats.ul.total_prb_aggregate,
+ .mac_stats.ul.used_prb_aggregate = src->mac_stats.ul.used_prb_aggregate,
+ };
+
+ return dst;
+}
+
/* measurements that need to store values from previous reporting period have a limitation
when it comes to multiple subscriptions to the same UEs; ric_req_id is unique per subscription */
typedef struct uldlcounter {
@@ -46,7 +58,7 @@ static nr_pdcp_statistics_t get_pdcp_stats_per_drb(const uint32_t rrc_ue_id, con
/* 3GPP TS 28.522 - section 5.1.2.1.1.1
note: this measurement is calculated as per spec */
-static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
@@ -57,7 +69,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_
meas_record.value = INTEGER_MEAS_VALUE;
// Get DL data volume delivered to PDCP layer
- meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000; // [kb]
+ meas_record.int_val = (pdcp.rxsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].dl)*8/1000000; // [Mb]
last_pdcp_sdu_total_bytes[ue_idx].dl = pdcp.rxsdu_bytes;
return meas_record;
@@ -65,7 +77,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_
/* 3GPP TS 28.522 - section 5.1.2.1.2.1
note: this measurement is calculated as per spec */
-static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
@@ -76,7 +88,7 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused))uint32_
meas_record.value = INTEGER_MEAS_VALUE;
// Get UL data volume delivered from PDCP layer
- meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000; // [kb]
+ meas_record.int_val = (pdcp.txsdu_bytes - last_pdcp_sdu_total_bytes[ue_idx].ul)*8/1000000; // [Mb]
last_pdcp_sdu_total_bytes[ue_idx].ul = pdcp.txsdu_bytes;
return meas_record;
@@ -103,7 +115,7 @@ static nr_rlc_statistics_t get_rlc_stats_per_drb(const rnti_t rnti, const int rb
/* 3GPP TS 28.522 - section 5.1.3.3.3
note: by default this measurement is calculated for previous 100ms (openair2/LAYER2/nr_rlc/nr_rlc_entity.c:118, 173, 213); please, update according to your needs */
-static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx)
+static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, __attribute__((unused))const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
@@ -122,7 +134,7 @@ static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t
/* 3GPP TS 28.522 - section 5.1.1.3.1
note: per spec, average UE throughput in DL (taken into consideration values from all UEs, and averaged)
here calculated as: UE specific throughput in DL */
-static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
@@ -141,7 +153,7 @@ static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_
/* 3GPP TS 28.522 - section 5.1.1.3.3
note: per spec, average UE throughput in UL (taken into consideration values from all UEs, and averaged)
here calculated as: UE specific throughput in UL */
-static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, __attribute__((unused))e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
@@ -159,32 +171,30 @@ static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_
}
/* 3GPP TS 28.522 - section 5.1.1.2.1
- note: per spec, DL PRB usage [%] = (total used PRBs for DL traffic / total available PRBs for DL traffic) * 100
- here calculated as: aggregated DL PRBs (t) - aggregated DL PRBs (t-gran_period) */
-static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+ note: this measurement is calculated as per spec */
+static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
meas_record.value = INTEGER_MEAS_VALUE;
// Get the number of DL PRBs
- meas_record.int_val = ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl; // [PRBs]
+ meas_record.int_val = (ue_info.ue->mac_stats.dl.total_rbs - last_total_prbs[ue_idx].dl) * 100 / (node_stats[1].mac_stats.dl.total_prb_aggregate - node_stats[0].mac_stats.dl.total_prb_aggregate); // [%]
last_total_prbs[ue_idx].dl = ue_info.ue->mac_stats.dl.total_rbs;
return meas_record;
}
/* 3GPP TS 28.522 - section 5.1.1.2.2
- note: per spec, UL PRB usage [%] = (total used PRBs for UL traffic / total available PRBs for UL traffic) * 100
- here calculated as: aggregated UL PRBs (t) - aggregated UL PRBs (t-gran_period) */
-static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+ note: this measurement is calculated as per spec */
+static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {0};
meas_record.value = INTEGER_MEAS_VALUE;
// Get the number of UL PRBs
- meas_record.int_val = ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul; // [PRBs]
+ meas_record.int_val = (ue_info.ue->mac_stats.ul.total_rbs - last_total_prbs[ue_idx].ul) * 100 / (node_stats[1].mac_stats.ul.total_prb_aggregate - node_stats[0].mac_stats.ul.total_prb_aggregate); // [%]
last_total_prbs[ue_idx].ul = ue_info.ue->mac_stats.ul.total_rbs;
return meas_record;
@@ -217,7 +227,7 @@ void init_kpm_subs_data(void)
}
}
-meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
+meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats)
{
assert(kpm_meas_name != NULL);
@@ -226,7 +236,7 @@ meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_m
assert(found_entry != NULL && "Unsupported KPM measurement name");
kv_measure_t *kv_found = (kv_measure_t *)found_entry->data;
- meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx);
+ meas_record_lst_t meas_record = kv_found->value(gran_period_ms, ue_info, ue_idx, node_stats);
return meas_record;
}
diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h
index 7dbd807fa1..e612ca2bab 100644
--- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h
+++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm_subs.h
@@ -34,7 +34,13 @@ typedef struct {
} cudu_ue_info_pair_t;
-typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
+typedef struct {
+ dlul_mac_stats_t mac_stats;
+} e2_node_level_stats_t;
+
+e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src);
+
+typedef meas_record_lst_t (*kpm_meas_fp)(uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats);
typedef struct{
char* key;
@@ -44,6 +50,6 @@ typedef struct{
void init_kpm_subs_data(void);
-meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
+meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx, e2_node_level_stats_t* node_stats);
#endif
diff --git a/openair2/E2AP/flexric b/openair2/E2AP/flexric
index df754a8553..6a595d8b24 160000
--- a/openair2/E2AP/flexric
+++ b/openair2/E2AP/flexric
@@ -1 +1 @@
-Subproject commit df754a85537f6db255b5330b8d83eda6a2742f25
+Subproject commit 6a595d8b243601b7148f60b5cb2cec47658e58c5
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 1466099ab1..fd1cf7f9f3 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -1223,7 +1223,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
T(T_GNB_MAC_RETRANSMISSION_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock.buf, TBS));
UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize;
- nr_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
+ nr_mac->mac_stats.dl.used_prb_aggregate += sched_pdsch->rbSize;
} else { /* initial transmission */
LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot);
uint8_t *buf = allocate_transportBlock_buffer(&harq->transportBlock, TBS);
@@ -1337,7 +1337,7 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
UE->mac_stats.dl.num_mac_sdu += sdus;
UE->mac_stats.dl.current_rbs = sched_pdsch->rbSize;
UE->mac_stats.dl.total_sdu_bytes += dlsch_total_bytes;
- nr_mac->mac_stats.used_prb_aggregate += sched_pdsch->rbSize;
+ nr_mac->mac_stats.dl.used_prb_aggregate += sched_pdsch->rbSize;
/* save retransmission information */
harq->sched_pdsch = *sched_pdsch;
@@ -1387,8 +1387,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
return;
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
- const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
- gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
+ int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
+ gNB_mac->mac_stats.dl.total_prb_aggregate += bw;
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
post_process_pdsch_t pdsch = { frame, slot, dl_req, TX_req };
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 17a4ad5a42..3f546d41b4 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -2455,6 +2455,7 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
}
UE->mac_stats.ul.current_bytes = sched_pusch->tb_size;
UE->mac_stats.ul.current_rbs = sched_pusch->rbSize;
+ nr_mac->mac_stats.ul.used_prb_aggregate += sched_pusch->rbSize;
sched_ctrl->last_ul_frame = sched_pusch->frame;
sched_ctrl->last_ul_slot = sched_pusch->slot;
@@ -2697,6 +2698,7 @@ static void nr_ulsch_preprocessor(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp
int tda = seq_arr_dist(&nr_mac->ul_tda, seq_arr_front(&nr_mac->ul_tda), tda_info);
AssertFatal(tda >= 0 && tda < 16, "illegal TDA index %d\n", tda);
+ nr_mac->mac_stats.ul.total_prb_aggregate += bw;
int len[num_beams];
for (int i = 0; i < num_beams; i++)
len[i] = rb_len;
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index d6a9ae1497..aa8b2b8644 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -870,6 +870,11 @@ typedef struct {
uint64_t used_prb_aggregate;
} mac_stats_t;
+typedef struct dlul_mac_stats {
+ mac_stats_t dl;
+ mac_stats_t ul;
+} dlul_mac_stats_t;
+
/// helper type to encapsulate a frame/slot combination in a single type.
/// Currently only used in the UL preprocessor. Note: if you use this type
/// further, please refactor it into a common type first.
@@ -996,7 +1001,7 @@ typedef struct gNB_MAC_INST_s {
pthread_mutex_t sched_lock;
- mac_stats_t mac_stats;
+ dlul_mac_stats_t mac_stats;
uint64_t num_scheduled_prach_rx;
} gNB_MAC_INST;