From 408cebc1e7401e6173eacedb83bb11ed60f03106 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 29 Mar 2024 19:37:57 +0100 Subject: [PATCH] implementing triggering RA after SR failure --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 4 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 71 +++++++++++++++---- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 39 +++++----- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 11 +++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 11 ++- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 18 ++++- 7 files changed, 122 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index fa58cf4676..2cda190f23 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -308,7 +308,7 @@ typedef struct { /// number of attempt for rach uint8_t RA_attempt_number; /// Random-access procedure flag - uint8_t RA_active; + bool RA_active; /// Random-access preamble index int ra_PreambleIndex; // When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble @@ -341,6 +341,8 @@ typedef struct { /// Msg3 buffer uint8_t *Msg3_buffer; + bool msg3_C_RNTI; + /// Random-access Contention Resolution Timer NR_timer_t contention_resolution_timer; /// Transmitted UE Contention Resolution Identifier diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index f263670e03..ea30052058 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -312,6 +312,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac); void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id); +void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); @@ -335,7 +336,7 @@ void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu); fapi_nr_ul_config_request_pdu_t *fapiLockIterator(fapi_nr_ul_config_request_t *ul_config, frame_t frame_tx, int slot_tx); void release_ul_config(fapi_nr_ul_config_request_pdu_t *pdu, bool clearIt); - +void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs); int16_t compute_nr_SSB_PL(NR_UE_MAC_INST_t *mac, short ssb_rsrp_dBm); // PUSCH scheduler: diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index e89e68f317..2ef2f427a4 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -61,7 +61,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, { mac->state = UE_PERFORMING_RA; RA_config_t *ra = &mac->ra; - ra->RA_active = 1; + ra->RA_active = true; ra->ra_PreambleIndex = -1; ra->RA_usedGroupA = 1; ra->RA_RAPID_found = 0; @@ -582,17 +582,25 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION; } -void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) +static uint8_t *fill_msg3_crnti_pdu(RA_config_t *ra, uint8_t *pdu, uint16_t crnti) +{ + // RA triggered by UE MAC with C-RNTI in MAC CE + LOG_D(NR_MAC, "Generating MAC CE with C-RNTI for MSG3 %x\n", crnti); + *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_C_RNTI, .R = 0}; + pdu += sizeof(NR_MAC_SUBHEADER_FIXED); + + // C-RNTI MAC CE (2 octets) + uint16_t rnti_pdu = ((crnti & 0xFF) << 8) | ((crnti >> 8) & 0xFF); + memcpy(pdu, &rnti_pdu, sizeof(rnti_pdu)); + pdu += sizeof(rnti_pdu); + ra->t_crnti = crnti; + return pdu; +} + +static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int TBS_max) { RA_config_t *ra = &mac->ra; - - // we already stored MSG3 in the buffer, we can use that - if (ra->Msg3_buffer) { - buf = ra->Msg3_buffer; - return; - } - - uint8_t *pdu = buf; + // regular MSG3 with PDU coming from higher layers *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH}; pdu += sizeof(NR_MAC_SUBHEADER_FIXED); tbs_size_t len = mac_rlc_data_req(mac->ue_id, @@ -613,6 +621,25 @@ void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) // We copy from persisted memory to another persisted memory memcpy(ra->cont_res_id, pdu, sizeof(uint8_t) * 6); pdu += len; + return pdu; +} + +void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) +{ + RA_config_t *ra = &mac->ra; + + // we already stored MSG3 in the buffer, we can use that + if (ra->Msg3_buffer) { + buf = ra->Msg3_buffer; + return; + } + + uint8_t *pdu = buf; + if (ra->msg3_C_RNTI) + pdu = fill_msg3_crnti_pdu(ra, pdu, mac->crnti); + else + pdu = fill_msg3_pdu_from_rlc(mac, pdu, TBS_max); + AssertFatal(TBS_max >= pdu - buf, "Allocated resources are not enough for Msg3!\n"); // Padding: fill remainder with 0 LOG_D(NR_MAC, "Remaining %ld bytes, filling with padding\n", pdu - buf); @@ -657,7 +684,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); if (ra->ra_state > nrRA_UE_IDLE && ra->ra_state < nrRA_SUCCEEDED) { - if (ra->RA_active == 0) { + if (!ra->RA_active) { NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; init_RA(mac, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); @@ -825,7 +852,8 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame } LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id); - ra->RA_active = 0; + ra->RA_active = false; + ra->msg3_C_RNTI = false; ra->ra_state = nrRA_SUCCEEDED; mac->state = UE_CONNECTED; free_and_zero(ra->Msg3_buffer); @@ -875,6 +903,25 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr } } +void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac) +{ + LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti); + mac->state = UE_SYNC; + reset_ra(mac, false); + mac->ra.msg3_C_RNTI = true; + // release PUCCH for all Serving Cells; + // release SRS for all Serving Cells; + release_PUCCH_SRS(mac); + // clear any configured downlink assignments and uplink grants; + int scs = mac->current_UL_BWP->scs; + if (mac->dl_config_request) + memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); + if (mac->ul_config_request) + clear_ul_config_request(mac, scs); + // clear any PUSCH resources for semi-persistent CSI reporting + // TODO we don't have semi-persistent CSI reporting +} + void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) { NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 5f0bc51e9a..ed23d52aa7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2434,7 +2434,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p if(!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList || - pucch_Config->schedulingRequestResourceToAddModList->list.count==0) + pucch_Config->schedulingRequestResourceToAddModList->list.count == 0) return false; // SR not configured int sr_count = 0; @@ -2458,7 +2458,12 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p pucch->pucch_resource = sr_pucch; pucch->n_sr = 1; /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ - pucch->sr_payload = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID); + int ret = nr_ue_get_SR(mac, frame, slot, sr_Config->schedulingRequestID); + if (ret < 0) { + memset(pucch, 0, sizeof(*pucch)); + return false; + } + pucch->sr_payload = ret; sr_count++; AssertFatal(sr_count < 2, "Cannot handle more than 1 SR per slot yet\n"); } @@ -2500,18 +2505,19 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_Schedu return 1; } - // TODO - // notify RRC to release PUCCH for all Serving Cells; - // notify RRC to release SRS for all Serving Cells; - // clear any configured downlink assignments and uplink grants; - // clear any PUSCH resources for semi-persistent CSI reporting; + LOG_W(NR_MAC, + "[UE %d] SR not served! SR counter %d reached sr_MaxTransmissions %d\n", + mac->ue_id, + sr_info->counter, + sr_info->maxTransmissions); + // initiate a Random Access procedure (see clause 5.1) on the SpCell and cancel all pending SRs. - LOG_E(NR_MAC, "[UE %d] SR not served. Triggering of new RA procedure not implemented yet.\n", mac->ue_id); + schedule_RA_after_SR_failure(mac); sr_info->pending = false; sr_info->counter = 0; nr_timer_stop(&sr_info->prohibitTimer); - return 0; + return -1; } // section 5.2.5 of 38.214 @@ -3511,7 +3517,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i mac_len = 6; if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) { - LOG_I(MAC, "[UE %d][RAPROC] Frame %d : received contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", + LOG_I(MAC, "[UE %d]Frame %d Contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", mac->ue_id, frameP, pduP[1], @@ -3523,21 +3529,21 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i bool ra_success = true; if (!IS_SOFTMODEM_IQPLAYER) { // Control is bypassed when replaying IQs (BMC) - for(int i = 0; icont_res_id[i] != pduP[i+1]) { + for(int i = 0; i < mac_len; i++) { + if(ra->cont_res_id[i] != pduP[i + 1]) { ra_success = false; break; } } } - if ( (ra->RA_active == 1) && ra_success) { + if (ra->RA_active && ra_success) { nr_ra_succeeded(mac, gNB_index, frameP, slot); - } else if (!ra_success){ + } else if (!ra_success) { // TODO: Handle failure of RA procedure @ MAC layer // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure ra->ra_state = nrRA_UE_IDLE; - ra->RA_active = 0; + ra->RA_active = false; } } break; @@ -3978,7 +3984,8 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d if (!ra->cfra) { ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); rnti = ra->t_crnti; - nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index); + if (!ra->msg3_C_RNTI) + nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index); } fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); if (!pdu) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 8c9062d8ec..1f17931264 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -60,6 +60,17 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_frame_t slotP); static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment); +void clear_ul_config_request(NR_UE_MAC_INST_t *mac, int scs) +{ + int slots = nr_slots_per_frame[scs]; + for (int i = 0; i < slots ; i++) { + fapi_nr_ul_config_request_t *ul_config = mac->ul_config_request + i; + pthread_mutex_lock(&ul_config->mutex_ul_config); + ul_config->number_pdus = 0; + pthread_mutex_unlock(&ul_config->mutex_ul_config); + } +} + fapi_nr_ul_config_request_pdu_t *lockGet_ul_config(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, uint8_t pdu_type) { NR_TDD_UL_DL_ConfigCommon_t *tdd_config = mac->tdd_UL_DL_ConfigurationCommon; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index e617184edd..422ae13d89 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -132,9 +132,14 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, // contention resolution identity MAC ce has a fixed 48 bit size // this contains the UL CCCH SDU. If UL CCCH SDU is longer than 48 bits, // it contains the first 48 bits of the UL CCCH SDU - LOG_T(NR_MAC, "[gNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", - ue_cont_res_id[0], ue_cont_res_id[1], ue_cont_res_id[2], - ue_cont_res_id[3], ue_cont_res_id[4], ue_cont_res_id[5]); + LOG_D(NR_MAC, + "[gNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n", + ue_cont_res_id[0], + ue_cont_res_id[1], + ue_cont_res_id[2], + ue_cont_res_id[3], + ue_cont_res_id[4], + ue_cont_res_id[5]); // Copying bytes (6 octects) to CEs pointer mac_ce_size = 6; memcpy(ce_ptr, ue_cont_res_id, mac_ce_size); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 38e57eda66..16f35f6c92 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1059,8 +1059,18 @@ static int handle_bcch_dlsch(NR_UE_MAC_INST_t *mac, } // L2 Abstraction Layer -static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci) +static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, + unsigned int gNB_index, + frame_t frame, + int slot, + fapi_nr_dci_indication_pdu_t *dci) { + // if notification of a reception of a PDCCH transmission of the SpCell is received from lower layers + // if the C-RNTI MAC CE was included in Msg3 + // consider this Contention Resolution successful + if (mac->ra.msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) + nr_ra_succeeded(mac, gNB_index, frame, slot); + return nr_ue_process_dci_indication_pdu(mac, frame, slot, dci); } @@ -1156,7 +1166,11 @@ static uint32_t nr_ue_dl_processing(nr_downlink_indication_t *dl_info) LOG_T(MAC, "[L2][IF MODULE][DL INDICATION][DCI_IND]\n"); for (int i = 0; i < dl_info->dci_ind->number_of_dcis; i++) { LOG_T(MAC, ">>>NR_IF_Module i=%d, dl_info->dci_ind->number_of_dcis=%d\n", i, dl_info->dci_ind->number_of_dcis); - nr_dci_format_t dci_format = handle_dci(mac, dl_info->frame, dl_info->slot, dl_info->dci_ind->dci_list + i); + nr_dci_format_t dci_format = handle_dci(mac, + dl_info->gNB_index, + dl_info->frame, + dl_info->slot, + dl_info->dci_ind->dci_list + i); /* The check below filters out UL_DCIs which are being processed as DL_DCIs. */ if (dci_format != NR_DL_DCI_FORMAT_1_0 && dci_format != NR_DL_DCI_FORMAT_1_1) {