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..a8ebe580ab 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}; @@ -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}; @@ -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