Commit fe228e57 authored by Noemi Giustini's avatar Noemi Giustini

Add RRC.ConnMean metric

Implement RRC.ConnMean (3GPP TS 28.552 §5.1.1.4.1): mean number of UEs in
RRC-CONNECTED state over the granularity period, computed as a time-average
of periodic samples.

- ran_func_kpm.c: append RRC.ConnMean to kpm_node_meas_cu[] and
  kpm_node_meas_gnb[].
- ran_func_kpm_subs.h: add rrc_conn_count_sum and rrc_conn_count_samples to
  e2_node_level_stats_t for per-report start/end snapshots.
- ran_func_kpm_subs.c: add fill_RRC_ConnMean(); snapshots the live RRC
  counters into node_stats[1], computes the mean as Δsum/Δsamples over the
  granularity window, returns a real-valued record (noLabel); extend
  cp_node_level_stats() to copy the two new fields; add dispatch entry to
  lst_measure[].
- nr_rrc_defs.h: add rrc_conn_count_sum and rrc_conn_count_samples to
  gNB_RRC_INST.
- rrc_gNB.c: add nr_rrc_sample_conn_count(); it samples the connected-UE
  count and accumulates it into the cumulative counters, invoked from the
  existing stats timer in the RRC task loop. It is always compiled: counting
  is harmless when the E2 agent is disabled, and it leaves the timer setup
  and write_rrc_stats() untouched.

Advertised by CU and monolithic gNB node types.
Signed-off-by: default avatarNoemi Giustini <giustini.n@northeastern.edu>
parent 97dee1ac
...@@ -447,6 +447,7 @@ static const char* kpm_node_meas_du[] = { ...@@ -447,6 +447,7 @@ static const char* kpm_node_meas_du[] = {
static const char* kpm_node_meas_cu[] = { static const char* kpm_node_meas_cu[] = {
"MR.NRScSSSINR", "MR.NRScSSSINR",
"RRC.ConnMean",
NULL, NULL,
}; };
...@@ -455,6 +456,7 @@ static const char* kpm_node_meas_gnb[] = { ...@@ -455,6 +456,7 @@ static const char* kpm_node_meas_gnb[] = {
"CARR.PUSCHMCSDist", "CARR.PUSCHMCSDist",
"L1M.SS-RSRP", "L1M.SS-RSRP",
"MR.NRScSSSINR", "MR.NRScSSSINR",
"RRC.ConnMean",
NULL, NULL,
}; };
......
...@@ -15,6 +15,8 @@ e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src) ...@@ -15,6 +15,8 @@ e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src)
.mac_stats.dl.used_prb_aggregate = src->mac_stats.dl.used_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.total_prb_aggregate = src->mac_stats.ul.total_prb_aggregate,
.mac_stats.ul.used_prb_aggregate = src->mac_stats.ul.used_prb_aggregate, .mac_stats.ul.used_prb_aggregate = src->mac_stats.ul.used_prb_aggregate,
.rrc_conn_count_sum = src->rrc_conn_count_sum,
.rrc_conn_count_samples = src->rrc_conn_count_samples,
}; };
return dst; return dst;
...@@ -160,6 +162,35 @@ static meas_record_lst_t fill_MR_NRScSSSINR(const label_info_lst_t label, ...@@ -160,6 +162,35 @@ static meas_record_lst_t fill_MR_NRScSSSINR(const label_info_lst_t label,
return meas_record; return meas_record;
} }
/* RRC.ConnMean — 3GPP TS 28.552 - section 5.1.1.4.1 */
static meas_record_lst_t fill_RRC_ConnMean(__attribute__((unused)) const label_info_lst_t label,
__attribute__((unused)) uint32_t gran_period_ms,
__attribute__((unused)) cudu_ue_info_pair_t ue_info,
__attribute__((unused)) const size_t ue_idx,
e2_node_level_stats_t* node_stats)
{
meas_record_lst_t meas_record = {.value = INTEGER_MEAS_VALUE};
node_stats[1].rrc_conn_count_sum = RC.nrrrc[0]->rrc_conn_count_sum;
node_stats[1].rrc_conn_count_samples = RC.nrrrc[0]->rrc_conn_count_samples;
const uint64_t d_sum = node_stats[1].rrc_conn_count_sum - node_stats[0].rrc_conn_count_sum;
const uint64_t d_samples = node_stats[1].rrc_conn_count_samples - node_stats[0].rrc_conn_count_samples;
if (d_samples > 0) {
meas_record.int_val = (long)((d_sum + d_samples / 2) / d_samples);
node_stats[0].rrc_conn_count_sum = node_stats[1].rrc_conn_count_sum;
node_stats[0].rrc_conn_count_samples = node_stats[1].rrc_conn_count_samples;
} else if (node_stats[1].rrc_conn_count_samples > 0) {
meas_record.int_val = (long)((node_stats[1].rrc_conn_count_sum + node_stats[1].rrc_conn_count_samples / 2)
/ node_stats[1].rrc_conn_count_samples);
} else {
meas_record.int_val = 0;
}
return meas_record;
}
#if defined (NGRAN_GNB_DU) #if defined (NGRAN_GNB_DU)
static uldlcounter_t last_rlc_pdu_total_bytes[MAX_MOBILES_PER_GNB] = {0}; static uldlcounter_t last_rlc_pdu_total_bytes[MAX_MOBILES_PER_GNB] = {0};
static uldlcounter_t last_total_prbs[MAX_MOBILES_PER_GNB] = {0}; static uldlcounter_t last_total_prbs[MAX_MOBILES_PER_GNB] = {0};
...@@ -359,6 +390,7 @@ static kv_measure_t lst_measure[] = { ...@@ -359,6 +390,7 @@ static kv_measure_t lst_measure[] = {
{.key = "DRB.PdcpSduVolumeUL", .value = fill_DRB_PdcpSduVolumeUL }, {.key = "DRB.PdcpSduVolumeUL", .value = fill_DRB_PdcpSduVolumeUL },
{.key = "L1M.SS-RSRP", .value = fill_L1M_SS_RSRP }, {.key = "L1M.SS-RSRP", .value = fill_L1M_SS_RSRP },
{.key = "MR.NRScSSSINR", .value = fill_MR_NRScSSSINR }, {.key = "MR.NRScSSSINR", .value = fill_MR_NRScSSSINR },
{.key = "RRC.ConnMean", .value = fill_RRC_ConnMean },
#if defined (NGRAN_GNB_DU) #if defined (NGRAN_GNB_DU)
{.key = "DRB.RlcSduDelayDl", .value = fill_DRB_RlcSduDelayDl }, {.key = "DRB.RlcSduDelayDl", .value = fill_DRB_RlcSduDelayDl },
{.key = "DRB.UEThpDl", .value = fill_DRB_UEThpDl }, {.key = "DRB.UEThpDl", .value = fill_DRB_UEThpDl },
......
...@@ -19,6 +19,9 @@ typedef struct { ...@@ -19,6 +19,9 @@ typedef struct {
typedef struct { typedef struct {
dlul_mac_stats_t mac_stats; dlul_mac_stats_t mac_stats;
uint64_t rrc_conn_count_sum;
uint64_t rrc_conn_count_samples;
} e2_node_level_stats_t; } e2_node_level_stats_t;
e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src); e2_node_level_stats_t cp_node_level_stats(const e2_node_level_stats_t *src);
......
...@@ -105,6 +105,7 @@ From 3GPP TS 28.552, we support the following list: ...@@ -105,6 +105,7 @@ From 3GPP TS 28.552, we support the following list:
* `CARR.PUSCHMCSDist` * `CARR.PUSCHMCSDist`
* `L1M.SS-RSRP` * `L1M.SS-RSRP`
* `MR.NRScSSSINR` * `MR.NRScSSSINR`
* `RRC.ConnMean`
From `O-RAN.WG3.E2SM-KPM-version` specification, we implemented: From `O-RAN.WG3.E2SM-KPM-version` specification, we implemented:
* REPORT Service Style 4 ("Common condition-based, UE-level" - section 7.4.5) - fetch above measurements per each UE based on the common S-NSSAI `(1, 0xffffff)` condition * REPORT Service Style 4 ("Common condition-based, UE-level" - section 7.4.5) - fetch above measurements per each UE based on the common S-NSSAI `(1, 0xffffff)` condition
......
...@@ -652,6 +652,9 @@ typedef struct gNB_RRC_INST_s { ...@@ -652,6 +652,9 @@ typedef struct gNB_RRC_INST_s {
/// cell-wide NR serving-cell SS-SINR distribution, see 28.552 5.1.1.32 /// cell-wide NR serving-cell SS-SINR distribution, see 28.552 5.1.1.32
/// 0-127 SS-SINR report level (TS 38.133) /// 0-127 SS-SINR report level (TS 38.133)
uint32_t ss_sinr_cell_dist[NR_KPM_SS_SINR_NB_LEVELS]; uint32_t ss_sinr_cell_dist[NR_KPM_SS_SINR_NB_LEVELS];
uint64_t rrc_conn_count_sum;
uint64_t rrc_conn_count_samples;
} gNB_RRC_INST; } gNB_RRC_INST;
/** Forward declaration for UE log macros */ /** Forward declaration for UE log macros */
......
...@@ -3514,6 +3514,18 @@ static bool write_rrc_stats(const gNB_RRC_INST *rrc) ...@@ -3514,6 +3514,18 @@ static bool write_rrc_stats(const gNB_RRC_INST *rrc)
return true; return true;
} }
static void nr_rrc_sample_conn_count(gNB_RRC_INST *rrc)
{
if (rrc == NULL)
return;
uint32_t count = 0;
rrc_gNB_ue_context_t *ue_context_p = NULL;
RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc->rrc_ue_head)
count++;
rrc->rrc_conn_count_sum += count;
rrc->rrc_conn_count_samples += 1;
}
void *rrc_gnb_task(void *args_p) void *rrc_gnb_task(void *args_p)
{ {
UNUSED(args_p); UNUSED(args_p);
...@@ -3553,6 +3565,7 @@ void *rrc_gnb_task(void *args_p) ...@@ -3553,6 +3565,7 @@ void *rrc_gnb_task(void *args_p)
case TIMER_HAS_EXPIRED: case TIMER_HAS_EXPIRED:
if (TIMER_HAS_EXPIRED(msg_p).timer_id == stats_timer_id) { if (TIMER_HAS_EXPIRED(msg_p).timer_id == stats_timer_id) {
nr_rrc_sample_conn_count(RC.nrrrc[0]);
if (!write_rrc_stats(RC.nrrrc[0])) if (!write_rrc_stats(RC.nrrrc[0]))
timer_remove(stats_timer_id); timer_remove(stats_timer_id);
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment