Merge remote-tracking branch 'origin/grafana-dist-channel_quality' into integration_2026_w13 (!3805)
[E2 agent] Refactor E2SM-KPM and implement support for REPORT style 1
- Refactor E2SM-KPM to:
- better handle different supported REPORT styles needed for "E2 Setup
Request"
- pass "Measurement Label" for calculating the measurement values
- Implement Subscription for E2SM-KPM REPORT style 1 and fill the PDSCH MCS
distribution measurement (CARR.PDSCHMCSDist)
- Fix the memory leakage caused by the UEs filtering based on NSSAI for REPORT
style 4
Tested successfully with and without ASan:
- in rfsim mode: gNB-mono, CU/DU and CU-CP/CU-UP/DU
- with the USRP B210: gNB-mono
and xapp_kpm_moni, xapp_rc_moni and xapp_kpm_rc xApps.
This commit is contained in:
@@ -53,7 +53,7 @@ add_library(e2_ran_func_cuup STATIC
|
|||||||
../flexric/test/rnd/fill_rnd_data_tc.c
|
../flexric/test/rnd/fill_rnd_data_tc.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds alg sm_common_enc_asn_obj_rc 3gpp_derived_ie_enc_asn_obj_rc)
|
target_link_libraries(e2_ran_func_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj kpm_ric_info_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds alg sm_common_enc_asn_obj_rc 3gpp_derived_ie_enc_asn_obj_rc)
|
||||||
target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP)
|
target_compile_definitions(e2_ran_func_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_CUUP)
|
||||||
|
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ add_library(e2_ran_func_du_cucp_cuup STATIC
|
|||||||
../flexric/test/rnd/fill_rnd_data_tc.c
|
../flexric/test/rnd/fill_rnd_data_tc.c
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds sm_common_enc_asn_obj_rc 3gpp_derived_ie_enc_asn_obj_rc)
|
target_link_libraries(e2_ran_func_du_cucp_cuup PUBLIC asn1_nr_rrc nr_rrc asn1_nr_rrc_hdrs e2_time_obj kpm_ric_info_common_obj kpm_ric_info_obj 3gpp_derived_ie_obj e2sm_rc_ir_obj sm_common_ie_obj ds sm_common_enc_asn_obj_rc 3gpp_derived_ie_enc_asn_obj_rc)
|
||||||
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
|
target_compile_definitions(e2_ran_func_du_cucp_cuup PUBLIC ${E2AP_VERSION} ${KPM_VERSION} NGRAN_GNB_DU NGRAN_GNB_CUCP NGRAN_GNB_CUUP)
|
||||||
|
|
||||||
# Current implementation:
|
# Current implementation:
|
||||||
|
|||||||
@@ -51,13 +51,20 @@ static ngran_node_t get_e2_node_type(void)
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t sz;
|
size_t sz;
|
||||||
ue_id_e2sm_t* ue_id;
|
ue_id_e2sm_t ue_id[MAX_MOBILES_PER_GNB];
|
||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
// only used to retrieve MAC/RLC stats
|
// only used to retrieve MAC/RLC stats
|
||||||
NR_UE_info_t** ue_info_list;
|
NR_UE_info_t* ue_info_list[MAX_MOBILES_PER_GNB];
|
||||||
}arr_ue_id_t;
|
}arr_ue_id_t;
|
||||||
|
|
||||||
|
static void free_arr_ue_id(arr_ue_id_t arr_ue_id)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < arr_ue_id.sz; i++) {
|
||||||
|
free_ue_id_e2sm(&arr_ue_id.ue_id[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static e2_node_level_stats_t node_stats[2] = {0}; // [0] node stats collected in previous reporting period; [1] current node stats
|
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)
|
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)
|
||||||
@@ -65,19 +72,25 @@ static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* m
|
|||||||
meas_data_lst_t data_item = {0};
|
meas_data_lst_t data_item = {0};
|
||||||
|
|
||||||
// Measurement Record
|
// Measurement Record
|
||||||
data_item.meas_record_len = len; // record data list length corresponds to info list length from action definition
|
size_t num_records = 0;
|
||||||
|
|
||||||
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++) {
|
for (size_t i = 0; i < len; i++) {
|
||||||
// Measurement Type as requested in Action Definition
|
// Measurement Type as requested in Action Definition
|
||||||
assert(meas_info_lst[i].meas_type.type == NAME_MEAS_TYPE && "Only NAME supported");
|
assert(meas_info_lst[i].meas_type.type == NAME_MEAS_TYPE && "Only NAME supported");
|
||||||
|
|
||||||
|
num_records += meas_info_lst[i].label_info_lst_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_item.meas_record_len = num_records;
|
||||||
|
data_item.meas_record_lst = calloc(num_records, sizeof(*data_item.meas_record_lst));
|
||||||
|
assert(data_item.meas_record_lst != NULL && "Memory exhausted");
|
||||||
|
|
||||||
|
num_records = 0;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
char* meas_info_name_str = cp_ba_to_str(meas_info_lst[i].meas_type.name);
|
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, node_stats);
|
for (size_t j = 0; j < meas_info_lst[i].label_info_lst_len; j++) {
|
||||||
|
data_item.meas_record_lst[num_records++] = get_kpm_meas_value(meas_info_name_str, meas_info_lst[i].label_info_lst[j], gran_period_ms, ue_info, ue_idx, node_stats);
|
||||||
|
}
|
||||||
free(meas_info_name_str);
|
free(meas_info_name_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,9 +131,7 @@ static cudu_ue_info_pair_t fill_ue_related_info(arr_ue_id_t* arr_ue_id, const si
|
|||||||
|
|
||||||
if (arr_ue_id->ue_id[ue_idx].type == GNB_UE_ID_E2SM) {
|
if (arr_ue_id->ue_id[ue_idx].type == GNB_UE_ID_E2SM) {
|
||||||
ue_info.rrc_ue_id = *arr_ue_id->ue_id[ue_idx].gnb.ran_ue_id; // rrc_ue_id
|
ue_info.rrc_ue_id = *arr_ue_id->ue_id[ue_idx].gnb.ran_ue_id; // rrc_ue_id
|
||||||
if (arr_ue_id->ue_info_list != NULL) {
|
ue_info.ue = arr_ue_id->ue_info_list[ue_idx];
|
||||||
ue_info.ue = arr_ue_id->ue_info_list[ue_idx];
|
|
||||||
}
|
|
||||||
} else if (arr_ue_id->ue_id[ue_idx].type == GNB_CU_UP_UE_ID_E2SM) {
|
} else if (arr_ue_id->ue_id[ue_idx].type == GNB_CU_UP_UE_ID_E2SM) {
|
||||||
/* in OAI implementation, CU-UP ue id = CU-CP ue id
|
/* in OAI implementation, CU-UP ue id = CU-CP ue id
|
||||||
=> CU-UP ue id = rrc_ue_id, but it should not be the case by the spec */
|
=> CU-UP ue id = rrc_ue_id, but it should not be the case by the spec */
|
||||||
@@ -208,8 +219,6 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info)
|
|||||||
capture_sst_sd(test_info.test_cond_value, &sst, &sd);
|
capture_sst_sd(test_info.test_cond_value, &sst, &sd);
|
||||||
|
|
||||||
arr_ue_id_t arr_ue_id = {.sz = 0};
|
arr_ue_id_t arr_ue_id = {.sz = 0};
|
||||||
arr_ue_id.ue_id = calloc(MAX_MOBILES_PER_GNB, sizeof(ue_id_e2sm_t));
|
|
||||||
assert(arr_ue_id.ue_id != NULL);
|
|
||||||
|
|
||||||
struct rrc_gNB_ue_context_s* rrc_ue_context = NULL;
|
struct rrc_gNB_ue_context_s* rrc_ue_context = NULL;
|
||||||
RB_FOREACH(rrc_ue_context, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) {
|
RB_FOREACH(rrc_ue_context, rrc_nr_ue_tree_s, &RC.nrrrc[0]->rrc_ue_head) {
|
||||||
@@ -246,8 +255,6 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cuup(const test_info_lst_t test_info
|
|||||||
capture_sst_sd(test_info.test_cond_value, &sst, &sd);
|
capture_sst_sd(test_info.test_cond_value, &sst, &sd);
|
||||||
|
|
||||||
arr_ue_id_t arr_ue_id = {.sz = 0};
|
arr_ue_id_t arr_ue_id = {.sz = 0};
|
||||||
arr_ue_id.ue_id = calloc(MAX_MOBILES_PER_GNB, sizeof(ue_id_e2sm_t));
|
|
||||||
assert(arr_ue_id.ue_id != NULL);
|
|
||||||
|
|
||||||
// Get NSSAI info from E1 context
|
// Get NSSAI info from E1 context
|
||||||
const instance_t e1_inst = 0;
|
const instance_t e1_inst = 0;
|
||||||
@@ -284,11 +291,6 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst
|
|||||||
capture_sst_sd(test_info.test_cond_value, &sst, &sd);
|
capture_sst_sd(test_info.test_cond_value, &sst, &sd);
|
||||||
|
|
||||||
arr_ue_id_t arr_ue_id = {.sz = 0};
|
arr_ue_id_t arr_ue_id = {.sz = 0};
|
||||||
arr_ue_id.ue_id = calloc(MAX_MOBILES_PER_GNB, sizeof(ue_id_e2sm_t));
|
|
||||||
assert(arr_ue_id.ue_id != NULL);
|
|
||||||
|
|
||||||
arr_ue_id.ue_info_list = calloc(MAX_MOBILES_PER_GNB, sizeof(*arr_ue_id.ue_info_list));
|
|
||||||
assert(arr_ue_id.ue_info_list != NULL);
|
|
||||||
|
|
||||||
const ngran_node_t node_type = get_e2_node_type();
|
const ngran_node_t node_type = get_e2_node_type();
|
||||||
|
|
||||||
@@ -431,18 +433,38 @@ bool read_kpm_sm(void* data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3(&arr_ue_id, &frm_4->action_def_format_1);
|
kpm->ind.msg.frm_3 = fill_kpm_ind_msg_frm_3(&arr_ue_id, &frm_4->action_def_format_1);
|
||||||
|
free_arr_ue_id(arr_ue_id);
|
||||||
}
|
}
|
||||||
break;
|
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: {
|
default: {
|
||||||
AssertFatal(kpm->act_def->type == FORMAT_4_ACTION_DEFINITION, "Action Definition Format %d not yet implemented", kpm->act_def->type);
|
AssertFatal(false, "Action Definition Format %d not yet implemented", kpm->act_def->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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[] = {
|
static const char* kpm_meas_du[] = {
|
||||||
"DRB.RlcSduDelayDl",
|
"DRB.RlcSduDelayDl",
|
||||||
"DRB.UEThpDl",
|
"DRB.UEThpDl",
|
||||||
@@ -471,18 +493,102 @@ static const char* kpm_meas_cuup[] = {
|
|||||||
|
|
||||||
typedef const char** meas_list;
|
typedef const char** meas_list;
|
||||||
|
|
||||||
static const meas_list ran_def_kpm[END_NGRAN_NODE_TYPE] = {
|
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},
|
||||||
kpm_meas_gnb,
|
{kpm_node_meas_gnb, NULL, NULL, kpm_meas_gnb, NULL},
|
||||||
NULL,
|
{NULL, NULL, NULL, NULL, NULL},
|
||||||
NULL,
|
{NULL, NULL, NULL, NULL, NULL},
|
||||||
kpm_meas_cuup, // at the moment, for CU, we use the same function as for CU-UP
|
{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},
|
||||||
kpm_meas_du,
|
{kpm_node_meas_du, NULL, NULL, kpm_meas_du, NULL},
|
||||||
NULL,
|
{NULL, NULL, NULL, NULL, NULL},
|
||||||
NULL, // at the moment, no measurement is implemented in CU-CP
|
{NULL, NULL, NULL, NULL, NULL}, // at the moment, no measurement is implemented in CU-CP
|
||||||
kpm_meas_cuup,
|
{NULL, NULL, NULL, kpm_meas_cuup, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static meas_info_for_action_lst_t* fill_meas_info_list_for_act(const ngran_node_t node_type, const ric_service_report_e report_style, size_t *sz)
|
||||||
|
{
|
||||||
|
*sz = 0;
|
||||||
|
const char** kpm_meas = ran_def_kpm[node_type][report_style];
|
||||||
|
if (kpm_meas == NULL)
|
||||||
|
return NULL;
|
||||||
|
while (kpm_meas[*sz] != NULL) {
|
||||||
|
(*sz)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
meas_info_for_action_lst_t *info_lst = calloc(*sz, sizeof(meas_info_for_action_lst_t));
|
||||||
|
assert(info_lst != NULL && "Memory exhausted");
|
||||||
|
|
||||||
|
for(size_t i = 0; i < *sz; i++) {
|
||||||
|
// 8.3.9
|
||||||
|
info_lst[i].name = cp_str_to_ba(kpm_meas[i]);
|
||||||
|
|
||||||
|
// 8.3.10 - OPTIONAL
|
||||||
|
info_lst[i].id = NULL;
|
||||||
|
|
||||||
|
// 8.3.26 - OPTIONAL
|
||||||
|
info_lst[i].bin_range_def = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
||||||
|
report_item.meas_info_for_action_lst = fill_meas_info_list_for_act(node_type, STYLE_4_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_4_RIC_SERVICE_REPORT;
|
||||||
|
const char report_style_name[] = "Common Condition-based, UE-level Measurement";
|
||||||
|
report_item.report_style_name = cp_str_to_ba(report_style_name);
|
||||||
|
report_item.act_def_format_type = FORMAT_4_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_3_INDICATION_MESSAGE; // 8.3.5
|
||||||
|
|
||||||
|
return report_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ric_report_style_item_t fill_kpm_def_report_style_null(const ngran_node_t node_type)
|
||||||
|
{
|
||||||
|
(void)node_type;
|
||||||
|
ric_report_style_item_t report_item = {0};
|
||||||
|
return report_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_1,
|
||||||
|
fill_kpm_def_report_style_null,
|
||||||
|
fill_kpm_def_report_style_null,
|
||||||
|
fill_kpm_def_report_style_4,
|
||||||
|
fill_kpm_def_report_style_null
|
||||||
};
|
};
|
||||||
|
|
||||||
void read_kpm_setup_sm(void* e2ap)
|
void read_kpm_setup_sm(void* e2ap)
|
||||||
@@ -493,48 +599,25 @@ void read_kpm_setup_sm(void* e2ap)
|
|||||||
kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap);
|
kpm_e2_setup_t* kpm = (kpm_e2_setup_t*)(e2ap);
|
||||||
|
|
||||||
/* Fill the RAN Function Definition with currently supported measurements */
|
/* Fill the RAN Function Definition with currently supported measurements */
|
||||||
|
|
||||||
// RAN Function Name is already filled in fill_ran_function_name() in kpm_sm_agent.c
|
// RAN Function Name is already filled in fill_ran_function_name() in kpm_sm_agent.c
|
||||||
|
|
||||||
// Fill supported measurements depending on the E2 node
|
// Fill supported measurements depending on the E2 node
|
||||||
// [1, 65535]
|
// [1, 65535]
|
||||||
// 3GPP TS 28.552
|
// 3GPP TS 28.552
|
||||||
const ngran_node_t node_type = get_e2_node_type();
|
const ngran_node_t node_type = get_e2_node_type();
|
||||||
const char** kpm_meas = ran_def_kpm[node_type];
|
size_t num_styles = 0;
|
||||||
if (kpm_meas == NULL) return; // e.g. CU-CP node, doesn't support any measurements
|
for (size_t i = 0; i < END_RIC_SERVICE_REPORT; i++) {
|
||||||
size_t sz = 0;
|
ric_report_style_item_t report_item = report_style[i](node_type);
|
||||||
while (kpm_meas[sz] != NULL) {
|
if (report_item.meas_info_for_action_lst != NULL) {
|
||||||
sz++;
|
kpm->ran_func_def.ric_report_style_list = realloc(kpm->ran_func_def.ric_report_style_list, (num_styles + 1) * sizeof(*kpm->ran_func_def.ric_report_style_list));
|
||||||
|
kpm->ran_func_def.ric_report_style_list[num_styles++] = cp_ric_report_style_item(&report_item);
|
||||||
|
free_ric_report_style_item(&report_item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (kpm->ran_func_def.ric_report_style_list == NULL)
|
||||||
// Sequence of Report styles
|
return; // no measurements supported for this node
|
||||||
const size_t sz_report = 1;
|
kpm->ran_func_def.sz_ric_report_style_list = num_styles;
|
||||||
kpm->ran_func_def.sz_ric_report_style_list = sz_report;
|
|
||||||
kpm->ran_func_def.ric_report_style_list = calloc(sz_report, sizeof(ric_report_style_item_t));
|
|
||||||
assert(kpm->ran_func_def.ric_report_style_list != NULL && "Memory exhausted");
|
|
||||||
|
|
||||||
ric_report_style_item_t* report_item = &kpm->ran_func_def.ric_report_style_list[0];
|
|
||||||
|
|
||||||
report_item->report_style_type = STYLE_4_RIC_SERVICE_REPORT;
|
|
||||||
const char report_style_name[] = "Common Condition-based, UE-level Measurement";
|
|
||||||
report_item->report_style_name = cp_str_to_ba(report_style_name);
|
|
||||||
report_item->act_def_format_type = FORMAT_4_ACTION_DEFINITION;
|
|
||||||
|
|
||||||
report_item->meas_info_for_action_lst_len = sz;
|
|
||||||
report_item->meas_info_for_action_lst = calloc(sz, sizeof(meas_info_for_action_lst_t));
|
|
||||||
assert(report_item->meas_info_for_action_lst != NULL && "Memory exhausted");
|
|
||||||
|
|
||||||
for(size_t i = 0; i < sz; i++) {
|
|
||||||
meas_info_for_action_lst_t* meas_item = &report_item->meas_info_for_action_lst[i];
|
|
||||||
// 8.3.9
|
|
||||||
meas_item->name = cp_str_to_ba(kpm_meas[i]);
|
|
||||||
|
|
||||||
// 8.3.10 - OPTIONAL
|
|
||||||
meas_item->id = NULL;
|
|
||||||
|
|
||||||
// 8.3.26 - OPTIONAL
|
|
||||||
meas_item->bin_range_def = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sequence of Event Trigger styles
|
// Sequence of Event Trigger styles
|
||||||
const size_t sz_ev_tr = 1;
|
const size_t sz_ev_tr = 1;
|
||||||
@@ -549,10 +632,6 @@ void read_kpm_setup_sm(void* e2ap)
|
|||||||
ev_tr_item->style_name = cp_str_to_ba(ev_style_name);
|
ev_tr_item->style_name = cp_str_to_ba(ev_style_name);
|
||||||
ev_tr_item->format_type = FORMAT_1_RIC_EVENT_TRIGGER;
|
ev_tr_item->format_type = FORMAT_1_RIC_EVENT_TRIGGER;
|
||||||
|
|
||||||
// Supported RIC Indication Formats
|
|
||||||
report_item->ind_hdr_format_type = FORMAT_1_INDICATION_HEADER; // 8.3.5
|
|
||||||
report_item->ind_msg_format_type = FORMAT_3_INDICATION_MESSAGE; // 8.3.5
|
|
||||||
|
|
||||||
// E2 Setup Request is sent periodically until the connection is established
|
// E2 Setup Request is sent periodically until the connection is established
|
||||||
// RC subscritpion data should be initialized only once
|
// RC subscritpion data should be initialized only once
|
||||||
const int ret = pthread_once(&once_kpm_mutex, init_once_kpm);
|
const int ret = pthread_once(&once_kpm_mutex, init_once_kpm);
|
||||||
|
|||||||
@@ -58,7 +58,11 @@ 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
|
/* 3GPP TS 28.522 - section 5.1.2.1.1.1
|
||||||
note: this measurement is calculated as per spec */
|
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, __attribute__((unused))e2_node_level_stats_t* node_stats)
|
static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
__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};
|
meas_record_lst_t meas_record = {0};
|
||||||
|
|
||||||
@@ -77,7 +81,11 @@ static meas_record_lst_t fill_DRB_PdcpSduVolumeDL(__attribute__((unused))uint32_
|
|||||||
|
|
||||||
/* 3GPP TS 28.522 - section 5.1.2.1.2.1
|
/* 3GPP TS 28.522 - section 5.1.2.1.2.1
|
||||||
note: this measurement is calculated as per spec */
|
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, __attribute__((unused))e2_node_level_stats_t* node_stats)
|
static meas_record_lst_t fill_DRB_PdcpSduVolumeUL(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
__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};
|
meas_record_lst_t meas_record = {0};
|
||||||
|
|
||||||
@@ -115,7 +123,11 @@ 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
|
/* 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 */
|
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, __attribute__((unused))e2_node_level_stats_t* node_stats)
|
static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
__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};
|
meas_record_lst_t meas_record = {0};
|
||||||
|
|
||||||
@@ -134,11 +146,14 @@ static meas_record_lst_t fill_DRB_RlcSduDelayDl(__attribute__((unused))uint32_t
|
|||||||
/* 3GPP TS 28.522 - section 5.1.1.3.1
|
/* 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)
|
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 */
|
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, __attribute__((unused))e2_node_level_stats_t* node_stats)
|
static meas_record_lst_t fill_DRB_UEThpDl(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
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};
|
meas_record_lst_t meas_record = {0};
|
||||||
|
|
||||||
// Get RLC stats per DRB
|
|
||||||
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
const int rb_id = 1; // at the moment, only 1 DRB is supported
|
||||||
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
|
nr_rlc_statistics_t rlc = get_rlc_stats_per_drb(ue_info.ue->rnti, rb_id);
|
||||||
meas_record.value = REAL_MEAS_VALUE;
|
meas_record.value = REAL_MEAS_VALUE;
|
||||||
@@ -153,7 +168,11 @@ 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
|
/* 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)
|
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 */
|
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, __attribute__((unused))e2_node_level_stats_t* node_stats)
|
static meas_record_lst_t fill_DRB_UEThpUl(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
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};
|
meas_record_lst_t meas_record = {0};
|
||||||
|
|
||||||
@@ -172,7 +191,11 @@ 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
|
/* 3GPP TS 28.522 - section 5.1.1.2.1
|
||||||
note: this measurement is calculated as per spec */
|
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)
|
static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
__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_lst_t meas_record = {0};
|
||||||
|
|
||||||
@@ -187,7 +210,11 @@ static meas_record_lst_t fill_RRU_PrbTotDl(__attribute__((unused))uint32_t gran_
|
|||||||
|
|
||||||
/* 3GPP TS 28.522 - section 5.1.1.2.2
|
/* 3GPP TS 28.522 - section 5.1.1.2.2
|
||||||
note: this measurement is calculated as per spec */
|
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)
|
static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused)) const label_info_lst_t label,
|
||||||
|
__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_lst_t meas_record = {0};
|
||||||
|
|
||||||
@@ -199,6 +226,29 @@ static meas_record_lst_t fill_RRU_PrbTotUl(__attribute__((unused))uint32_t gran_
|
|||||||
|
|
||||||
return meas_record;
|
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
|
#endif
|
||||||
|
|
||||||
static kv_measure_t lst_measure[] = {
|
static kv_measure_t lst_measure[] = {
|
||||||
@@ -210,6 +260,7 @@ static kv_measure_t lst_measure[] = {
|
|||||||
{.key = "DRB.UEThpUl", .value = fill_DRB_UEThpUl },
|
{.key = "DRB.UEThpUl", .value = fill_DRB_UEThpUl },
|
||||||
{.key = "RRU.PrbTotDl", .value = fill_RRU_PrbTotDl },
|
{.key = "RRU.PrbTotDl", .value = fill_RRU_PrbTotDl },
|
||||||
{.key = "RRU.PrbTotUl", .value = fill_RRU_PrbTotUl },
|
{.key = "RRU.PrbTotUl", .value = fill_RRU_PrbTotUl },
|
||||||
|
{.key = "CARR.PDSCHMCSDist", .value = fill_CARR_PDSCHMCSDist },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -227,7 +278,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, e2_node_level_stats_t* node_stats)
|
meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, const label_info_lst_t label, 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);
|
assert(kpm_meas_name != NULL);
|
||||||
|
|
||||||
@@ -236,7 +287,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");
|
assert(found_entry != NULL && "Unsupported KPM measurement name");
|
||||||
|
|
||||||
kv_measure_t *kv_found = (kv_measure_t *)found_entry->data;
|
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, node_stats);
|
meas_record_lst_t meas_record = kv_found->value(label, gran_period_ms, ue_info, ue_idx, node_stats);
|
||||||
|
|
||||||
return meas_record;
|
return meas_record;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ typedef struct {
|
|||||||
|
|
||||||
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);
|
||||||
|
|
||||||
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 meas_record_lst_t (*kpm_meas_fp)(const label_info_lst_t label, 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{
|
typedef struct{
|
||||||
char* key;
|
char* key;
|
||||||
@@ -50,6 +50,6 @@ typedef struct{
|
|||||||
|
|
||||||
void init_kpm_subs_data(void);
|
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, e2_node_level_stats_t* node_stats);
|
meas_record_lst_t get_kpm_meas_value(char* kpm_meas_name, const label_info_lst_t label, 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
|
#endif
|
||||||
|
|||||||
+1
-1
Submodule openair2/E2AP/flexric updated: 6a595d8b24...340c36bc83
@@ -1364,6 +1364,12 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE
|
|||||||
T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS));
|
T(T_GNB_MAC_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(sched_pdsch->mcs), T_INT(TBS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DevAssert(nrOfLayers >= 1 && nrOfLayers <= 8);
|
||||||
|
DevAssert(current_BWP->mcsTableIdx >= 0 && current_BWP->mcsTableIdx <= 1);
|
||||||
|
DevAssert(sched_pdsch->mcs >= 0 && sched_pdsch->mcs <= 31);
|
||||||
|
NR_du_stats_t *stats = &nr_mac->du_stats;
|
||||||
|
stats->pdsch_mcs_dist[nrOfLayers - 1][current_BWP->mcsTableIdx][sched_pdsch->mcs] += sched_pdsch->rbSize;
|
||||||
|
|
||||||
const int ntx_req = pdsch->TX_req->Number_of_PDUs;
|
const int ntx_req = pdsch->TX_req->Number_of_PDUs;
|
||||||
nfapi_nr_pdu_t *tx_req = &pdsch->TX_req->pdu_list[ntx_req];
|
nfapi_nr_pdu_t *tx_req = &pdsch->TX_req->pdu_list[ntx_req];
|
||||||
tx_req->PDU_index = pduindex;
|
tx_req->PDU_index = pduindex;
|
||||||
|
|||||||
@@ -637,6 +637,12 @@ static void evaluate_cqi_report(uint8_t *payload,
|
|||||||
|
|
||||||
uint8_t temp_cqi = pickandreverse_bits(payload, 4, cumul_bits);
|
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_table1 = 0
|
||||||
// NR_CSI_ReportConfig__cqi_Table_table2 = 1
|
// NR_CSI_ReportConfig__cqi_Table_table2 = 1
|
||||||
// NR_CSI_ReportConfig__cqi_Table_table3 = 2
|
// NR_CSI_ReportConfig__cqi_Table_table3 = 2
|
||||||
|
|||||||
@@ -2502,6 +2502,12 @@ void post_process_ulsch(gNB_MAC_INST *nr_mac, post_process_pusch_t *pusch, NR_UE
|
|||||||
|
|
||||||
T(T_GNB_MAC_UL, T_INT(UE->rnti), T_INT(frame), T_INT(slot), T_INT(sched_pusch->mcs), T_INT(sched_pusch->tb_size));
|
T(T_GNB_MAC_UL, T_INT(UE->rnti), T_INT(frame), T_INT(slot), T_INT(sched_pusch->mcs), T_INT(sched_pusch->tb_size));
|
||||||
|
|
||||||
|
DevAssert(sched_pusch->nrOfLayers >= 1 && sched_pusch->nrOfLayers <= 8);
|
||||||
|
DevAssert(current_BWP->mcs_table == 0 || current_BWP->mcs_table == 1 || current_BWP->mcs_table == 3);
|
||||||
|
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! */
|
/* PUSCH in a later slot, but corresponding DCI now! */
|
||||||
const int index = ul_buffer_index(sched_pusch->frame,
|
const int index = ul_buffer_index(sched_pusch->frame,
|
||||||
sched_pusch->slot,
|
sched_pusch->slot,
|
||||||
|
|||||||
@@ -889,6 +889,20 @@ typedef struct fsn {
|
|||||||
slot_t s;
|
slot_t s;
|
||||||
} fsn_t;
|
} fsn_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-3 MCS table, 0-31 MCS value
|
||||||
|
uint32_t pdsch_mcs_dist[8][3][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 */
|
/*! \brief top level eNB MAC structure */
|
||||||
typedef struct gNB_MAC_INST_s {
|
typedef struct gNB_MAC_INST_s {
|
||||||
/// Ethernet parameters for northbound midhaul interface
|
/// Ethernet parameters for northbound midhaul interface
|
||||||
@@ -1010,6 +1024,9 @@ typedef struct gNB_MAC_INST_s {
|
|||||||
|
|
||||||
dlul_mac_stats_t mac_stats;
|
dlul_mac_stats_t mac_stats;
|
||||||
uint64_t num_scheduled_prach_rx;
|
uint64_t num_scheduled_prach_rx;
|
||||||
|
|
||||||
|
NR_du_stats_t du_stats;
|
||||||
|
|
||||||
} gNB_MAC_INST;
|
} gNB_MAC_INST;
|
||||||
|
|
||||||
#endif /*__LAYER2_NR_MAC_GNB_H__ */
|
#endif /*__LAYER2_NR_MAC_GNB_H__ */
|
||||||
|
|||||||
Reference in New Issue
Block a user