From b3028fdd18dab84c827cd3e3696207cc942e9cf1 Mon Sep 17 00:00:00 2001 From: fatich Date: Fri, 5 Dec 2025 11:28:32 +0100 Subject: [PATCH] Implement E2SM-KPM REPORT style 1 containing "CARR.PDSCHMCSDist" measurement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Teodora Vladić --- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 45 +++++++++++++++++-- .../RAN_FUNCTION/O-RAN/ran_func_kpm_subs.c | 24 ++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) 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 fc37665d19..602464de1f 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -440,6 +440,15 @@ bool read_kpm_sm(void* data) } break; } + case FORMAT_1_ACTION_DEFINITION: { + kpm->ind.hdr = kpm_ind_hdr(); + + kpm->ind.msg.type = FORMAT_1_INDICATION_MESSAGE; + cudu_ue_info_pair_t ue_info = {0}; // not used + const size_t ue_idx = 0; // not used + kpm->ind.msg.frm_1 = fill_kpm_ind_msg_frm_1(ue_info, ue_idx, &kpm->act_def->frm_1); + break; + } default: { AssertFatal(false, "Action Definition Format %d not yet implemented", kpm->act_def->type); @@ -449,6 +458,16 @@ bool read_kpm_sm(void* data) return true; } +static const char* kpm_node_meas_du[] = { + "CARR.PDSCHMCSDist", + NULL, +}; + +static const char* kpm_node_meas_gnb[] = { + "CARR.PDSCHMCSDist", + NULL, +}; + static const char* kpm_meas_du[] = { "DRB.RlcSduDelayDl", "DRB.UEThpDl", @@ -480,12 +499,12 @@ typedef const char** meas_list; static const meas_list ran_def_kpm[END_NGRAN_NODE_TYPE][END_RIC_SERVICE_REPORT] = { {NULL, NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL}, - {NULL, NULL, NULL, kpm_meas_gnb, NULL}, + {kpm_node_meas_gnb, NULL, NULL, kpm_meas_gnb, NULL}, {NULL, NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, kpm_meas_cuup, NULL}, // at the moment, for CU, we use the same function as for CU-UP {NULL, NULL, NULL, NULL, NULL}, - {NULL, NULL, NULL, kpm_meas_du, NULL}, + {kpm_node_meas_du, NULL, NULL, kpm_meas_du, NULL}, {NULL, NULL, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL}, // at the moment, no measurement is implemented in CU-CP {NULL, NULL, NULL, kpm_meas_cuup, NULL} @@ -518,6 +537,26 @@ static meas_info_for_action_lst_t* fill_meas_info_list_for_act(const ngran_node_ return info_lst; } +static ric_report_style_item_t fill_kpm_def_report_style_1(const ngran_node_t node_type) +{ + ric_report_style_item_t report_item = {0}; + + report_item.meas_info_for_action_lst = fill_meas_info_list_for_act(node_type, STYLE_1_RIC_SERVICE_REPORT, &report_item.meas_info_for_action_lst_len); + if (report_item.meas_info_for_action_lst == NULL) + return report_item; + + report_item.report_style_type = STYLE_1_RIC_SERVICE_REPORT; + const char report_style_name[] = "E2 Node Measurement"; + report_item.report_style_name = cp_str_to_ba(report_style_name); + report_item.act_def_format_type = FORMAT_1_ACTION_DEFINITION; + + // Supported RIC Indication Formats + report_item.ind_hdr_format_type = FORMAT_1_INDICATION_HEADER; // 8.3.5 + report_item.ind_msg_format_type = FORMAT_1_INDICATION_MESSAGE; // 8.3.5 + + return report_item; +} + static ric_report_style_item_t fill_kpm_def_report_style_4(const ngran_node_t node_type) { ric_report_style_item_t report_item = {0}; @@ -548,7 +587,7 @@ static ric_report_style_item_t fill_kpm_def_report_style_null(const ngran_node_t typedef ric_report_style_item_t (*kpm_report_style)(const ngran_node_t node_type); static kpm_report_style report_style[END_RIC_SERVICE_REPORT] = { - fill_kpm_def_report_style_null, + fill_kpm_def_report_style_1, fill_kpm_def_report_style_null, fill_kpm_def_report_style_null, fill_kpm_def_report_style_4, 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 429b012298..22cb45a71a 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 @@ -226,6 +226,29 @@ static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused)) const label_i return meas_record; } + +/* 3GPP TS 28.552 - section 5.1.1.12.1*/ +static meas_record_lst_t fill_CARR_PDSCHMCSDist(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, + __attribute__((unused))e2_node_level_stats_t* node_stats) +{ + meas_record_lst_t meas_record = {.value = INTEGER_MEAS_VALUE}; + + uint32_t bin_x = *label.distBinX, bin_y = *label.distBinY, bin_z = *label.distBinZ; + + NR_du_stats_t* du_stats = &RC.nrmac[0]->du_stats; + + if (bin_x <= 8 && bin_y <= 3 && bin_z <= 31) { + meas_record.int_val = du_stats->pdsch_mcs_dist[bin_x - 1][bin_y - 1][bin_z]; + } else { + printf("[E2 AGENT] Unknown binX %d, binY %d, binZ %d for \"CARR.PDSCHMCSDist\" measurement\n", bin_x, bin_y, bin_z); + meas_record.int_val = 0; + } + + return meas_record; +} #endif static kv_measure_t lst_measure[] = { @@ -237,6 +260,7 @@ static kv_measure_t lst_measure[] = { {.key = "DRB.UEThpUl", .value = fill_DRB_UEThpUl }, {.key = "RRU.PrbTotDl", .value = fill_RRU_PrbTotDl }, {.key = "RRU.PrbTotUl", .value = fill_RRU_PrbTotUl }, + {.key = "CARR.PDSCHMCSDist", .value = fill_CARR_PDSCHMCSDist }, #endif };