add ue mac stats and monitoring as per gnb ones

This commit is contained in:
Laurent THOMAS
2024-11-21 16:39:19 +01:00
parent 5d1c0aaab7
commit 65e3c89bb1
16 changed files with 176 additions and 80 deletions
@@ -2232,8 +2232,7 @@ static const uint16_t Table_51311[32][2] = {{2, 1200}, {2, 1570}, {2, 1930}, {2,
{4, 6580}, {6, 4380}, {6, 4660}, {6, 5170}, {6, 5670}, {6, 6160}, {6, 6660}, {6, 7190},
{6, 7720}, {6, 8220}, {6, 8730}, {6, 9100}, {6, 9480}, {2, 0}, {4, 0}, {6, 0}};
//Table 5.1.3.1-2 of 38.214
// Imcs values 20 and 26 have been multiplied by 2 to avoid the floating point
// Table 5.1.3.1-2 of 38.214
static const uint16_t Table_51312[32][2] = {{2, 1200}, {2, 1930}, {2, 3080}, {2, 4490}, {2, 6020}, {4, 3780}, {4, 4340},
{4, 4900}, {4, 5530}, {4, 6160}, {4, 6580}, {6, 4660}, {6, 5170}, {6, 5670},
{6, 6160}, {6, 6660}, {6, 7190}, {6, 7720}, {6, 8220}, {6, 8730}, {8, 6825},
+32 -4
View File
@@ -385,13 +385,15 @@ typedef struct {
uint32_t R;
uint32_t TBS;
int last_ndi;
} NR_UE_HARQ_STATUS_t;
int round;
} NR_UE_DL_HARQ_STATUS_t;
typedef struct {
uint32_t R;
uint32_t TBS;
int last_ndi;
} NR_UL_HARQ_INFO_t;
int round;
} NR_UE_UL_HARQ_INFO_t;
typedef struct {
uint8_t freq_hopping;
@@ -510,6 +512,31 @@ typedef enum {
ON_PUSCH
} CSI_mapping_t;
typedef struct {
uint64_t rounds[NR_MAX_HARQ_ROUNDS_FOR_STATS];
uint64_t total_bits;
uint64_t total_symbols;
uint64_t target_code_rate;
uint64_t qam_mod_order;
uint64_t rb_size;
uint64_t nr_of_symbols;
} ue_mac_dir_stats_t;
typedef struct {
ue_mac_dir_stats_t dl;
ue_mac_dir_stats_t ul;
uint32_t bad_dci;
uint32_t ulsch_DTX;
uint64_t ulsch_total_bytes_scheduled;
uint32_t pucch0_DTX;
int cumul_rsrp;
uint8_t num_rsrp_meas;
char srs_stats[50]; // Statistics may differ depending on SRS usage
int pusch_snrx10;
int deltaMCS;
int NPRB;
} ue_mac_stats_t;
/*!\brief Top level UE MAC structure */
typedef struct NR_UE_MAC_INST_s {
module_id_t ue_id;
@@ -594,8 +621,8 @@ typedef struct NR_UE_MAC_INST_s {
// Defined for abstracted mode
nr_downlink_indication_t dl_info;
NR_UE_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES];
NR_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES];
NR_UE_DL_HARQ_STATUS_t dl_harq_info[NR_MAX_HARQ_PROCESSES];
NR_UE_UL_HARQ_INFO_t ul_harq_info[NR_MAX_HARQ_PROCESSES];
NR_TAG_Id_t tag_Id;
A_SEQUENCE_OF(NR_TAG_t) TAG_list;
@@ -615,6 +642,7 @@ typedef struct NR_UE_MAC_INST_s {
bool pusch_power_control_initialized;
int delta_msg2;
pthread_mutex_t if_mutex;
ue_mac_stats_t stats;
} NR_UE_MAC_INST_t;
/*@}*/
+1 -2
View File
@@ -240,8 +240,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
nr_mac->scheduling_info.phr_info.was_mac_reset = true;
// flush the soft buffers for all DL HARQ processes
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
memset(&nr_mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t));
memset(nr_mac->dl_harq_info, 0, sizeof(nr_mac->dl_harq_info));
// for each DL HARQ process, consider the next received transmission for a TB as the very first transmission
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
+1 -1
View File
@@ -1053,7 +1053,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac)
void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack)
{
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid];
int sched_slot = current_harq->ul_slot;
int sched_frame = current_harq->ul_frame;
mac->nr_ue_emul_l1.num_harqs = 1;
+23 -10
View File
@@ -806,7 +806,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
/* MCS */
dlsch_pdu->mcs = dci->mcs;
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
/* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
if (dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH ||
dl_conf_req->pdu_type == FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH ||
@@ -815,9 +815,9 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
dlsch_pdu->new_data_indicator = true;
current_harq->R = 0;
current_harq->TBS = 0;
}
else
} else {
dlsch_pdu->new_data_indicator = false;
}
if (dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_SI_DLSCH &&
dl_conf_req->pdu_type != FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH) {
@@ -935,6 +935,12 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
dci_ind->N_CCE,
frame,
slot);
if (dlsch_pdu->new_data_indicator)
current_harq->round = 0;
else
current_harq->round++;
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
mac->stats.dl.rounds[current_harq->round]++;
}
LOG_D(MAC,
@@ -1126,7 +1132,7 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
/* MCS (for transport block 1)*/
dlsch_pdu->mcs = dci->mcs;
/* NDI (for transport block 1)*/
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid.val];
if (dci->ndi != current_harq->last_ndi) {
// new data
dlsch_pdu->new_data_indicator = true;
@@ -1275,6 +1281,12 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
dci_ind->N_CCE,
frame,
slot);
if (dlsch_pdu->new_data_indicator)
current_harq->round = 0;
else
current_harq->round++;
if (current_harq->round < sizeofArray(mac->stats.dl.rounds))
mac->stats.dl.rounds[current_harq->round]++;
// send the ack/nack slot number to phy to indicate tx thread to wait for DLSCH decoding
dlsch_pdu->k1_feedback = feedback_ti;
@@ -1432,10 +1444,11 @@ nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t
nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, dci->ss_type, dci->payloadBits, slot);
if (format == NR_DCI_NONE)
return NR_DCI_NONE;
dci_pdu_rel15_t *def_dci_pdu_rel15 = &mac->def_dci_pdu_rel15[slot][format];
int ret = nr_ue_process_dci(mac, frame, slot, def_dci_pdu_rel15, dci, format);
if (ret < 0)
int ret = nr_ue_process_dci(mac, frame, slot, mac->def_dci_pdu_rel15[slot] + format, dci, format);
if (ret < 0) {
mac->stats.bad_dci++;
return NR_DCI_NONE;
}
return format;
}
@@ -1459,7 +1472,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
frame_t frame,
int slot)
{
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id];
current_harq->active = true;
current_harq->ack_received = false;
current_harq->pucch_resource_indicator = pucch_id;
@@ -1486,7 +1499,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
// looking for other active HARQ processes with feedback in the same frame/slot
if (i == harq_id)
continue;
NR_UE_HARQ_STATUS_t *harq = &mac->dl_harq_info[i];
NR_UE_DL_HARQ_STATUS_t *harq = &mac->dl_harq_info[i];
if (harq->active &&
harq->ul_frame == current_harq->ul_frame &&
harq->ul_slot == current_harq->ul_slot) {
@@ -2331,7 +2344,7 @@ bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sche
for (int dl_harq_pid = 0; dl_harq_pid < num_dl_harq; dl_harq_pid++) {
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dl_harq_pid];
if (current_harq->active) {
LOG_D(PHY, "HARQ pid %d is active for %d.%d\n",
+31 -16
View File
@@ -166,8 +166,8 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac)
{
// flush all HARQ buffers for all Serving Cells
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) {
memset(&mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t));
memset(&mac->ul_harq_info[k], 0, sizeof(NR_UL_HARQ_INFO_t));
memset(&mac->dl_harq_info[k], 0, sizeof(*mac->dl_harq_info));
memset(&mac->ul_harq_info[k], 0, sizeof(*mac->ul_harq_info));
mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value
mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value
}
@@ -704,6 +704,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
0,
f_alloc) < 0) {
LOG_E(NR_MAC, "can't nr_ue_process_dci_freq_dom_resource_assignment()\n");
mac->stats.bad_dci++;
return -1;
}
@@ -713,7 +714,6 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
// Time domain allocation
pusch_config_pdu->start_symbol_index = tda_info->startSymbolIndex;
pusch_config_pdu->nr_of_symbols = tda_info->nrOfSymbols;
l_prime_mask = get_l_prime(tda_info->nrOfSymbols,
tda_info->mapping_type,
add_pos,
@@ -817,11 +817,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
ul_ports_config(mac, &dmrslength, pusch_config_pdu, dci, dci_format);
} else {
LOG_E(NR_MAC, "UL grant from DCI format %d is not handled...\n", dci_format);
mac->stats.bad_dci++;
return -1;
}
if (pusch_config_pdu->nrOfLayers < 1) {
LOG_E(NR_MAC, "Invalid UL number of layers %d from DCI\n", pusch_config_pdu->nrOfLayers);
mac->stats.bad_dci++;
return -1;
}
@@ -892,6 +894,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
0,
dci->frequency_domain_assignment) < 0) {
LOG_E(NR_MAC, "can't nr_ue_process_dci_freq_dom_resource_assignment()\n");
mac->stats.bad_dci++;
return -1;
}
@@ -910,18 +913,20 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->mcs_table = get_pusch_mcs_table(mcs_table_config, tp_enabled, dci_format, rnti_type, ss_type, false);
/* NDI */
NR_UL_HARQ_INFO_t *harq = &mac->ul_harq_info[dci->harq_pid.val];
const int pid = dci->harq_pid.val;
NR_UE_UL_HARQ_INFO_t *harq = &mac->ul_harq_info[pid];
pusch_config_pdu->pusch_data.new_data_indicator = false;
if (dci->ndi != harq->last_ndi) {
pusch_config_pdu->pusch_data.new_data_indicator = true;
// if new data reset harq structure
memset(harq, 0, sizeof(*harq));
}
} else
harq->round++;
harq->last_ndi = dci->ndi;
/* RV */
pusch_config_pdu->pusch_data.rv_index = dci->rv;
/* HARQ_PROCESS_NUMBER */
pusch_config_pdu->pusch_data.harq_process_id = dci->harq_pid.val;
pusch_config_pdu->pusch_data.harq_process_id = pid;
if (NR_DMRS_ulconfig != NULL)
add_pos = (NR_DMRS_ulconfig->dmrs_AdditionalPosition == NULL) ? 2 : *NR_DMRS_ulconfig->dmrs_AdditionalPosition;
@@ -994,6 +999,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table);
if (pusch_config_pdu->qam_mod_order == 0) {
LOG_W(NR_MAC, "Invalid Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n");
mac->stats.bad_dci++;
return -1;
}
@@ -1001,15 +1007,16 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
int number_of_symbols = pusch_config_pdu->nr_of_symbols;
int number_dmrs_symbols = 0;
for (int i = start_symbol; i < start_symbol + number_of_symbols; i++) {
if((pusch_config_pdu->ul_dmrs_symb_pos >> i) & 0x01)
if ((pusch_config_pdu->ul_dmrs_symb_pos >> i) & 0x01)
number_dmrs_symbols += 1;
}
int nb_dmrs_re_per_rb = ((pusch_config_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6 : 4) * pusch_config_pdu->num_dmrs_cdm_grps_no_data;
int nb_dmrs_re_per_rb =
((pusch_config_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6 : 4) * pusch_config_pdu->num_dmrs_cdm_grps_no_data;
// Compute TBS
uint16_t R = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table);
int pid = pusch_config_pdu->pusch_data.harq_process_id;
const int pid = pusch_config_pdu->pusch_data.harq_process_id;
if (R > 0) {
pusch_config_pdu->target_code_rate = R;
pusch_config_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_config_pdu->qam_mod_order,
@@ -1022,8 +1029,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->nrOfLayers) >> 3;
mac->ul_harq_info[pid].TBS = pusch_config_pdu->pusch_data.tb_size;
mac->ul_harq_info[pid].R = R;
}
else {
} else {
pusch_config_pdu->target_code_rate = mac->ul_harq_info[pid].R;
pusch_config_pdu->pusch_data.tb_size = mac->ul_harq_info[pid].TBS;
}
@@ -1052,7 +1058,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->rb_start,
pusch_config_pdu->nr_of_symbols,
nb_dmrs_re_per_rb * number_dmrs_symbols,
0, //TODO: count PTRS per RB
0, // TODO: count PTRS per RB
pusch_config_pdu->qam_mod_order,
pusch_config_pdu->target_code_rate,
pusch_config_pdu->pusch_uci.beta_offset_csi1,
@@ -1063,12 +1069,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate);
//The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH
// The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH
if (pusch_config_pdu->pusch_data.new_data_indicator && dci && dci->ulsch_indicator)
nr_timer_start(&mac->scheduling_info.retxBSR_Timer);
if (pusch_config_pdu->pusch_data.tb_size == 0) {
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
mac->stats.bad_dci++;
return -1;
}
@@ -1081,6 +1088,14 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
nr_timer_start(&mac->scheduling_info.phr_info.periodicPHR_Timer);
}
}
if (mac->ul_harq_info[pid].round < sizeofArray(mac->stats.ul.rounds))
mac->stats.ul.rounds[mac->ul_harq_info[pid].round]++;
int bits = pusch_config_pdu->pusch_data.tb_size;
mac->stats.ul.total_bits += bits;
mac->stats.ul.target_code_rate += pusch_config_pdu->target_code_rate * bits;
mac->stats.ul.total_symbols += bits / pusch_config_pdu->qam_mod_order;
mac->stats.ul.rb_size += pusch_config_pdu->rb_size;
mac->stats.ul.nr_of_symbols += pusch_config_pdu->nr_of_symbols;
return 0;
}
@@ -2124,9 +2139,9 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac)
tx_ssb->nb_mapped_ro);
// If all the required SSBs are mapped to this RO, exit the loop of SSBs
if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
idx++;
break;
}
idx++;
break;
}
}
done = MAX_NB_SSB == idx;
}
+52 -1
View File
@@ -67,6 +67,57 @@ queue_t nr_ul_dci_req_queue;
queue_t nr_ul_tti_req_queue;
static void save_pdsch_pdu_for_crnti(nfapi_nr_dl_tti_request_t *dl_tti_request);
void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slot_rx)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(mod);
int ret = pthread_mutex_lock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret);
char txt[1024];
char *end = txt + sizeof(txt);
char *cur = txt;
float nbul = 0;
for (uint64_t *p = mac->stats.ul.rounds; p < mac->stats.ul.rounds + NR_MAX_HARQ_ROUNDS_FOR_STATS; p++)
nbul += *p;
if (nbul < 1)
nbul = 1;
float nbdl = 0;
for (uint64_t *p = mac->stats.dl.rounds; p < mac->stats.dl.rounds + NR_MAX_HARQ_ROUNDS_FOR_STATS; p++)
nbdl += *p;
if (nbdl < 1)
nbdl = 1;
cur += snprintf(cur, end - cur, "UE %d stats sfn: %d.%d, cumulated bad DCI %d\n", mod, frame_rx, slot_rx, mac->stats.bad_dci);
cur += snprintf(cur, end - cur, " DL harq: %lu", mac->stats.dl.rounds[0]);
int nb;
for (nb = NR_MAX_HARQ_ROUNDS_FOR_STATS - 1; nb > 1; nb--)
if (mac->stats.ul.rounds[nb])
break;
for (int i = 1; i < nb + 1; i++)
cur += snprintf(cur, end - cur, "/%lu", mac->stats.dl.rounds[i]);
cur += snprintf(cur, end - cur, "\n Ul harq: %lu", mac->stats.ul.rounds[0]);
for (nb = NR_MAX_HARQ_ROUNDS_FOR_STATS - 1; nb > 1; nb--)
if (mac->stats.ul.rounds[nb])
break;
for (int i = 1; i < nb + 1; i++)
cur += snprintf(cur, end - cur, "/%lu", mac->stats.ul.rounds[i]);
snprintf(cur,
end - cur,
" avg code rate %.01f, avg bit/symbol %.01f, avg per TB: "
"(nb RBs %.01f, nb symbols %.01f)\n",
(double)mac->stats.ul.target_code_rate / (mac->stats.ul.total_bits * 1024 * 10), // See const Table_51311 definition
(double)mac->stats.ul.total_bits / mac->stats.ul.total_symbols,
mac->stats.ul.rb_size / nbul,
mac->stats.ul.nr_of_symbols / nbul);
LOG_I(NR_MAC, "%s", txt);
ret = pthread_mutex_unlock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret);
}
void nrue_init_standalone_socket(int tx_port, int rx_port)
{
{
@@ -1120,7 +1171,7 @@ static int8_t handle_csirs_measurements(NR_UE_MAC_INST_t *mac,
void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nack)
{
NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid];
NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_pid];
if (current_harq->active) {
LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack);
@@ -322,5 +322,7 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info);
void nr_ue_sl_indication(nr_sidelink_indication_t *sl_indication);
void print_ue_mac_stats(const module_id_t mod, const int frame_rx, const int slot_rx);
#endif