From 8f62baefa61e770635cb931ae587eb8c80350ca8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 3 Mar 2025 09:52:21 +0100 Subject: [PATCH] Use list of UEs during RA instead of array of RA processes - rewrite add_UE_to_list() and rewrite remove_UE_from_list() to simplify list handling - return pointer from get_new_nr_ue_inst(); it's completely freed by delete_nr_ue_data() - have add_new_UE_RA() add UE context to access list; remove with nr_release_ra_UE() - have add_connected_nr_ue() only add UE to connected list; to move from access to connected use transition_ra_connected_nr_ue(); remove with mac_remove_nr_ue() as previously - free memory on problems during RA - add some documentation - in NSA/HO: check for pre-configured RA process - there are asserts in all functions to clarify when a UE has RA --- openair1/SIMULATION/NR_PHY/dlsim.c | 4 +- openair2/LAYER2/NR_MAC_gNB/config.c | 50 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 487 +++++++++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 3 - .../NR_MAC_gNB/gNB_scheduler_primitives.c | 285 +++++----- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 92 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 237 ++++----- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 33 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 25 +- openair2/LAYER2/NR_MAC_gNB/main.c | 3 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 21 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 2 +- openair2/RRC/NR/rrc_gNB_nsa.c | 14 +- 13 files changed, 584 insertions(+), 672 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 708bb9e831..8408d6ecb0 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -185,7 +185,7 @@ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLay void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) { NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0]; - AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "can have only a single UE\n"); + AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n"); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP; NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; @@ -804,7 +804,7 @@ printf("%d\n", slot); N_RB_DL = gNB->frame_parms.N_RB_DL; NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0]; - configure_UE_BWP(RC.nrmac[0], scc, &UE_info->UE_sched_ctrl, NULL, UE_info, -1, -1); + configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, -1, -1); // stub to configure frame_parms // nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 90891919db..dcd5fa220f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -858,14 +858,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c find_SSB_and_RO_available(nrmac); - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; - NR_SCHED_LOCK(&nrmac->sched_lock); - for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) { - NR_RA_t *ra = &cc->ra[n]; - nr_clear_ra_proc(ra); - } - NR_SCHED_UNLOCK(&nrmac->sched_lock); - if (IS_SA_MODE(get_softmodem_params())) config_sched_ctrlCommon(nrmac); } @@ -979,18 +971,17 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t DevAssert(get_softmodem_params()->phy_test); NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UE_info_t *UE = add_new_nr_ue(nrmac, rnti, CellGroup); - if (!UE) { + NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup); + DevAssert(UE != NULL); // test-mode: we assume we can always create a UE + free_and_zero(UE->ra); // test-mode (sims, phy-test): UE will not do RA + bool res = add_connected_nr_ue(nrmac, UE); + if (!res) { LOG_E(NR_MAC, "Error adding UE %04x\n", rnti); + delete_nr_ue_data(UE, NULL, &nrmac->UE_info.uid_allocator); NR_SCHED_UNLOCK(&nrmac->sched_lock); return false; } - - if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra) { - nr_mac_prepare_ra_ue(RC.nrmac[0], UE->rnti, CellGroup); - } + configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, -1, -1); process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList); AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n"); NR_SCHED_UNLOCK(&nrmac->sched_lock); @@ -998,32 +989,18 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t return true; } -bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) +void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE) { DevAssert(nrmac != NULL); - DevAssert(CellGroup != NULL); NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - - // NSA case: need to pre-configure CFRA - const int CC_id = 0; - NR_COMMON_channels_t *cc = &nrmac->common_channels[CC_id]; - uint8_t ra_index = 0; - /* checking for free RA process */ - for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) { - if ((cc->ra[ra_index].ra_state == nrRA_gNB_IDLE) && (!cc->ra[ra_index].cfra)) - break; - } - if (ra_index == NR_NB_RA_PROC_MAX) { - LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti); - return false; - } - NR_RA_t *ra = &cc->ra[ra_index]; + NR_RA_t *ra = UE->ra; ra->cfra = true; - ra->rnti = rnti; - ra->CellGroup = CellGroup; + NR_CellGroupConfig_t *CellGroup = UE->CellGroup; + DevAssert(CellGroup != NULL); struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra; uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count; ra->preambles.num_preambles = num_preamble; + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; for (int i = 0; i < cc->num_active_ssb; i++) { for (int j = 0; j < num_preamble; j++) { if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) { @@ -1033,8 +1010,7 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig } } } - LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti); - return true; + LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti); } /* Prepare a new CellGroupConfig to be applied for this UE. We cannot diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 2c4ef67e3e..beb66aa6b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -49,14 +49,14 @@ // forward declaration of functions used in this file static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, NR_ServingCellConfigCommon_t *scc, - const NR_RA_t *ra, + NR_UE_info_t *UE, int startSymbolAndLength, int scs, int bwp_size, int bwp_start, int mappingtype, int fh); -static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); +static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); static const uint8_t DELTA[4] = {2, 3, 4, 6}; @@ -636,39 +636,26 @@ int nr_fill_successrar(const NR_UE_sched_ctrl_t *ue_sched_ctl, return mac_pdu_length; } -static bool ra_contains_preamble(const NR_RA_t *ra, uint16_t preamble_index) +/** @brief find UE with RA process for given preamble */ +static NR_UE_info_t *get_existing_ra(gNB_MAC_INST *nr_mac, uint16_t preamble_index) { - for (int j = 0; j < ra->preambles.num_preambles; j++) { - // check if the preamble received correspond to one of the listed or configured preambles - if (preamble_index == ra->preambles.preamble_list[j]) { - if (ra->rnti == 0 && get_softmodem_params()->nsa) - continue; - return true; + UE_iterator(nr_mac->UE_info.access_ue_list, UE) { + NR_RA_t *ra = UE->ra; + for (int i = 0; i < ra->preambles.num_preambles; ++i) { + if (ra->preambles.preamble_list[i] == preamble_index) + return UE; } } - return false; + return NULL; } -static NR_RA_t *find_free_nr_RA(NR_RA_t *ra_base, int ra_count, uint16_t preamble_index) +/** @brief add UE to list of UEs doing RA. + * + * Remove with nr_release_ra_UE(). */ +bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) { - // for posteriority: in the past we checked the beam index, but only in CFRA - //if (ra->cfra && preamble_index != ra->preamble.preamble_list[beam_index]]) - // // then is not right RA - // - // that seems strange because: - // - we check preamble_index already - // - why only CFRA? - - for (int i = 0; i < ra_count; ++i) { - NR_RA_t *ra = &ra_base[i]; - if (ra->ra_state != nrRA_gNB_IDLE) - continue; - if (!ra_contains_preamble(ra, preamble_index)) - continue; - - return ra; - } - return NULL; + DevAssert(UE->ra); // a UE in the acess_ue_list needs to have an RA process + return add_UE_to_list(NR_NB_RA_PROC_MAX, nr_mac->UE_info.access_ue_list, UE); } static uint8_t nr_get_msg3_tpc(uint32_t preamble_power) @@ -704,8 +691,8 @@ static unsigned int get_slot_RA(const NR_ServingCellConfigCommon_t *scc, void nr_initiate_ra_proc(module_id_t module_idP, int CC_id, - frame_t frameP, - int slotP, + frame_t frame, + int slot, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol, @@ -717,32 +704,48 @@ void nr_initiate_ra_proc(module_id_t module_idP, gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_SCHED_LOCK(&nr_mac->sched_lock); - NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - - NR_RA_t *ra = find_free_nr_RA(cc->ra, sizeofArray(cc->ra), preamble_index); - if (ra == NULL) { - LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frameP, slotP, preamble_index); + /* check if preamble exists (NSA, HO cases) */ + NR_UE_info_t *UE = get_existing_ra(nr_mac, preamble_index); + if ((get_softmodem_params()->nsa || get_softmodem_params()->do_ra) && !UE) { + /* we are in NSA, but no UE has been configured => we ignore it */ + LOG_W(NR_MAC, "random access with preamble %d: no pre-configured RA process found\n", preamble_index); NR_SCHED_UNLOCK(&nr_mac->sched_lock); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); return; } - if (ra->rnti == 0) { // This condition allows for the usage of a preconfigured rnti for the CFRA - bool rnti_found = nr_mac_get_new_rnti(&nr_mac->UE_info, cc->ra, sizeofArray(cc->ra), &ra->rnti); + if (!UE) { + /* in CBRA: we don't know this UE yet. There might be CFRA (e.g., HO IN SA) + * where we know the UE */ + rnti_t rnti; + bool rnti_found = nr_mac_get_new_rnti(&nr_mac->UE_info, &rnti); if (!rnti_found) { LOG_E(NR_MAC, "initialisation random access: no more available RNTIs for new UE\n"); - nr_clear_ra_proc(ra); + NR_SCHED_UNLOCK(&nr_mac->sched_lock); + return; + } + + UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL); + if (!UE) { + LOG_E(NR_MAC, "FAILURE: %4d.%2d cannot create UE context, ignoring RA because RRC Reject not implemented yet\n", frame, slot); + NR_SCHED_UNLOCK(&nr_mac->sched_lock); + return; + } + if (!add_new_UE_RA(nr_mac, UE)) { + LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index); + delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator); NR_SCHED_UNLOCK(&nr_mac->sched_lock); return; } } - ra->preamble_frame = frameP; - ra->preamble_slot = slotP; + NR_RA_t *ra = UE->ra; + ra->preamble_frame = frame; + ra->preamble_slot = slot; ra->preamble_index = preamble_index; ra->timing_offset = timing_offset; ra->msg3_TPC = nr_get_msg3_tpc(preamble_power); + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; // 3GPP TS 38.321 Section 5.1.3(a) says t_id for RA-RNTI depends on mu as specified in clause 5.3.2 in TS 38.211 // so mu = 0 for prach format < 4. @@ -750,10 +753,10 @@ void nr_initiate_ra_proc(module_id_t module_idP, NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; - uint32_t slot_RA = get_slot_RA(scc, rach_ConfigCommon, msgacc, cc->frame_type, slotP); uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL + uint32_t slot_RA = get_slot_RA(scc, rach_ConfigCommon, msgacc, cc->frame_type, slot); ra->RA_rnti = nr_get_ra_rnti(symbol, slot_RA, freq_index, ul_carrier_id); - if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { + if (msgacc) { ra->ra_type = RA_2_STEP; ra->ra_state = nrRA_WAIT_MsgA_PUSCH; ra->MsgB_rnti = nr_get_MsgB_rnti(symbol, slot_RA, freq_index, ul_carrier_id); @@ -762,18 +765,15 @@ void nr_initiate_ra_proc(module_id_t module_idP, ra->ra_state = nrRA_Msg2; } - int index = ra - cc->ra; - LOG_A(NR_MAC, "%d.%d UE RA-RNTI %04x TC-RNTI %04x: Activating RA process index %d\n", frameP, slotP, ra->RA_rnti, ra->rnti, index); + LOG_A(NR_MAC, "%d.%d UE RA-RNTI %04x TC-RNTI %04x: initiating RA procedure\n", frame, slot, ra->RA_rnti, UE->rnti); // Configure RA BWP - configure_UE_BWP(nr_mac, scc, NULL, ra, NULL, -1, -1); - + configure_UE_BWP(nr_mac, scc, UE, true, -1, -1); // return current SSB order in the list of tranmitted SSBs - int n_ssb = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol); - ra->beam_id = get_fapi_beamforming_index(nr_mac, cc->ssb_index[n_ssb]); + int n_ssb = ssb_index_from_prach(module_idP, frame, slot, preamble_index, freq_index, symbol); + UE->UE_beam_index = get_fapi_beamforming_index(nr_mac, cc->ssb_index[n_ssb]); NR_SCHED_UNLOCK(&nr_mac->sched_lock); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } @@ -796,14 +796,15 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, slot_t slot, - NR_RA_t *ra, + NR_UE_info_t *UE, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_RA_t *ra = UE->ra; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common; int mu = ul_bwp->scs; @@ -813,12 +814,12 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, const int sched_slot = (slot + K2) % slots_frame; if (is_ul_slot(sched_slot, &nr_mac->frame_structure)) { - NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, slots_frame); + NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame); if (beam_ul.idx < 0) return; - NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, ra->beam_id, slots_frame); + NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame); if (beam_dci.idx < 0) { - reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, slots_frame, beam_ul.new_beam); + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); return; } int fh = 0; @@ -849,7 +850,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, "%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", frame, slot, - ra->rnti, + UE->rnti, CC_id, sched_frame, sched_slot); @@ -871,12 +872,12 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); - fill_msg3_pusch_pdu(pusch_pdu, scc, ra, startSymbolAndLength, mu, BWPSize, BWPStart, mappingtype, fh); + fill_msg3_pusch_pdu(pusch_pdu, scc, UE, startSymbolAndLength, mu, BWPSize, BWPStart, mappingtype, fh); future_ul_tti_req->n_pdus += 1; // generation of DCI 0_0 to schedule msg3 retransmission - NR_SearchSpace_t *ss = ra->ra_ss; - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_SearchSpace_t *ss = UE->UE_sched_ctrl.search_space; + NR_ControlResourceSet_t *coreset = UE->UE_sched_ctrl.coreset; AssertFatal(coreset, "Coreset cannot be null for RA-Msg3 retransmission\n"); const int coresetid = coreset->controlResourceSetId; @@ -888,7 +889,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &UE->UE_sched_ctrl.sched_pdcch); nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } @@ -899,18 +900,18 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, beam_dci.idx, ss, coreset, - &ra->sched_pdcch, + &UE->UE_sched_ctrl.sched_pdcch, true, 0); if (CCEIndex < 0) { - LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", ra->rnti); + LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", UE->rnti); return; } // Fill PDCCH DL DCI PDU nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; pdcch_pdu_rel15->numDlDci++; - dci_pdu->RNTI = ra->rnti; + dci_pdu->RNTI = UE->rnti; dci_pdu->ScramblingId = *scc->physCellId; dci_pdu->ScramblingRNTI = 0; dci_pdu->AggregationLevel = aggregation_level; @@ -922,7 +923,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, dci_pdu->precodingAndBeamforming.prg_size = 0; dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; dci_pdu_rel15_t uldci_payload={0}; @@ -940,7 +941,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra->msg3_TPC = 1; fill_dci_pdu_rel15(sc_info, - &ra->DL_BWP, + &UE->current_DL_BWP, ul_bwp, dci_pdu, &uldci_payload, @@ -956,7 +957,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, fill_pdcch_vrb_map(nr_mac, CC_id, - &ra->sched_pdcch, + &UE->UE_sched_ctrl.sched_pdcch, CCEIndex, aggregation_level, beam_dci.idx); @@ -971,7 +972,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, K2, - ra->UL_BWP.scs); + ul_bwp->scs); // reset state to wait msg3 ra->ra_state = nrRA_WAIT_Msg3; @@ -987,6 +988,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, int slot, NR_RA_t *ra, NR_beam_info_t *beam_info, + int ue_beam_idx, const frame_structure_t *fs) { DevAssert(tda_list != NULL); @@ -1025,7 +1027,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, continue; // check if it is possible to allocate MSG3 in a beam in this slot - NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ra->beam_id, slots_per_frame); + NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ue_beam_idx, slots_per_frame); if (beam.idx < 0) continue; @@ -1040,14 +1042,15 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, return false; } -static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, frame_t current_frame, NR_RA_t *ra) +static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, frame_t current_frame, NR_UE_info_t *UE) { + NR_RA_t *ra = UE->ra; DevAssert(ra->Msg3_tda_id >= 0 && ra->Msg3_tda_id < 16); uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes - NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; const NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common; @@ -1056,7 +1059,7 @@ static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, fra LOG_I(NR_MAC, "UE %04x: Msg3 scheduled at %d.%d (%d.%d TDA %u)\n", - ra->rnti, + UE->rnti, ra->Msg3_frame, ra->Msg3_slot, current_frame, @@ -1101,7 +1104,7 @@ static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, fra static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, NR_ServingCellConfigCommon_t *scc, - const NR_RA_t *ra, + NR_UE_info_t *UE, int startSymbolAndLength, int scs, int bwp_size, @@ -1110,12 +1113,11 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, int fh) { int start_symbol_index,nr_of_symbols; - SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); int mcsindex = -1; // init value - + const NR_RA_t *ra = UE->ra; pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = ra->rnti; + pusch_pdu->rnti = UE->rnti; pusch_pdu->handle = 0; pusch_pdu->bwp_start = bwp_start; pusch_pdu->bwp_size = bwp_size; @@ -1169,7 +1171,7 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, pusch_pdu->beamforming.num_prgs = 0; pusch_pdu->beamforming.prg_size = 0; // bwp_size; pusch_pdu->beamforming.dig_bf_interface = 1; - pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; int num_dmrs_symb = 0; for(int i = start_symbol_index; i < start_symbol_index+nr_of_symbols; i++) @@ -1196,16 +1198,16 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, } } -static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) +static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, NR_UE_info_t *UE, uint8_t *RAR_pdu) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; - + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; + NR_RA_t *ra = UE->ra; if (ra->ra_state == nrRA_gNB_IDLE) { - LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti); + LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", UE->rnti); return; } @@ -1222,7 +1224,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] |= mask; } - LOG_D(NR_MAC, "UE %04x: %d.%d RA is active, Msg3 in (%d,%d)\n", ra->rnti, frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); + LOG_D(NR_MAC, "UE %04x: %d.%d RA is active, Msg3 in (%d,%d)\n", UE->rnti, frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, slots_frame, mac->UL_tti_req_ahead_size); nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][buffer_index]; AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame @@ -1244,7 +1246,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ LOG_D(NR_MAC, "UE %04x: %d.%d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n", - ra->rnti, + UE->rnti, frameP, slotP, ra->Msg3_frame, @@ -1253,18 +1255,18 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ ra->msg3_first_rb, ra->msg3_round); - fill_msg3_pusch_pdu(pusch_pdu, scc, ra, startSymbolAndLength, ul_bwp->scs, ibwp_size, ra->msg3_bwp_start, mappingtype, fh); + fill_msg3_pusch_pdu(pusch_pdu, scc, UE, startSymbolAndLength, ul_bwp->scs, ibwp_size, ra->msg3_bwp_start, mappingtype, fh); future_ul_tti_req->n_pdus += 1; // calling function to fill rar message - nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); + nr_fill_rar(module_idP, UE, RAR_pdu, pusch_pdu); } -static bool check_msg2_monitoring(const NR_RA_t *ra, int slots_per_frame, int current_frame, int current_slot) +static bool check_msg2_monitoring(const NR_SearchSpace_t *ss, int slots_per_frame, int current_frame, int current_slot) { // check if the slot is not among the PDCCH monitored ones (38.213 10.1) int monitoring_slot_period, monitoring_offset; - get_monitoring_period_offset(ra->ra_ss, &monitoring_slot_period, &monitoring_offset); + get_monitoring_period_offset(ss, &monitoring_slot_period, &monitoring_offset); if ((current_frame * slots_per_frame + current_slot - monitoring_offset) % monitoring_slot_period != 0) return false; return true; @@ -1334,8 +1336,7 @@ static bool msg2_in_response_window(int rach_frame, } static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, - NR_RA_t *ra, - NR_UE_DL_BWP_t *dl_bwp, + NR_UE_info_t *UE, nfapi_nr_dl_tti_request_body_t *dl_req, NR_sched_pucch_t *pucch, NR_pdsch_dmrs_t dmrs_info, @@ -1362,7 +1363,8 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, { // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; const int coresetid = coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; if (!pdcch_pdu_rel15) { @@ -1372,7 +1374,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &sched_ctrl->sched_pdcch); nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } @@ -1385,7 +1387,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; int mcsTableIdx = dl_bwp->mcsTableIdx; pdsch_pdu_rel15->pduBitmap = 0; @@ -1420,14 +1422,14 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pdsch_pdu_rel15->StartSymbolIndex = tda.startSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = tda.nrOfSymbols; pdsch_pdu_rel15->dlDmrsSymbPos = dmrs_info.dl_dmrs_symb_pos; - pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, ra->sc_info.dl_bw_tbslbrm, 1); + pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, UE->sc_info.dl_bw_tbslbrm, 1); pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(tb_size << 3, R); pdsch_pdu_rel15->precodingAndBeamforming.num_prgs = 1; pdsch_pdu_rel15->precodingAndBeamforming.prg_size = 275; pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1; pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; /* Fill PDCCH DL DCI PDU */ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; @@ -1444,7 +1446,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dci_pdu->precodingAndBeamforming.prg_size = 0; dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; dci_pdu_rel15_t dci_payload; dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, @@ -1490,15 +1492,15 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pdcch_pdu_rel15->DurationSymbols, pdsch_pdu_rel15->BWPSize); - fill_dci_pdu_rel15(&ra->sc_info, + fill_dci_pdu_rel15(&UE->sc_info, dl_bwp, - &ra->UL_BWP, + &UE->current_UL_BWP, &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], &dci_payload, NR_DL_DCI_FORMAT_1_0, rnti_type, dl_bwp->bwp_id, - ra->ra_ss, + sched_ctrl->search_space, coreset, 0, // parameter not needed for DCI 1_0 nr_mac->cset0_bwp_size); @@ -1524,7 +1526,7 @@ static void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, - NR_RA_t *ra, + NR_UE_info_t *UE, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req) { @@ -1536,28 +1538,30 @@ static void nr_generate_Msg2(module_id_t module_idP, } NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - + NR_RA_t *ra = UE->ra; long rrc_ra_ResponseWindow = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; if (!msg2_in_response_window(ra->preamble_frame, ra->preamble_slot, n_slots_frame, rrc_ra_ResponseWindow, frameP, slotP)) { - LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", ra->RA_rnti, ra->rnti); - nr_clear_ra_proc(ra); + LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", ra->RA_rnti, UE->rnti); + nr_release_ra_UE(nr_mac, UE->rnti); return; } - if (!check_msg2_monitoring(ra, n_slots_frame, frameP, slotP)) { - LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, ra->rnti); + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_SearchSpace_t *ss = sched_ctrl->search_space; + if (!check_msg2_monitoring(ss, n_slots_frame, frameP, slotP)) { + LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, UE->rnti); return; } - NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame); + NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame); if (beam.idx < 0) return; - const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; + const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; bool ret = get_feasible_msg3_tda(scc, DELTA[ul_bwp->scs], ul_bwp->tdaList_Common, @@ -1565,19 +1569,17 @@ static void nr_generate_Msg2(module_id_t module_idP, slotP, ra, &nr_mac->beam_info, + UE->UE_beam_index, &nr_mac->frame_structure); if (!ret || ra->Msg3_tda_id > 15) { - LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } int mcsIndex = -1; // initialization value int rbStart = 0; int rbSize = 8; - - NR_SearchSpace_t *ss = ra->ra_ss; - long BWPStart = 0; long BWPSize = 0; NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; @@ -1585,12 +1587,12 @@ static void nr_generate_Msg2(module_id_t module_idP, BWPStart = dl_bwp->BWPStart; BWPSize = sc_info->initial_dl_BWPSize; } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[ra->beam_id]]; + type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; BWPStart = type0_PDCCH_CSS_config->cset_start_rb; BWPSize = type0_PDCCH_CSS_config->num_rbs; } - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; AssertFatal(coreset, "Coreset cannot be null for RA-Msg2\n"); const int coresetid = coreset->controlResourceSetId; // Calculate number of symbols @@ -1617,34 +1619,34 @@ static void nr_generate_Msg2(module_id_t module_idP, if (rbStart > (BWPSize - rbSize)) { LOG_W(NR_MAC, "Cannot find free vrb_map for RA RNTI %04x!\n", ra->RA_rnti); - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } // Checking if the DCI allocation is feasible in current subframe nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { - LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } uint8_t aggregation_level; - int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &ra->sched_pdcch, true, 0); + int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &sched_ctrl->sched_pdcch, true, 0); if (CCEIndex < 0) { - LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } - bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, ra); + bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, UE); if (!msg3_ret) { - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } @@ -1653,14 +1655,14 @@ static void nr_generate_Msg2(module_id_t module_idP, // Distance calculation according to SCF222.10.02 RACH.indication (table 3-74) and 38.213 4.2/38.211 4.3.1 // T_c according to 38.211 4.1 float T_c_ns = 0.509; - int numerology = ra->UL_BWP.scs; + int numerology = ul_bwp->scs; float rtt_ns = T_c_ns * 16 * 64 / (1 << numerology) * ra->timing_offset; float speed_of_light_in_meters_per_second = 299792458.0f; float distance_in_meters = speed_of_light_in_meters_per_second * rtt_ns / 1000 / 1000 / 1000 / 2; LOG_A(NR_MAC, "UE %04x: %d.%d Generating RA-Msg2 DCI, RA RNTI 0x%x, state %d, preamble_index(RAPID) %d, " "timing_offset = %d (estimated distance %.1f [m])\n", - ra->rnti, + UE->rnti, frameP, slotP, ra->RA_rnti, @@ -1697,8 +1699,7 @@ static void nr_generate_Msg2(module_id_t module_idP, } prepare_dl_pdus(nr_mac, - ra, - dl_bwp, + UE, dl_req, NULL, dmrs_parms, @@ -1727,28 +1728,25 @@ static void nr_generate_Msg2(module_id_t module_idP, nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; // Program UL processing for Msg3 - nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); + nr_add_msg3(module_idP, CC_id, frameP, slotP, UE, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) // 3GPP TS 38.321 Section 5.1.5 Contention Resolution start_ra_contention_resolution_timer( ra, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, - *ra->UL_BWP.tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), - ra->UL_BWP.scs); + *ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), + ul_bwp->scs); if (ra->cfra) { - NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_idP]->UE_info, ra->rnti); - if (UE) { - int delay = nr_mac_get_reconfig_delay_slots(ra->DL_BWP.scs); - interrupt_followup_action_t action = UE->reconfigCellGroup ? FOLLOW_INSYNC_RECONFIG : FOLLOW_INSYNC; - nr_mac_interrupt_ue_transmission(RC.nrmac[module_idP], UE, action, delay); - } + int delay = nr_mac_get_reconfig_delay_slots(dl_bwp->scs); + interrupt_followup_action_t action = UE->reconfigCellGroup ? FOLLOW_INSYNC_RECONFIG : FOLLOW_INSYNC; + nr_mac_interrupt_ue_transmission(RC.nrmac[module_idP], UE, action, delay); } LOG_D(NR_MAC, "UE %04x: %d.%d: Setting RA-Msg3 reception (%s) for SFN.Slot %d.%d\n", - ra->rnti, + UE->rnti, frameP, slotP, ra->cfra ? "CFRA" : "CBRA", @@ -1775,7 +1773,7 @@ static void nr_generate_Msg2(module_id_t module_idP, T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length)); // Mark the corresponding symbols RBs as used - fill_pdcch_vrb_map(nr_mac, CC_id, &ra->sched_pdcch, CCEIndex, aggregation_level, beam.idx); + fill_pdcch_vrb_map(nr_mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, aggregation_level, beam.idx); for (int rb = 0; rb < rbSize; rb++) { vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); } @@ -1787,44 +1785,37 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, - NR_RA_t *ra, + NR_UE_info_t *UE, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; // if it is a DL slot, if the RA is in MSG4 state if (is_dl_slot(slotP, &nr_mac->frame_structure)) { NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_SearchSpace_t *ss = ra->ra_ss; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_SearchSpace_t *ss = sched_ctrl->search_space; + NR_RA_t *ra = UE->ra; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str); uint16_t mac_sdu_length = 0; - - NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti); - if (!UE) { - LOG_E(NR_MAC, "want to generate %s, but rnti %04x not in the table. Abort RA\n", ra_type_str, ra->rnti); - nr_clear_ra_proc(ra); - return; - } - - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ int current_harq_pid = sched_ctrl->retrans_dl_harq.head; logical_chan_id_t lcid = DL_SCH_LCID_CCCH; if (current_harq_pid < 0) { // Check for data on SRB0 (RRCSetup) - mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(ra->rnti, frameP, lcid); + mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); if (srb_status.bytes_in_buffer == 0) { lcid = DL_SCH_LCID_DCCH; // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration) - srb_status = nr_mac_rlc_status_ind(ra->rnti, frameP, lcid); + srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); } // Need to wait until data for Msg4 is ready @@ -1834,7 +1825,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; - NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame); + NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame); if (beam.idx < 0) return; @@ -1845,7 +1836,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, BWPStart = dl_bwp->BWPStart; BWPSize = dl_bwp->BWPSize; } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[ra->beam_id]]; + type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; BWPStart = type0_PDCCH_CSS_config->cset_start_rb; BWPSize = type0_PDCCH_CSS_config->num_rbs; } @@ -1858,21 +1849,21 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, beam.idx, ss, coreset, - &ra->sched_pdcch, + &sched_ctrl->sched_pdcch, true, 0); if (CCEIndex < 0) { - LOG_E(NR_MAC, "Cannot find free CCE for RA RNTI 0x%04x!\n", ra->rnti); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_E(NR_MAC, "Cannot find free CCE for RA RNTI 0x%04x!\n", UE->rnti); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } // Checking if the DCI allocation is feasible in current subframe nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { - LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } @@ -1935,18 +1926,18 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } if (rbStart > (BWPSize - rbSize)) { - LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", ra->rnti); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", UE->rnti); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } const int delta_PRI = 0; - int r_pucch = nr_get_pucch_resource(coreset, ra->UL_BWP.pucch_Config, CCEIndex); + int r_pucch = nr_get_pucch_resource(coreset, UE->current_UL_BWP.pucch_Config, CCEIndex); LOG_D(NR_MAC, "Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI); - int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, ra->beam_id, r_pucch, 1); + int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, UE->UE_beam_index, r_pucch, 1); if (alloc < 0) { LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n", frameP, slotP); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } @@ -1974,10 +1965,10 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, uint16_t mac_pdu_length = 0; if (ra->ra_type == RA_4_STEP) { // UE Contention Resolution Identity MAC CE - mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); + mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, sched_ctrl, buf, 255, ra->cont_res_id); } else if (ra->ra_type == RA_2_STEP) { - mac_pdu_length = nr_fill_successrar(nr_mac->sched_ctrlCommon, - ra->rnti, + mac_pdu_length = nr_fill_successrar(sched_ctrl, + UE->rnti, ra->cont_res_id, pucch->resource_indicator, pucch->timing_indicator, @@ -1990,7 +1981,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, uint8_t buffer[CCCH_SDU_SIZE]; uint8_t mac_subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT); // Get RLC data on the SRB (RRCSetup, RRCReestablishment) - mac_sdu_length = nr_mac_rlc_data_req(module_idP, ra->rnti, true, lcid, CCCH_SDU_SIZE, (char *)buffer); + mac_sdu_length = nr_mac_rlc_data_req(module_idP, UE->rnti, true, lcid, CCCH_SDU_SIZE, (char *)buffer); if (mac_sdu_length < 256) { ((NR_MAC_SUBHEADER_SHORT *)&buf[mac_pdu_length])->R = 0; @@ -2009,12 +2000,11 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, memcpy(&buf[mac_pdu_length + mac_subheader_len], buffer, mac_sdu_length); } - rnti_t rnti = ra->ra_type == RA_4_STEP ? ra->rnti : ra->MsgB_rnti; + rnti_t rnti = ra->ra_type == RA_4_STEP ? UE->rnti : ra->MsgB_rnti; const int pduindex = nr_mac->pdu_index[CC_id]++; prepare_dl_pdus(nr_mac, - ra, - dl_bwp, + UE, dl_req, pucch, dmrs_info, @@ -2052,7 +2042,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } } - T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti), + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(UE->rnti), T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, harq->tb_size)); // DL TX request @@ -2069,7 +2059,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, CC_id, - &ra->sched_pdcch, + &sched_ctrl->sched_pdcch, CCEIndex, aggregation_level, beam.idx); @@ -2080,7 +2070,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, ra->ra_state = nrRA_WAIT_Msg4_MsgB_ACK; LOG_I(NR_MAC, "UE %04x Generate %s: feedback at %4d.%2d, payload %d bytes, next state nrRA_WAIT_Msg4_MsgB_ACK\n", - ra->rnti, + UE->rnti, ra_type_str, pucch->frame, pucch->ul_slot, @@ -2088,67 +2078,47 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } } -static void nr_check_Msg4_MsgB_Ack(module_id_t module_id, int CC_id, frame_t frame, slot_t slot, NR_RA_t *ra) +void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success) { + NR_RA_t *ra = UE->ra; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; - NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti); - if (!UE) { - LOG_E(NR_MAC, "Cannot check %s ACK/NACK, rnti %04x not in the table\n", ra_type_str, ra->rnti); - return; - } const int current_harq_pid = ra->harq_pid; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - LOG_D(NR_MAC, "ue rnti 0x%04x, harq is waiting %d, round %d, frame %d %d, harq id %d\n", ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid); + LOG_D(NR_MAC, "ue rnti 0x%04x, round %d, frame %d %d, harq id %d\n", UE->rnti, harq->round, frame, slot, current_harq_pid); - if (harq->is_waiting == 0) { - if (harq->round == 0) { - if (UE->Msg4_MsgB_ACKed) { - LOG_A(NR_MAC, - "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", - frame, slot, ra->rnti, ra_type_str); - } else { - LOG_I(NR_MAC, - "%4d.%2d UE %04x: RA Procedure failed at %s!\n", - frame, slot, ra->rnti, ra_type_str); - nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - } - - // Pause scheduling according to: - // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs - // Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3. - // In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack, - // UE->reconfigCellGroup already set when processing RRCReestablishment message - int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs); - nr_mac_interrupt_ue_transmission(RC.nrmac[module_id], UE, UE->interrupt_action, delay); - - nr_clear_ra_proc(ra); - if (sched_ctrl->retrans_dl_harq.head >= 0) { - remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); - } + if (harq->round == 0) { + if (success) { + LOG_A(NR_MAC, "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", frame, slot, UE->rnti, ra_type_str); } else { - LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", ra->rnti, ra_type_str); - ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; + LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at %s!\n", frame, slot, UE->rnti, ra_type_str); + nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); } + + // Pause scheduling according to: + // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs + // Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3. + // In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack, + // UE->reconfigCellGroup already set when processing RRCReestablishment message + int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs); + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + nr_mac_interrupt_ue_transmission(nr_mac, UE, UE->interrupt_action, delay); + if (!transition_ra_connected_nr_ue(nr_mac, UE)) { + LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator); + return; + } + if (sched_ctrl->retrans_dl_harq.head >= 0) { + remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); + } + } else { + LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", UE->rnti, ra_type_str); + ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; } } -void nr_clear_ra_proc(NR_RA_t *ra) -{ - /* we assume that this function is mutex-protected from outside */ - NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock); - memset(ra, 0, sizeof(*ra)); - ra->ra_state = nrRA_gNB_IDLE; - if (IS_SA_MODE(get_softmodem_params())) { // in SA, prefill with allowed preambles - ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; - for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) - ra->preambles.preamble_list[i] = i; - } -} - - ///////////////////////////////////// // Random Access Response PDU // // TS 38.213 ch 8.2 // @@ -2179,9 +2149,15 @@ void nr_clear_ra_proc(NR_RA_t *ra) // - sending only 1 RAR subPDU // - UL Grant: hardcoded CSI, TPC, time alloc // - padding -static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu) +static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu) { - LOG_D(NR_MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index, ra->timing_offset); + NR_RA_t *ra = UE->ra; + LOG_D(NR_MAC, + "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", + ra->Msg2_frame, + ra->Msg2_slot, + ra->preamble_index, + ra->timing_offset); NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer; NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1); NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 2); @@ -2212,8 +2188,8 @@ static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfa rar->TA2 = (uint8_t) (ra->timing_offset & 0x1f); // 5 LSBs of timing advance // TC-RNTI - rar->TCRNTI_1 = (uint8_t) (ra->rnti >> 8); // 8 MSBs of rnti - rar->TCRNTI_2 = (uint8_t) (ra->rnti & 0xff); // 8 LSBs of rnti + rar->TCRNTI_1 = (uint8_t) (UE->rnti >> 8); // 8 MSBs of rnti + rar->TCRNTI_2 = (uint8_t) (UE->rnti & 0xff); // 8 LSBs of rnti // UL grant @@ -2263,6 +2239,22 @@ static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfa ra->msg3_TPC = 1; } +/** @brief remove the UE with RNTI rnti from list of UEs doing RA. + * + * The corresponding function to add is add_new_UE_RA(). */ +void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti) +{ + NR_UEs_t *UE_info = &mac->UE_info; + NR_SCHED_LOCK(&UE_info->mutex); + NR_UE_info_t *UE = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, rnti); + NR_SCHED_UNLOCK(&UE_info->mutex); + if (UE) { + delete_nr_ue_data(UE, mac->common_channels, &UE_info->uid_allocator); + } else { + LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); + } +} + void nr_schedule_RA(module_id_t module_idP, frame_t frameP, slot_t slotP, @@ -2276,38 +2268,33 @@ void nr_schedule_RA(module_id_t module_idP, start_meas(&mac->schedule_ra); for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; + UE_iterator(mac->UE_info.access_ue_list, UE) { + NR_RA_t *ra = UE->ra; if (ra->ra_state != nrRA_gNB_IDLE) - LOG_D(NR_MAC, "RA[%d] frame.slot %d.%d state: %d\n", i, frameP, slotP, ra->ra_state); + LOG_D(NR_MAC, "UE %04x frame.slot %d.%d RA state: %d\n", UE->rnti, frameP, slotP, ra->ra_state); - // Check RA Contention Resolution timer - if (ra->ra_type == RA_4_STEP && ra->ra_state >= nrRA_WAIT_Msg3) { + // Check RA Contention Resolution timer (TODO check this procedure) + if (ra->ra_type == RA_4_STEP && ra->ra_state > nrRA_WAIT_Msg3) { ra->contention_resolution_timer--; if (ra->contention_resolution_timer < 0) { - LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, ra->rnti); - bool requested = nr_mac_request_release_ue(mac, ra->rnti); + LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, UE->rnti); + bool requested = nr_mac_request_release_ue(mac, UE->rnti); if (!requested) - nr_mac_release_ue(mac, ra->rnti); - nr_clear_ra_proc(ra); + nr_release_ra_UE(mac, UE->rnti); continue; } } switch (ra->ra_state) { case nrRA_Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, UE, DL_req, TX_req); break; case nrRA_Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, UE, ul_dci_req); break; case nrRA_Msg4: case nrRA_MsgB: - nr_generate_Msg4_MsgB(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - break; - case nrRA_WAIT_Msg4_MsgB_ACK: - nr_check_Msg4_MsgB_Ack(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg4_MsgB(module_idP, CC_id, frameP, slotP, UE, DL_req, TX_req); break; default: break; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c6054eeefd..226fe80dbb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -609,9 +609,6 @@ static void pf_dl(module_id_t module_id, /* Loop UE_info->list to check retransmission */ UE_iterator(UE_list, UE) { - if (!UE->Msg4_MsgB_ACKed) - continue; - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 68d27be46a..cb4592b4eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2060,7 +2060,6 @@ void remove_front_nr_list(NR_list_t *listP) NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP) { - UE_iterator(UEs->connected_ue_list, UE) { if (UE->rnti == rntiP) { LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP); @@ -2070,6 +2069,17 @@ NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP) return NULL; } +NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP) +{ + UE_iterator(UEs->access_ue_list, UE) { + if (UE->rnti == rntiP) { + LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP); + return UE; + } + } + return NULL; +} + void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia) { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); @@ -2088,6 +2098,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca free_sched_pucch_list(sched_ctrl); uid_linear_allocator_free(uia, UE->uid); LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti); + free(UE->ra); free(UE); } @@ -2195,31 +2206,16 @@ static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, // main function to configure parameters of current BWP void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, - NR_UE_sched_ctrl_t *sched_ctrl, - NR_RA_t *ra, NR_UE_info_t *UE, + bool is_RA, int dl_bwp_switch, int ul_bwp_switch) { - AssertFatal((ra != NULL && UE == NULL) || (ra == NULL && UE != NULL), "RA and UE structures are mutually exlusive in BWP configuration\n"); + NR_CellGroupConfig_t *CellGroup = UE->CellGroup; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; + NR_UE_DL_BWP_t *DL_BWP = &UE->current_DL_BWP; + NR_UE_UL_BWP_t *UL_BWP = &UE->current_UL_BWP; - NR_CellGroupConfig_t *CellGroup; - NR_UE_ServingCell_Info_t *sc_info; - NR_UE_DL_BWP_t *DL_BWP; - NR_UE_UL_BWP_t *UL_BWP; - - if (ra) { - DL_BWP = &ra->DL_BWP; - UL_BWP = &ra->UL_BWP; - CellGroup = ra->CellGroup; - sc_info = &ra->sc_info; - } - else { - DL_BWP = &UE->current_DL_BWP; - UL_BWP = &UE->current_UL_BWP; - CellGroup = UE->CellGroup; - sc_info = &UE->sc_info; - } NR_BWP_Downlink_t *dl_bwp = NULL; NR_BWP_Uplink_t *ul_bwp = NULL; NR_BWP_DownlinkDedicated_t *bwpd = NULL; @@ -2229,13 +2225,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, sc_info->n_ul_bwp = 0; int old_dl_bwp_id = DL_BWP->bwp_id; int old_ul_bwp_id = UL_BWP->bwp_id; - int target_ss; NR_ServingCellConfig_t *servingCellConfig = NULL; - if (CellGroup && - CellGroup->spCellConfig && - CellGroup->spCellConfig->spCellConfigDedicated) { + if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) { servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated; target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; @@ -2359,7 +2352,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, UL_BWP->rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; } - if(UE) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + // Reset required fields in sched_ctrl (e.g. ul_ri and tpmi) + reset_sched_ctrl(sched_ctrl); + if(!is_RA) { if (servingCellConfig) { if (servingCellConfig->csi_MeasConfig) { sc_info->csi_MeasConfig = servingCellConfig->csi_MeasConfig->choice.setup; @@ -2403,18 +2399,9 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, if (CellGroup && CellGroup->physicalCellGroupConfig) UE->pdsch_HARQ_ACK_Codebook = CellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook; - // Reset required fields in sched_ctrl (e.g. ul_ri and tpmi) - reset_sched_ctrl(sched_ctrl); - // setting PDCCH related structures for sched_ctrl - sched_ctrl->search_space = get_searchspace(scc, - bwpd, - target_ss); - sched_ctrl->coreset = get_coreset(nr_mac, - scc, - bwpd, - sched_ctrl->search_space, - target_ss); + sched_ctrl->search_space = get_searchspace(scc, bwpd, target_ss); + sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, sched_ctrl->search_space, target_ss); sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac, sched_ctrl->search_space, @@ -2436,11 +2423,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0) : NR_UL_DCI_FORMAT_0_0; - set_max_fb_time(UL_BWP, DL_BWP); - set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure); - } - - if(ra) { + } else { // setting PDCCH related structures for RA struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = NULL; NR_SearchSpaceId_t ra_SearchSpace = 0; @@ -2453,26 +2436,29 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, } AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - NR_SearchSpace_t * ss = commonSearchSpaceList->list.array[i]; + NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i]; if (ss->searchSpaceId == ra_SearchSpace) - ra->ra_ss = ss; + sched_ctrl->search_space = ss; } - AssertFatal(ra->ra_ss!=NULL,"SearchSpace cannot be null for RA\n"); + AssertFatal(sched_ctrl->search_space != NULL, "SearchSpace cannot be null for RA\n"); - ra->coreset = get_coreset(nr_mac, scc, dl_bwp, ra->ra_ss, NR_SearchSpace__searchSpaceType_PR_common); + sched_ctrl->coreset = get_coreset(nr_mac, scc, dl_bwp, sched_ctrl->search_space, NR_SearchSpace__searchSpaceType_PR_common); NR_COMMON_channels_t *cc = &nr_mac->common_channels[0]; - int ssb_index = cc->ssb_index[ra->beam_id]; - ra->sched_pdcch = set_pdcch_structure(nr_mac, - ra->ra_ss, - ra->coreset, - scc, - &dl_genericParameters, - &nr_mac->type0_PDCCH_CSS_config[ssb_index]); + int ssb_index = cc->ssb_index[UE->UE_beam_index]; + sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac, + sched_ctrl->search_space, + sched_ctrl->coreset, + scc, + &dl_genericParameters, + &nr_mac->type0_PDCCH_CSS_config[ssb_index]); UL_BWP->dci_format = NR_UL_DCI_FORMAT_0_0; DL_BWP->dci_format = NR_DL_DCI_FORMAT_1_0; } + set_max_fb_time(UL_BWP, DL_BWP); + set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure); + // Set MCS tables long *dl_mcs_Table = DL_BWP->pdsch_Config ? DL_BWP->pdsch_Config->mcs_Table : NULL; DL_BWP->mcsTableIdx = get_pdsch_mcs_table(dl_mcs_Table, DL_BWP->dci_format, TYPE_C_RNTI_, target_ss); @@ -2482,9 +2468,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, // Set uplink MCS table long *mcs_Table = NULL; if (UL_BWP->pusch_Config) - mcs_Table = UL_BWP->transform_precoding ? - UL_BWP->pusch_Config->mcs_Table : - UL_BWP->pusch_Config->mcs_TableTransformPrecoder; + mcs_Table = UL_BWP->transform_precoding ? UL_BWP->pusch_Config->mcs_Table : UL_BWP->pusch_Config->mcs_TableTransformPrecoder; UL_BWP->mcs_table = get_pusch_mcs_table(mcs_Table, !UL_BWP->transform_precoding, UL_BWP->dci_format, TYPE_C_RNTI_, target_ss, false); } @@ -2502,49 +2486,29 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f; } -//------------------------------------------------------------------------------ -NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup) +/* @brief returns a new UE allocated instance. + * + * It will be typically added to the access_ue_list, but not always (e.g., + * phytest mode), so this is not done in this function (and also, to allow + * error handling). Remove with delete_nr_ue_data(). */ +NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup) { - NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; - NR_UEs_t *UE_info = &nr_mac->UE_info; - LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", rntiP); - dump_nr_list(UE_info->connected_ue_list); - - // We will attach at the end, to mitigate race conditions - // This is not good, but we will fix it progressively - NR_UE_info_t *UE = calloc(1, sizeof(NR_UE_info_t)); - if(!UE) { - LOG_E(NR_MAC,"want to add UE %04x but the fixed allocated size is full\n",rntiP); + uid_t uid = uid_linear_allocator_new(uia); + /* if the UE list is full, we should reject the UE with an RRC reject + * message, but we do not have this functionality. To keep it simple, do not + * create a UE context here, so we can print an error message. */ + if (uid >= MAX_MOBILES_PER_GNB) { + uid_linear_allocator_free(uia, uid); return NULL; } - UE->rnti = rntiP; - UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator); + NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t)); + UE->rnti = rnti; UE->CellGroup = CellGroup; - - UE->Msg4_MsgB_ACKed = CellGroup != NULL; - + UE->uid = uid; + UE->ra = calloc(1, sizeof(*UE->ra)); NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - memset(sched_ctrl, 0, sizeof(*sched_ctrl)); - sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */ sched_ctrl->ta_update = 31; - sched_ctrl->sched_srs.frame = -1; - sched_ctrl->sched_srs.slot = -1; - sched_ctrl->pdcch_cl_adjust = 0; - - // Initialize bler_stats - init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame); - init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame); - - // initialize LCID structure - seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t)); - - // initialize UE BWP information - NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; - memset(dl_bwp, 0, sizeof(*dl_bwp)); - NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - memset(ul_bwp, 0, sizeof(*ul_bwp)); - configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, -1, -1); /* set illegal time domain allocation to force recomputation of all fields */ sched_ctrl->sched_pdsch.time_domain_allocation = -1; @@ -2558,27 +2522,87 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf create_dl_harq_list(sched_ctrl, &UE->sc_info); create_ul_harq_list(sched_ctrl, &UE->sc_info); - reset_srs_stats(UE); + // initialize LCID structure + seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t)); + return UE; +} - NR_SCHED_LOCK(&UE_info->mutex); - int i; - for(i=0; iconnected_ue_list[i] == NULL) { - UE_info->connected_ue_list[i] = UE; - break; +bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE) +{ + for (int i = 0; i < list_size; i++) { + if (!list[i]) { + list[i] = UE; + return true; } } - if (i == MAX_MOBILES_PER_GNB) { - LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", rntiP); - delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); - NR_SCHED_UNLOCK(&UE_info->mutex); - return NULL; - } - NR_SCHED_UNLOCK(&UE_info->mutex); + return false; +} - LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP); +NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti) +{ + for (int i = 0; i < list_size; i++) { + NR_UE_info_t *curr_UE = list[i]; + if (curr_UE->rnti != rnti) + continue; + + /* remove this UE from the list, return the pointer */ + memmove(&list[i], &list[i+1], sizeof(list[0]) * (list_size - i - 1)); + list[list_size - 1] = NULL; + return curr_UE; + } + LOG_E(NR_MAC, "UE %04x to be removed not found in list\n", rnti); + return NULL; +} + +/** @brief Transitions a UE from access list to connected list (i.e., the RA + * list to the "normal" UE context list. */ +bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) +{ + NR_UEs_t *UE_info = &nr_mac->UE_info; + + // remove UE from initial access list (moved to connected mode) + NR_UE_info_t *r = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, UE->rnti); + DevAssert(r == UE); /* sanity check: we should have removed the current UE ptr from list */ + + free_and_zero(UE->ra); + + return add_connected_nr_ue(nr_mac, UE); +} + +/** @brief Add a UE to the list of UEs in * connected mode. + * + * To remove the UE, use mac_remove_nr_ue(). */ +bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) +{ + LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", UE->rnti); + NR_UEs_t *UE_info = &nr_mac->UE_info; dump_nr_list(UE_info->connected_ue_list); - return (UE); + AssertFatal(!UE->ra, "UE in connected cannot have RA process\n"); + + NR_SCHED_LOCK(&UE_info->mutex); + + bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE); + if (!success) { + LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &UE_info->uid_allocator); + NR_SCHED_UNLOCK(&UE_info->mutex); + return false; + } + + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */ + sched_ctrl->sched_srs.frame = -1; + sched_ctrl->sched_srs.slot = -1; + sched_ctrl->pdcch_cl_adjust = 0; + reset_srs_stats(UE); + + // Initialize bler_stats + init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame); + init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame); + + NR_SCHED_UNLOCK(&UE_info->mutex); + dump_nr_list(UE_info->connected_ue_list); + return true; } void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl) @@ -2683,38 +2707,11 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) { /* already mutex protected */ NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); - NR_UEs_t *UE_info = &nr_mac->UE_info; NR_SCHED_LOCK(&UE_info->mutex); - UE_iterator(UE_info->connected_ue_list, UE) { - if (UE->rnti==rnti) - break; - } - - if (!UE) { - LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); - NR_SCHED_UNLOCK(&UE_info->mutex); - return; - } - - NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0}; - int newListIdx = 0; - for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) - if(UE_info->connected_ue_list[i] && UE_info->connected_ue_list[i]->rnti != rnti) - newUEs[newListIdx++] = UE_info->connected_ue_list[i]; - memcpy(UE_info->connected_ue_list, newUEs, sizeof(UE_info->connected_ue_list)); + NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti); NR_SCHED_UNLOCK(&UE_info->mutex); - const int CC_id = 0; - NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; - if (ra->rnti == UE->rnti) { - nr_clear_ra_proc(ra); - ra->cfra = 0; - } - } - delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); } @@ -3071,7 +3068,7 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); + configure_UE_BWP(mac, scc, UE, false, -1, -1); reset_srs_stats(UE); @@ -3519,24 +3516,14 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid) return true; } -static const NR_RA_t *find_nr_RA_rnti(const NR_RA_t *ra_base, int ra_count, rnti_t rnti) -{ - for (int i = 0; i < ra_count; ++i) { - const NR_RA_t *ra = &ra_base[i]; - if (ra->ra_state != nrRA_gNB_IDLE && ra->rnti == rnti) - return ra; - } - return NULL; -} - -bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti) +bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti) { int loop = 0; bool exist_connected_ue, exist_in_pending_ra_ue; do { *rnti = (taus() % 0xffef) + 1; exist_connected_ue = find_nr_UE(UEs, *rnti) != NULL; - exist_in_pending_ra_ue = find_nr_RA_rnti(ra_base, ra_count, *rnti) != NULL; + exist_in_pending_ra_ue = find_ra_UE(UEs, *rnti) != NULL; loop++; } while (loop < 100 && (exist_connected_ue || exist_in_pending_ra_ue)); return loop < 100; // nothing found: loop count 100 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 5254ff5b59..29ff27d38e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -171,39 +171,54 @@ static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size; } -void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP) +static void schedule_pucch_core(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, frame_t frame, slot_t slot) +{ + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + const int pucch_index = get_pucch_index(frame, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); + NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; + if (!curr_pucch->active) + return; + if (frame != curr_pucch->frame || slot != curr_pucch->ul_slot) { + LOG_E(NR_MAC, + "PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n", + curr_pucch->frame, + curr_pucch->ul_slot, + frame, + slot); + memset(curr_pucch, 0, sizeof(*curr_pucch));; + return; + } + + const uint16_t O_ack = curr_pucch->dai_c; + const uint16_t O_csi = curr_pucch->csi_bits; + const uint8_t O_sr = curr_pucch->sr_flag; + LOG_D(NR_MAC, + "Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", + pucch_index, + UE->rnti, + curr_pucch->frame, + curr_pucch->ul_slot, + O_ack,O_sr, + O_csi); + nr_fill_nfapi_pucch(nrmac, frame, slot, curr_pucch, UE); + memset(curr_pucch, 0, sizeof(*curr_pucch)); +} + +void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot) { /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - if (!is_ul_slot(slotP, &nrmac->frame_structure)) + if (!is_ul_slot(slot, &nrmac->frame_structure)) return; + UE_iterator(nrmac->UE_info.access_ue_list, init_UE) { + if (init_UE->ra->ra_state == nrRA_WAIT_Msg4_MsgB_ACK) + schedule_pucch_core(nrmac, init_UE, frame, slot); + } + UE_iterator(nrmac->UE_info.connected_ue_list, UE) { - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); - NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; - if (!curr_pucch->active) - continue; - if (frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) { - LOG_E(NR_MAC, - "PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n", - curr_pucch->frame, - curr_pucch->ul_slot, - frameP, - slotP); - memset(curr_pucch, 0, sizeof(*curr_pucch));; - continue; - } - - const uint16_t O_ack = curr_pucch->dai_c; - const uint16_t O_csi = curr_pucch->csi_bits; - const uint8_t O_sr = curr_pucch->sr_flag; - LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", - pucch_index,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi); - nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE); - memset(curr_pucch, 0, sizeof(*curr_pucch)); - + schedule_pucch_core(nrmac, UE, frame, slot); } } @@ -854,14 +869,19 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; int rssi_threshold = nrmac->pucch_rssi_threshold; NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); + NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); + bool is_ra = false; if (!UE) { - LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); - NR_SCHED_UNLOCK(&nrmac->sched_lock); - return; + UE = find_ra_UE(&nrmac->UE_info, uci_01->rnti); + if (UE) + is_ra = true; + else { + LOG_E(NR_MAC, "Unknown RNTI %04x in PUCCH UCI\n", uci_01->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return; + } } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (((uci_01->pduBitmap >> 1) & 0x01)) { // iterate over received harq bits for (int harq_bit = 0; harq_bit < uci_01->harq.num_harq; harq_bit++) { @@ -877,10 +897,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con remove_front_nr_list(&sched_ctrl->feedback_dl_harq); LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value); nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0); - handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max); - if (!UE->Msg4_MsgB_ACKed && harq_value == 0 && harq_confidence == 0) - UE->Msg4_MsgB_ACKed = true; - if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; + bool success = harq_value == 0 && harq_confidence == 0; + handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max); + if (is_ra) + nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success); + if (harq_confidence == 1) + UE->mac_stats.pucch0_DTX++; } // tpc (power control) only if we received AckNack diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index cbbcbd00a9..5ca2b69151 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -461,17 +461,13 @@ static int nr_process_mac_pdu(instance_t module_idP, break; case UL_SCH_LCID_C_RNTI: - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; - if (ra->ra_state == nrRA_gNB_IDLE && ra->rnti == UE->rnti) { - // Extract C-RNTI value - rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF); - AssertFatal(false, - "Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the " - "MAC PDU?\n", - crnti); - break; - } + if (UE->ra && UE->ra->ra_state == nrRA_gNB_IDLE) { + // Extract C-RNTI value + rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF); + AssertFatal(false, + "Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the " + "MAC PDU?\n", + crnti); } break; @@ -547,24 +543,7 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } -static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, - const int CC_id, - const frame_t frame, - const slot_t slot, - rnti_t rnti) -{ - bool UE_waiting_CFRA_msg3 = false; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i]; - if (ra->cfra && ra->ra_state == nrRA_WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot && rnti == ra->rnti) { - UE_waiting_CFRA_msg3 = true; - break; - } - } - return UE_waiting_CFRA_msg3; -} - -void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu) +void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu) { gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; if (nrmac->radio_config.disable_harq) { @@ -573,12 +552,13 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot } NR_SCHED_LOCK(&nrmac->sched_lock); - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i]; + NR_UEs_t *UE_info = &nrmac->UE_info; + UE_iterator(UE_info->access_ue_list, ra_UE) { + const NR_RA_t *ra = ra_UE->ra; // if we find any ongoing RA that has already scheduled MSG3 // and it is expecting its reception in current frame and slot with matching RNTI // we can exit the function (no HARQ involved) - if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { + if (ra->ra_state >= nrRA_WAIT_Msg3 && ra_UE->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti); NR_SCHED_UNLOCK(&nrmac->sched_lock); return; @@ -586,6 +566,7 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot } NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); + UE = UE ? UE : find_ra_UE(&nrmac->UE_info, crc_pdu->rnti); if (!UE) { NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n"); @@ -641,29 +622,56 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot NR_SCHED_UNLOCK(&nrmac->sched_lock); } -static void handle_msg3_failed_rx(NR_RA_t *ra, int i, int harq_round_max) +static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max) { // for CFRA (NSA) do not schedule retransmission of msg3 if (ra->cfra) { - LOG_D(NR_MAC, "Random Access %i failed at state %s (NSA msg3 reception failed)\n", i, nrra_text[ra->ra_state]); - nr_clear_ra_proc(ra); + LOG_W(NR_MAC, "UE %04x RA failed at state %s (NSA msg3 reception failed)\n", rnti, nrra_text[ra->ra_state]); + nr_release_ra_UE(mac, rnti); return; } if (ra->msg3_round >= harq_round_max - 1) { - LOG_W(NR_MAC, "Random Access %i failed at state %s (Reached msg3 max harq rounds)\n", i, nrra_text[ra->ra_state]); - nr_clear_ra_proc(ra); + LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]); + nr_release_ra_UE(mac, rnti); return; } - LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass\n", i); + LOG_D(NR_MAC, "UE %04x Msg3 CRC did not pass\n", rnti); ra->msg3_round++; ra->ra_state = nrRA_Msg3_retransmission; } -/* -* When data are received on PHY and transmitted to MAC -*/ +static NR_UE_info_t *configure_UE_crnti_msg3(gNB_MAC_INST *mac, NR_UE_info_t *old_UE, NR_UE_info_t *new_UE) +{ + // in case UE beam has changed + old_UE->UE_beam_index = new_UE->UE_beam_index; + // Reset UL failure for old UE + nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl); + // Reset HARQ processes + reset_dl_harq_list(&old_UE->UE_sched_ctrl); + reset_ul_harq_list(&old_UE->UE_sched_ctrl); + // old UE need to complete RA by sending DL + free_and_zero(old_UE->ra); + old_UE->ra = new_UE->ra; + new_UE->ra = NULL; + NR_UE_sched_ctrl_t *sched_ctrl = &old_UE->UE_sched_ctrl; + sched_ctrl->search_space = new_UE->UE_sched_ctrl.search_space; + sched_ctrl->coreset = new_UE->UE_sched_ctrl.coreset; + memcpy(&sched_ctrl->sched_pdcch, &new_UE->UE_sched_ctrl.sched_pdcch, sizeof(NR_sched_pdcch_t)); + old_UE->current_DL_BWP.dci_format = NR_DL_DCI_FORMAT_1_0; + // replace new UE with old UE in the access list + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + if (mac->UE_info.access_ue_list[i] && mac->UE_info.access_ue_list[i]->rnti == new_UE->rnti) { + mac->UE_info.access_ue_list[i] = old_UE; + break; + } + } + // remove new UE + delete_nr_ue_data(new_UE, mac->common_channels, &mac->UE_info.uid_allocator); + return old_UE; +} + static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const int CC_idP, const frame_t frameP, @@ -685,9 +693,8 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const int pusch_failure_thres = gNB_mac->pusch_failure_thres; NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); - bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(gNB_mac, CC_idP, frameP, slotP, current_rnti); - if (UE && UE_waiting_CFRA_msg3 == false) { + if (UE) { NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; @@ -791,74 +798,45 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } } - } else if (sduP) { - - bool no_sig = true; - for (uint32_t k = 0; k < sdu_lenP; k++) { - if (sduP[k] != 0) { - no_sig = false; - break; - } + } else { + UE = find_ra_UE(&gNB_mac->UE_info, current_rnti); + if (!UE) { + LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", current_rnti); + return; } + NR_RA_t *ra = UE->ra; + if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) { + LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti); + return; + } + if (sduP) { + bool no_sig = true; + for (uint32_t k = 0; k < sdu_lenP; k++) { + if (sduP[k] != 0) { + no_sig = false; + break; + } + } - T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), - T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, - T_BUFFER(sduP, sdu_lenP)); + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, + T_BUFFER(sduP, sdu_lenP)); - /* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3) - * and check the corresponding UE's RNTI match, in which case we activate - * it. */ - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; - if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) - continue; if (no_sig) { - LOG_W(NR_MAC, "Random Access %i ULSCH with no signal\n", i); - handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max); - continue; + LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n"); + handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max); + return; } if (ra->ra_type == RA_2_STEP) { // random access pusch with RA-RNTI if (ra->RA_rnti != current_rnti) { LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, current_rnti); - continue; - } - } else { - // random access pusch with TC-RNTI - if (ra->rnti != current_rnti) { - LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti); - - if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot)) { - LOG_W(NR_MAC, - "Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n", - i, - nrra_text[ra->ra_state], - ra->rnti, - current_rnti); - nr_clear_ra_proc(ra); - } - - continue; + return; } } - UE = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup); - if (!UE) { - LOG_W(NR_MAC, - "Random Access %i discarded at state %s (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", - i, - nrra_text[ra->ra_state], - ra->rnti, - current_rnti); - - nr_clear_ra_proc(ra); - return; - } - - UE->UE_beam_index = ra->beam_id; - - // re-initialize ta update variables after RA procedure completion + // re-initialize ta update variables after RA procedure completion UE->UE_sched_ctrl.ta_frame = frameP; LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti); @@ -873,12 +851,16 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, UE_scheduling_control->raw_rssi = rssi; LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); if (ra->cfra) { - LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti); + LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); nr_mac_reset_ul_failure(UE_scheduling_control); reset_dl_harq_list(UE_scheduling_control); reset_ul_harq_list(UE_scheduling_control); - process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList); - nr_clear_ra_proc(ra); + process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList); + if (!transition_ra_connected_nr_ue(gNB_mac, UE)) { + LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &gNB_mac->UE_info.uid_allocator); + return; + } } else { LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); for (uint32_t k = 0; k < sdu_lenP; k++) { @@ -892,40 +874,20 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // Search for MAC CE for C-RNTI rnti_t crnti = lcid_crnti_lookahead(sduP, sdu_lenP); if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A - // this UE is the one identified by the RNTI in sduP - ra->rnti = crnti; - // Remove UE context just created after Msg.3 in some milliseconds as the UE is one already known (not now, as the UE - // context is still needed for the moment) - nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); - // Replace the current UE by the UE identified by C-RNTI - UE = find_nr_UE(&gNB_mac->UE_info, crnti); - if (!UE) { + NR_UE_info_t *old_UE = find_nr_UE(&gNB_mac->UE_info, crnti); + if (!old_UE) { // The UE identified by C-RNTI no longer exists at the gNB // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better // solution may be implemented - LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", ra->rnti); - mac_remove_nr_ue(gNB_mac, ra->rnti); - nr_clear_ra_proc(ra); + LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti); + nr_release_ra_UE(gNB_mac, current_rnti); return; } - - // The UE identified by C-RNTI still exists at the gNB - // Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration - UE->Msg4_MsgB_ACKed = false; - nr_mac_reset_ul_failure(&UE->UE_sched_ctrl); - // Reset HARQ processes - reset_dl_harq_list(&UE->UE_sched_ctrl); - reset_ul_harq_list(&UE->UE_sched_ctrl); - - // Switch to BWP where RA is configured, typically in the InitialBWP - // At this point, UE already switched and triggered RA in that BWP, need to do BWP switching also at gNB for C-RNTI - if (ra->DL_BWP.bwp_id != UE->current_DL_BWP.bwp_id || ra->UL_BWP.bwp_id != UE->current_UL_BWP.bwp_id) { - LOG_D(NR_MAC, "UE %04x Switch BWP from %ld to BWP id %ld\n", UE->rnti, UE->current_DL_BWP.bwp_id, ra->DL_BWP.bwp_id); - NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_idP].ServingCellConfigCommon; - configure_UE_BWP(gNB_mac, scc, &UE->UE_sched_ctrl, NULL, UE, ra->DL_BWP.bwp_id, ra->UL_BWP.bwp_id); - } - + // remove old UE from connected UEs + remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, gNB_mac->UE_info.connected_ue_list, crnti); + UE = configure_UE_crnti_msg3(gNB_mac, old_UE, UE); + ra = UE->ra; if (UE->reconfigCellGroup) { // Nothing to do // A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be @@ -950,26 +912,23 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, LOG_I(NR_MAC, "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", - ra->rnti, + UE->rnti, nrra_text[ra->ra_state]); ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; - LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", ra->rnti, nrra_text[ra->ra_state]); + LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]); return; } - } - } else { - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; + } else { if (ra->ra_state != nrRA_WAIT_Msg3) - continue; + return; if((frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot)) - continue; + return; if (ul_cqi != 0xff) ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0); - handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max); + handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max); } } } @@ -1891,7 +1850,7 @@ static void pf_ul(module_id_t module_id, UE_iterator(UE_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (!UE->Msg4_MsgB_ACKed || sched_ctrl->ul_failure) + if (sched_ctrl->ul_failure) continue; LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 8b403f9e86..5bb9f902ef 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -60,8 +60,8 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac); bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); - +void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); +bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs); bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup); @@ -135,8 +135,6 @@ void nr_initiate_ra_proc(module_id_t module_idP, int16_t timing_offset, uint32_t preamble_power); -void nr_clear_ra_proc(NR_RA_t *ra); - int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, slot_t slotP, int test_only); void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP); @@ -310,21 +308,22 @@ void remove_nr_list(NR_list_t *listP, int id); void add_tail_nr_list(NR_list_t *listP, int id); void add_front_nr_list(NR_list_t *listP, int id); void remove_front_nr_list(NR_list_t *listP); - +void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti); NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP); - +NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP); +void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia); void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, - NR_UE_sched_ctrl_t *sched_ctrl, - NR_RA_t *ra, NR_UE_info_t *UE, + bool is_RA, int dl_bwp_switch, int ul_bwp_switch); -NR_UE_info_t* add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup); - +bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); +bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); +void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success); void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti); - +NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup); int nr_get_default_pucch_res(int pucch_ResourceCommon); int nr_write_ce_dlsch_pdu(module_id_t module_idP, @@ -362,11 +361,7 @@ void reset_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl); void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl); -void handle_nr_ul_harq(const int CC_idP, - module_id_t mod_id, - frame_t frame, - slot_t slot, - const nfapi_nr_crc_t *crc_pdu); +void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu); uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed); void free_transportBlock_buffer(byte_array_t *tb); @@ -394,7 +389,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); - +bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE); +NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti); int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot); @@ -430,7 +426,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, int ul_buffer_index(int frame, int slot, int slots_per_frame, int size); void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP); - void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac); int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx); NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame); @@ -467,7 +462,7 @@ void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c); bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid); -bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti); +bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti); void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected); void prepare_du_configuration_update(gNB_MAC_INST *mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 51357e2978..bc0a53a645 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -476,15 +476,18 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig) static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id) { int CC_id = 0; - const NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; rnti_t rnti; - bool found = nr_mac_get_new_rnti(&mac->UE_info, cc->ra, sizeofArray(cc->ra), &rnti); + bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti); if (!found) return NULL; - NR_UE_info_t* UE = add_new_nr_ue(mac, rnti, NULL); - if (!UE) + NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL); + AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n"); + if (!add_new_UE_RA(mac, UE)) { + delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator); + LOG_E(NR_MAC, "UE list full while creating new UE\n"); return NULL; + } f1_ue_data_t new_ue_data = {.secondary_ue = cu_id}; bool success = du_add_f1_ue_data(rnti, &new_ue_data); @@ -499,11 +502,10 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id) // by add_new_nr_ue(); it's a kind of chicken-and-egg problem), so below we // complete the UE context with the information that add_new_nr_ue() would // have added - UE->Msg4_MsgB_ACKed = true; UE->CellGroup = cellGroupConfig; nr_rlc_activate_srb0(UE->rnti, UE, NULL); - nr_mac_prepare_ra_ue(mac, rnti, UE->CellGroup); + nr_mac_prepare_ra_ue(mac, UE); /* SRB1 is added to RLC and MAC in the handler later */ return UE; } @@ -759,13 +761,6 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse return; } - const int CC_id = 0; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; - if (ra->rnti == UE->rnti) - nr_clear_ra_proc(ra); - } NR_SCHED_UNLOCK(&mac->sched_lock); f1ap_ue_context_release_req_t request = { @@ -822,6 +817,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) pthread_mutex_lock(&mac->sched_lock); /* check first that the scheduler knows such UE */ NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id); + UE = UE ? UE : find_ra_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id); if (UE == NULL) { LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring DL RRC Message Transfer\n", dl_rrc->gNB_DU_ue_id); pthread_mutex_unlock(&mac->sched_lock); @@ -870,12 +866,11 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) * from the current configuration. Also, expect the reconfiguration from * the CU, so save the old UE's CellGroup for the new UE */ UE->CellGroup->spCellConfig = NULL; - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; uid_t temp_uid = UE->uid; UE->uid = oldUE->uid; oldUE->uid = temp_uid; - configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); + configure_UE_BWP(mac, scc, UE, false, -1, -1); for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) { const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i); nr_mac_add_lcid(&UE->UE_sched_ctrl, c); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 13da756d56..20602b8641 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -362,6 +362,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i) if (UE_info->connected_ue_list[i]) delete_nr_ue_data(UE_info->connected_ue_list[i], cc, &UE_info->uid_allocator); + for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i) + if (UE_info->access_ue_list[i]) + delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator); } void nr_mac_send_f1_setup_req(void) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 5d14bd9007..6002c5756f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -229,8 +229,6 @@ typedef struct { NR_beam_alloc_t Msg3_beam; /// harq_pid used for Msg4 transmission uint8_t harq_pid; - /// UE RNTI allocated during RAR - rnti_t rnti; /// RA RNTI allocated from received PRACH uint16_t RA_rnti; /// MsgB RNTI allocated from received MsgA @@ -251,25 +249,12 @@ typedef struct { int msg3_nbSymb; /// MAC PDU length for Msg4 int mac_pdu_length; - /// RA search space - NR_SearchSpace_t *ra_ss; - /// RA Coreset - NR_ControlResourceSet_t *coreset; - NR_sched_pdcch_t sched_pdcch; - // Beam index - uint8_t beam_id; - /// CellGroup for UE that is to come (NSA is non-null, null for SA) - NR_CellGroupConfig_t *CellGroup; /// Preambles for contention-free access NR_preamble_ue_t preambles; int contention_resolution_timer; nr_ra_type_t ra_type; /// CFRA flag bool cfra; - // BWP for RA - NR_UE_DL_BWP_t DL_BWP; - NR_UE_UL_BWP_t UL_BWP; - NR_UE_ServingCell_Info_t sc_info; } NR_RA_t; /*! \brief gNB common channels */ @@ -289,8 +274,6 @@ typedef struct { /// used for otherSIB data uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8]; int other_sib_bcch_length[2]; - /// Template for RA computations - NR_RA_t ra[NR_NB_RA_PROC_MAX]; /// VRB map for common channels uint16_t vrb_map[MAX_NUM_BEAM_PERIODS][275]; /// VRB map for common channels and PUSCH, dynamically allocated because @@ -654,7 +637,6 @@ typedef struct { int pusch_snrx10; int pucch_snrx10; uint16_t ul_rssi; - uint8_t current_harq_pid; int pusch_consecutive_dtx_cnt; int pucch_consecutive_dtx_cnt; bool ul_failure; @@ -770,11 +752,11 @@ typedef struct { NR_UE_NR_Capability_t *capability; // UE selected beam index uint8_t UE_beam_index; - bool Msg4_MsgB_ACKed; float ul_thr_ue; float dl_thr_ue; long pdsch_HARQ_ACK_Codebook; bool is_redcap; + NR_RA_t *ra; } NR_UE_info_t; typedef struct { @@ -782,6 +764,7 @@ typedef struct { // last element always NULL pthread_mutex_t mutex; NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1]; + NR_UE_info_t *access_ue_list[NR_NB_RA_PROC_MAX]; // bitmap of CSI-RS already scheduled in current slot int sched_csirs; uid_allocator_t uid_allocator; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index e82a185ba8..47fad165cd 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -203,7 +203,7 @@ static void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->timing_advance, crc->ul_cqi, crc->rssi); - handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); } UL_info->rx_ind.number_of_pdus = 0; UL_info->crc_ind.number_crcs = 0; diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index e41875027e..714ac5b067 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -371,9 +371,17 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a && secondaryCellGroup->spCellConfig->reconfigurationWithSync && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra); - NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock); - ret = nr_mac_prepare_ra_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup); - NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock); + gNB_MAC_INST *nrmac = RC.nrmac[rrc->module_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + NR_UE_info_t *UE_info = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, UE->rnti, secondaryCellGroup); + AssertFatal(UE_info != NULL, "cannot create UE context: list is full?\n"); + if (add_new_UE_RA(nrmac, UE_info)) { + ret = true; + nr_mac_prepare_ra_ue(nrmac, UE_info); + } else { + delete_nr_ue_data(UE_info, /* not used */ NULL, &nrmac->UE_info.uid_allocator); + } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } AssertFatal(ret, "cannot add NSA UE in MAC, aborting\n");