Compare commits

...

4 Commits

Author SHA1 Message Date
fatich
89f89d43b4 fix: Add type cast for E2 agent IP init 2025-08-29 15:09:40 +02:00
fatich
770a56f90e feat(kpm): Add CARR.PDSCHMCSDist measurement 2025-08-29 15:03:35 +02:00
fatich
a1ab90176b refactor(kpm): Pass action definition to measurement functions 2025-08-29 11:59:18 +02:00
fatich
a850bdd4f5 Add statistics for CQI and MCS distribution 2025-08-29 11:56:05 +02:00
9 changed files with 114 additions and 29 deletions

View File

@@ -52,7 +52,7 @@ 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);
fr_args_t args = { .ip = (char*)oai_args.ip }; // init_fr_args(0, NULL);
memcpy(args.libs_dir, oai_args.sm_dir, 128);
sleep(1);

View File

@@ -527,7 +527,7 @@ 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);
fr_args_t args = { .ip = (char*)oai_args.ip }; // init_fr_args(0, NULL);
memcpy(args.libs_dir, oai_args.sm_dir, 128);
sleep(1);

View File

@@ -57,25 +57,21 @@ typedef struct {
NR_UE_info_t** ue_info_list;
}arr_ue_id_t;
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)
static meas_data_lst_t fill_kpm_meas_data_item(const kpm_act_def_format_1_t* act_def_fr_1, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
assert(act_def_fr_1 != NULL);
const size_t len = act_def_fr_1->meas_info_lst_len;
meas_data_lst_t data_item = {0};
// Measurement Record
data_item.meas_record_len = len; // record data list length corresponds to info list length from action definition
data_item.meas_record_len = len; // record data list length corresponds to info list length from action definition
data_item.meas_record_lst = calloc(len, sizeof(meas_record_lst_t));
assert(data_item.meas_record_lst != NULL && "Memory exhausted");
for (size_t i = 0; i < len; i++) {
// Measurement Type as requested in Action Definition
assert(meas_info_lst[i].meas_type.type == NAME_MEAS_TYPE && "Only NAME supported");
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);
free(meas_info_name_str);
data_item.meas_record_lst[i] = get_kpm_meas_value(act_def_fr_1, i, ue_info, ue_idx);
}
return data_item;
@@ -92,9 +88,7 @@ static kpm_ind_msg_format_1_t fill_kpm_ind_msg_frm_1(cudu_ue_info_pair_t ue_info
msg_frm_1.meas_data_lst = calloc(msg_frm_1.meas_data_lst_len, sizeof(*msg_frm_1.meas_data_lst));
assert(msg_frm_1.meas_data_lst != NULL && "Memory exhausted" );
msg_frm_1.meas_data_lst[0] = fill_kpm_meas_data_item(act_def_fr_1->meas_info_lst,
act_def_fr_1->meas_info_lst_len,
act_def_fr_1->gran_period_ms,
msg_frm_1.meas_data_lst[0] = fill_kpm_meas_data_item(act_def_fr_1,
ue_info,
ue_idx);
@@ -438,6 +432,7 @@ static const char* kpm_meas_du[] = {
"DRB.UEThpUl",
"RRU.PrbTotDl",
"RRU.PrbTotUl",
"CARR.PDSCHMCSDist",
NULL,
};
@@ -449,6 +444,7 @@ static const char* kpm_meas_gnb[] = {
"DRB.UEThpUl",
"RRU.PrbTotDl",
"RRU.PrbTotUl",
"CARR.PDSCHMCSDist",
NULL,
};

View File

@@ -46,7 +46,10 @@ 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))const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -65,7 +68,10 @@ 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))const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -103,7 +109,10 @@ 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))const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
__attribute__((unused))const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -122,7 +131,10 @@ 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(const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -132,7 +144,7 @@ static meas_record_lst_t fill_DRB_UEThpDl(uint32_t gran_period_ms, cudu_ue_info_
meas_record.value = REAL_MEAS_VALUE;
// Calculate DL Thp
meas_record.real_val = (double)(rlc.txpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].dl)*8/gran_period_ms; // [kbps]
meas_record.real_val = (double)(rlc.txpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].dl)*8/act_def->gran_period_ms; // [kbps]
last_rlc_pdu_total_bytes[ue_idx].dl = rlc.txpdu_bytes;
return meas_record;
@@ -141,7 +153,10 @@ 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(const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -152,7 +167,7 @@ static meas_record_lst_t fill_DRB_UEThpUl(uint32_t gran_period_ms, cudu_ue_info_
meas_record.value = REAL_MEAS_VALUE;
// Calculate UL Thp
meas_record.real_val = (double)(rlc.rxpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].ul)*8/gran_period_ms; // [kbps]
meas_record.real_val = (double)(rlc.rxpdu_bytes - last_rlc_pdu_total_bytes[ue_idx].ul)*8/act_def->gran_period_ms; // [kbps]
last_rlc_pdu_total_bytes[ue_idx].ul = rlc.rxpdu_bytes;
return meas_record;
@@ -161,7 +176,10 @@ 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)
static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -177,7 +195,10 @@ static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_
/* 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)
static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))const kpm_act_def_format_1_t* act_def,
__attribute__((unused))const size_t meas_info_idx,
cudu_ue_info_pair_t ue_info,
const size_t ue_idx)
{
meas_record_lst_t meas_record = {0};
@@ -189,6 +210,34 @@ static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_
return meas_record;
}
/* 3GPP TS 28.552 - section 5.1.1.12.1*/
static meas_record_lst_t fill_CARR_PDSCHMCSDist(const kpm_act_def_format_1_t* act_def,
const size_t meas_info_idx,
__attribute__((unused)) cudu_ue_info_pair_t ue_info,
__attribute__((unused)) const size_t ue_idx)
{
const meas_info_format_1_lst_t* meas_info = &act_def->meas_info_lst[meas_info_idx];
meas_record_lst_t meas_record = {.value = INTEGER_MEAS_VALUE};
uint32_t bin_x = 0, bin_y = 0, bin_z = 0;
if (meas_info->label_info_lst_len > 0) {
const label_info_lst_t* label = &meas_info->label_info_lst[0];
if (label->distBinX) bin_x = *label->distBinX;
if (label->distBinY) bin_y = *label->distBinY;
if (label->distBinZ) bin_z = *label->distBinZ;
}
NR_du_stats_t* du_stats = &RC.nrmac[0]->du_stats;
if (bin_x < 8 && bin_y < 4 && bin_z < 32) {
meas_record.int_val = du_stats->pdsch_mcs_dist[bin_x][bin_y][bin_z];
} else {
meas_record.int_val = 0;
}
return meas_record;
}
#endif
static kv_measure_t lst_measure[] = {
@@ -200,6 +249,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
};
@@ -217,16 +267,19 @@ 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(const kpm_act_def_format_1_t* act_def, const size_t meas_info_idx, cudu_ue_info_pair_t ue_info, const size_t ue_idx)
{
assert(kpm_meas_name != NULL);
const meas_info_format_1_lst_t* meas_info = &act_def->meas_info_lst[meas_info_idx];
assert(meas_info->meas_type.type == NAME_MEAS_TYPE && "Only NAME supported");
char* kpm_meas_name = cp_ba_to_str(meas_info->meas_type.name);
ENTRY search_entry = {.key = kpm_meas_name};
ENTRY *found_entry = hsearch(search_entry, FIND);
assert(found_entry != NULL && "Unsupported KPM measurement name");
free(kpm_meas_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(act_def, meas_info_idx, ue_info, ue_idx);
return meas_record;
}

View File

@@ -34,7 +34,7 @@ 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 meas_record_lst_t (*kpm_meas_fp)(const kpm_act_def_format_1_t* act_def, const size_t meas_info_idx, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
typedef struct{
char* key;
@@ -44,6 +44,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(const kpm_act_def_format_1_t* act_def, const size_t meas_info_idx, cudu_ue_info_pair_t ue_info, const size_t ue_idx);
#endif

View File

@@ -1379,6 +1379,12 @@ void nr_schedule_ue_spec(module_id_t module_id,
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, TBS));
}
DevAssert(nrOfLayers >= 1 && nrOfLayers <= 8);
DevAssert(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 3);
DevAssert(sched_pdsch->mcs >= 0 && sched_pdsch->mcs <= 31);
NR_du_stats_t *stats = &gNB_mac->du_stats;
stats->pdsch_mcs_dist[nrOfLayers - 1][current_BWP->mcsTableIdx][sched_pdsch->mcs] += sched_pdsch->rbSize;
const int ntx_req = TX_req->Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
tx_req->PDU_index = pduindex;

View File

@@ -632,6 +632,12 @@ static void evaluate_cqi_report(uint8_t *payload,
uint8_t temp_cqi = pickandreverse_bits(payload, 4, cumul_bits);
DevAssert(temp_cqi >= 0 && temp_cqi <= 15); // binX: value is 0-indexed, so it uses temp_cqi below
DevAssert(ri >= 0 && ri <= 7); // binY: value is 0-indexed, so it used ri below
DevAssert(cqi_Table >= 0 && cqi_Table <= 2); // binZ: value is 0-indexed, so it uses cqi_Table below
NR_du_stats_t *stats = &RC.nrmac[0]->du_stats;
stats->wb_cqi_dist[temp_cqi][ri][cqi_Table] += 1;
// NR_CSI_ReportConfig__cqi_Table_table1 = 0
// NR_CSI_ReportConfig__cqi_Table_table2 = 1
// NR_CSI_ReportConfig__cqi_Table_table3 = 2

View File

@@ -2557,6 +2557,12 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
sched_ctrl->sched_ul_bytes,
sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes,
sched_ctrl->tpc0);
DevAssert(sched_pusch->nrOfLayers >= 1 && sched_pusch->nrOfLayers <= 8);
DevAssert(current_BWP->mcs_table >= 0 && current_BWP->mcs_table <= 1);
DevAssert(sched_pusch->mcs >= 0 && sched_pusch->mcs <= 31);
NR_du_stats_t *stats = &nr_mac->du_stats;
stats->pusch_mcs_dist[sched_pusch->nrOfLayers - 1][current_BWP->mcs_table][sched_pusch->mcs] += sched_pusch->rbSize;
/* PUSCH in a later slot, but corresponding DCI now! */
const int index = ul_buffer_index(sched_pusch->frame,

View File

@@ -802,6 +802,21 @@ typedef struct {
uint64_t used_prb_aggregate;
} mac_stats_t;
typedef struct NR_du_stats {
/// cell-wide wide-band CQI distribution, see 28.552 5.1.1.11.1;
/// 0-15 CQI, 1-8 RI, 1-3 CQI table
uint32_t wb_cqi_dist[16][8][3];
/// cell-wide MCS distribution in PDSCH, see 28.552 5.1.1.12.1
/// 1-8 RI, 1-4 MCS table, 0-31 MCS value
uint32_t pdsch_mcs_dist[8][4][32];
/// cell-wide MCS distribution in PUSCH, see 28.552 5.1.1.12.1
/// 1-8 RI, 1-2 MCS table, 0-31 MCS value
uint32_t pusch_mcs_dist[8][2][32];
} NR_du_stats_t;
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -911,6 +926,9 @@ typedef struct gNB_MAC_INST_s {
mac_stats_t mac_stats;
uint64_t num_scheduled_prach_rx;
NR_du_stats_t du_stats;
} gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */