diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index dd8f3098ba..7364b66308 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -239,9 +239,9 @@ typedef struct { typedef struct { - uint8_t rv_index; - uint8_t harq_process_id; - uint8_t new_data_indicator; + uint8_t rv_index; + uint8_t harq_process_id; + bool new_data_indicator; uint32_t tb_size; uint16_t num_cb; uint8_t cb_present_and_position[(NFAPI_UE_MAX_NUM_CB+7) / 8]; @@ -455,13 +455,13 @@ typedef struct { uint8_t rate_matching_ind; uint8_t zp_csi_rs_trigger; uint8_t mcs; - uint8_t ndi; + bool new_data_indicator; uint8_t rv; uint16_t targetCodeRate; uint8_t qamModOrder; uint32_t TBS; uint8_t tb2_mcs; - uint8_t tb2_ndi; + bool tb2_new_data_indicator; uint8_t tb2_rv; uint8_t harq_process_nbr; vrb_to_prb_mapping_t vrb_to_prb_mapping; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 0b2f7ba888..6e976bb8db 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -104,8 +104,6 @@ typedef struct { typedef struct { /// Indicator of first reception uint8_t first_rx; - /// Last Ndi received for this process on DCI (used for C-RNTI only) - uint8_t Ndi; /// DLSCH status flag indicating SCH_status_t status; /// Transport block size diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 476ec8db67..fbe04ffb84 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -304,7 +304,14 @@ static void configure_dlsch(NR_UE_DLSCH_t *dlsch0, if ((dlsch_config_pdu->dmrs_ports>>i)&0x01) Nl += 1; } dlsch0->Nl = Nl; - downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->ndi, dlsch_config_pdu->rv, dlsch0->rnti_type); + if (dlsch_config_pdu->new_data_indicator) { + dlsch0_harq->first_rx = true; + dlsch0_harq->DLround = 0; + } else { + dlsch0_harq->first_rx = false; + dlsch0_harq->DLround++; + } + downlink_harq_process(dlsch0_harq, current_harq_pid, dlsch_config_pdu->new_data_indicator, dlsch_config_pdu->rv, dlsch0->rnti_type); if (dlsch0_harq->status != ACTIVE) { // dlsch0_harq->status not ACTIVE due to false retransmission // Reset the following flag to skip PDSCH procedures in that case and retrasmit harq status diff --git a/openair1/SCHED_NR_UE/harq_nr.c b/openair1/SCHED_NR_UE/harq_nr.c index b7b542bf54..b6e528bdb5 100644 --- a/openair1/SCHED_NR_UE/harq_nr.c +++ b/openair1/SCHED_NR_UE/harq_nr.c @@ -115,7 +115,6 @@ void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) dl_harq->status = SCH_IDLE; dl_harq->first_rx = 1; dl_harq->DLround = 0; - dl_harq->Ndi = 2; // set to an invalid value dl_harq->ack = DL_ACKNACK_NO_SET; } @@ -152,32 +151,9 @@ void downlink_harq_process(NR_DL_UE_HARQ_t *dl_harq, int harq_pid, int dci_ndi, rv, dci_ndi, rnti_type, - dl_harq->Ndi != dci_ndi ? "yes" : "no"); + dci_ndi ? "yes" : "no"); AssertFatal(rv<4 && rv>=0, "invalid redondancy version %d\n", rv); - if (dci_ndi!=dl_harq->Ndi) { - if (dl_harq->ack == DL_NACK) - LOG_D(PHY,"New transmission on a harq pid (%d) never acknowledged\n", harq_pid); - else - LOG_D(PHY,"Starting new transmission on a harq pid (%d)\n", harq_pid); - } else { - if (dl_harq->ack != DL_NACK) - LOG_D(PHY,"gNB asked for retransmission even if we sent ACK\n"); - else - LOG_D(PHY,"Starting retransmission on a harq pid (%d), rv (%d)\n", harq_pid, rv); - } - - if (dci_ndi!=dl_harq->Ndi) { - dl_harq->first_rx = true; - dl_harq->DLround = 0; - } else { - dl_harq->first_rx = false; - dl_harq->DLround++; - } - dl_harq->status = ACTIVE; - - dl_harq->Ndi = dci_ndi; - //dl_harq->status = SCH_IDLE; - } + } } diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 756273769c..b2713edb9a 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -348,11 +348,13 @@ typedef struct { int8_t delta_pucch; uint32_t R; uint32_t TBS; + int last_ndi; } NR_UE_HARQ_STATUS_t; typedef struct { uint32_t R; uint32_t TBS; + int last_ndi; } NR_UL_HARQ_INFO_t; typedef struct { @@ -499,8 +501,6 @@ typedef struct NR_UE_MAC_INST_s { /// measurements from CSI-RS fapi_nr_csirs_measurements_t csirs_measurements; - /// Last NDI of UL HARQ processes - int UL_ndi[NR_MAX_HARQ_PROCESSES]; //// FAPI-like interface message fapi_nr_ul_config_request_t *ul_config_request; fapi_nr_dl_config_request_t *dl_config_request; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index be013b6dff..7a1d3cfb17 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -74,6 +74,10 @@ void nr_ue_init_mac(module_id_t module_idP) memset(&mac->ssb_list[i], 0, sizeof(mac->ssb_list[i])); memset(&mac->prach_assoc_pattern[i], 0, sizeof(mac->prach_assoc_pattern[i])); } + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value + mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value + } } void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) @@ -100,8 +104,6 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) mac->scheduling_info.lc_sched_info[i].LCGID = 0; // defaults to 0 irrespective of SRB or DRB mac->scheduling_info.lc_sched_info[i].LCID_status = LCID_EMPTY; mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0; - for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) - mac->UL_ndi[k] = -1; // initialize to invalid value } } @@ -142,6 +144,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) // MAC reset according to 38.321 Section 5.12 nr_ue_mac_default_configs(nr_mac); + // initialize Bj for each logical channel to zero // Done in default config but to -1 (is that correct?) @@ -153,7 +156,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) // set the NDIs for all uplink HARQ processes to the value 0 for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) - nr_mac->UL_ndi[k] = -1; // initialize to invalid value + nr_mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value // stop any ongoing RACH procedure if (nr_mac->ra.ra_state < RA_SUCCEEDED) @@ -179,7 +182,8 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) memset(&nr_mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t)); // for each DL HARQ process, consider the next received transmission for a TB as the very first transmission - // TODO there is nothing in the MAC indicating first transmission + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) + nr_mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value // release, if any, Temporary C-RNTI nr_mac->ra.t_crnti = 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index b170fc61b9..25e3cae83f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -681,13 +681,30 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id, /* MCS */ dlsch_pdu->mcs = dci->mcs; + NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid]; + /* 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 || + dci->ndi != current_harq->last_ndi) { + // new data + dlsch_pdu->new_data_indicator = true; + current_harq->R = 0; + current_harq->TBS = 0; + } + 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) { + current_harq->last_ndi = dci->ndi; + } + dlsch_pdu->qamModOrder = nr_get_Qm_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); if (dlsch_pdu->qamModOrder == 0) { LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n"); return -1; } - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid]; int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); if (R > 0) { dlsch_pdu->targetCodeRate = R; @@ -707,6 +724,11 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id, 1); // storing for possible retransmissions current_harq->R = dlsch_pdu->targetCodeRate; + if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) { + LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n", + dlsch_pdu->TBS, current_harq->TBS); + dlsch_pdu->new_data_indicator = true; // treated as new data + } current_harq->TBS = dlsch_pdu->TBS; } else { @@ -716,11 +738,14 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id, dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate); + if (dlsch_pdu->TBS == 0) { + LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); + return -1; + } + int bw_tbslbrm = current_DL_BWP ? mac->sc_info.dl_bw_tbslbrm : dlsch_pdu->BWPSize; dlsch_pdu->tbslbrm = nr_compute_tbslbrm(dlsch_pdu->mcs_table, bw_tbslbrm, 1); - /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ - dlsch_pdu->ndi = dci->ndi; /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ dlsch_pdu->rv = dci->rv; /* HARQ_PROCESS_NUMBER (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/ @@ -801,7 +826,7 @@ static int nr_ue_process_dci_dl_10(module_id_t module_id, "scaling_factor_S=%f\n>>> tpc_pucch=%d\n>>> pucch_res_ind=%d\n>>> pdsch_to_harq_feedback_time_ind=%d\n", dlsch_pdu->vrb_to_prb_mapping, dlsch_pdu->mcs, - dlsch_pdu->ndi, + dlsch_pdu->new_data_indicator, dlsch_pdu->rv, dlsch_pdu->harq_process_nbr, dci->dai[0].val, @@ -961,13 +986,23 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id, /* MCS (for transport block 1)*/ dlsch_pdu->mcs = dci->mcs; /* NDI (for transport block 1)*/ - dlsch_pdu->ndi = dci->ndi; + NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid]; + if (dci->ndi != current_harq->last_ndi) { + // new data + dlsch_pdu->new_data_indicator = true; + current_harq->R = 0; + current_harq->TBS = 0; + } + else { + dlsch_pdu->new_data_indicator = false; + } + current_harq->last_ndi = dci->ndi; /* RV (for transport block 1)*/ dlsch_pdu->rv = dci->rv; /* MCS (for transport block 2)*/ dlsch_pdu->tb2_mcs = dci->mcs2.val; /* NDI (for transport block 2)*/ - dlsch_pdu->tb2_ndi = dci->ndi2.val; + dlsch_pdu->tb2_new_data_indicator = dci->ndi2.val; /* RV (for transport block 2)*/ dlsch_pdu->tb2_rv = dci->rv2.val; /* HARQ_PROCESS_NUMBER */ @@ -1124,7 +1159,6 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id, nb_rb_oh = 0; int nb_re_dmrs = ((dmrs_type == NULL) ? 6 : 4) * dlsch_pdu->n_dmrs_cdm_groups; - NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[dci->harq_pid]; int R = nr_get_code_rate_dl(dlsch_pdu->mcs, dlsch_pdu->mcs_table); if (R > 0) { dlsch_pdu->targetCodeRate = R; @@ -1137,6 +1171,11 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id, 0, Nl); // storing for possible retransmissions + if (!dlsch_pdu->new_data_indicator && current_harq->TBS != dlsch_pdu->TBS) { + LOG_W(NR_MAC, "NDI indicates re-transmission but computed TBS %d doesn't match with what previously stored %d\n", + dlsch_pdu->TBS, current_harq->TBS); + dlsch_pdu->new_data_indicator = true; // treated as new data + } current_harq->R = dlsch_pdu->targetCodeRate; current_harq->TBS = dlsch_pdu->TBS; } @@ -1147,6 +1186,11 @@ static int nr_ue_process_dci_dl_11(module_id_t module_id, dlsch_pdu->ldpcBaseGraph = get_BG(dlsch_pdu->TBS, dlsch_pdu->targetCodeRate); + if (dlsch_pdu->TBS == 0) { + LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); + return -1; + } + // TBS_LBRM according to section 5.4.2.1 of 38.212 AssertFatal(sc_info->maxMIMO_Layers_PDSCH != NULL, "Option with max MIMO layers not configured is not supported\n"); int nl_tbslbrm = *sc_info->maxMIMO_Layers_PDSCH < 4 ? *sc_info->maxMIMO_Layers_PDSCH : 4; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index d493ab25c7..da201a782c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -656,8 +656,14 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, } /* NDI */ - pusch_config_pdu->pusch_data.new_data_indicator = dci->ndi != mac->UL_ndi[dci->harq_pid] ? 1 : 0; - mac->UL_ndi[dci->harq_pid] = dci->ndi; + NR_UL_HARQ_INFO_t *harq = &mac->ul_harq_info[dci->harq_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)); + } + harq->last_ndi = dci->ndi; /* RV */ pusch_config_pdu->pusch_data.rv_index = dci->rv; /* HARQ_PROCESS_NUMBER */ @@ -768,7 +774,14 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, 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; } + pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate); + + if (pusch_config_pdu->pusch_data.tb_size == 0) { + LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); + return -1; + } + return 0; }