From b6bedf1216950d8dcda01503d6530e8a9fe93d87 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Thu, 6 Mar 2025 13:03:14 +0000 Subject: [PATCH 01/34] fix(nrLDPC_decoder): fix numIter increment The logs of `./nr_ulsim -n100 -m19 -s12 -S12 -z2 -L4` were showing that sometimes the decoding of one segment was failing while the CRC check succeeded. This was happening because the iteration counter `numIter` was not properly managed so that when the last iteration was successful to decode the segment still `numIter` at the exit was equal to `numMaxIter` plus 1 so that decoding was considered to have failed. In other words the last iteration if it occured was always wasted. This commit offers to solve this problem by simply moving the iteration counter increment at the end of the iteration loop while remaining careful at fixing the tests relying on this counter. --- openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index fcee71c151..742c0311d8 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -552,8 +552,6 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, uint32_t numIter = 1; int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful while ((numIter <= numMaxIter) && (pcRes != 0)) { - // Increase iteration counter - numIter++; if (check_abort(ab)) { numIter = numMaxIter + 2; break; @@ -847,7 +845,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z); NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc)); } else { - if (numIter > 2) { + if (numIter > 1) { int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG); @@ -861,6 +859,8 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, } } } + // Increase iteration counter + numIter++; } if (!p_decParams->check_crc) { int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; From 5acb37c3e2e53ea6a45cf127bc6350558af4269f Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 20 Feb 2025 12:39:25 +0100 Subject: [PATCH 02/34] Handle changing N_TA_offset correctly Handle N_TA_offset update the same way timing advance changes are handled: modify writeBlockSize to ensure continuous transmission. Also address possible data races by making sure the new timing_advance/N_TA_offset is only read once from global memory. --- executables/nr-ue.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index a5c4f69ed5..e08569e999 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -867,6 +867,7 @@ void *UE_thread(void *arg) initNotifiedFIFO_nothreadSafe(&freeBlocks); int timing_advance = UE->timing_advance; + int N_TA_offset = UE->N_TA_offset; NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id); bool syncRunning = false; @@ -1089,13 +1090,19 @@ void *UE_thread(void *arg) // use previous timing_advance value to compute writeTimestamp const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, duration_rx_to_tx) - - firstSymSamp - UE->N_TA_offset - timing_advance; + - firstSymSamp - N_TA_offset - timing_advance; // but use current UE->timing_advance value to compute writeBlockSize int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; - if (UE->timing_advance != timing_advance) { - writeBlockSize -= UE->timing_advance - timing_advance; - timing_advance = UE->timing_advance; + int new_timing_advance = UE->timing_advance; + if (new_timing_advance != timing_advance) { + writeBlockSize -= new_timing_advance- timing_advance; + timing_advance = new_timing_advance; + } + int new_N_TA_offset = UE->N_TA_offset; + if (new_N_TA_offset != N_TA_offset) { + writeBlockSize -= new_N_TA_offset - N_TA_offset; + N_TA_offset = new_N_TA_offset; } if (curMsg.proc.nr_slot_tx == 0) From 75f04874d18c16c1e8c9341bf7ed98b3ac773978 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 6 Mar 2025 11:29:55 +0100 Subject: [PATCH 03/34] Handle changing N_TA_offset on the UE correctly in higher layers Send new N_TA_offset in config_request to PHY. Remove N_TA_offset update from ta_command. --- executables/nr-ue.c | 35 ++++++++++++---- .../nfapi/public_inc/fapi_nr_ue_interface.h | 3 +- openair1/PHY/INIT/nr_init_ue.c | 18 --------- openair1/PHY/INIT/nr_phy_init.h | 1 - openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 9 ----- openair2/LAYER2/NR_MAC_UE/config_ue.c | 40 +++++++++---------- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 - openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 1 - 9 files changed, 48 insertions(+), 61 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index e08569e999..4a315f1fc9 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -147,6 +147,24 @@ static void *nrL1_UE_stats_thread(void *param) return NULL; } +static int determine_N_TA_offset(PHY_VARS_NR_UE *ue) { + if (ue->sl_mode == 2) + return 0; + else { + int N_TA_offset = ue->nrUE_config.cell_config.N_TA_offset; + if (N_TA_offset == -1) { + return set_default_nta_offset(ue->frame_parms.freq_range, ue->frame_parms.samples_per_subframe); + } else { + // Return N_TA_offet in samples, as described in 38.211 4.1 and 4.3.1 + // T_c[s] = 1/(Ξ”f_max x N_f) = 1 / (480 * 1000 * 4096) + // N_TA_offset[s] = N_TA_offset x T_c + // N_TA_offset[samples] = samples_per_second x N_TA_offset[s] + // N_TA_offset[samples] = N_TA_offset x samples_per_subframe x 1000 x T_c + return (N_TA_offset * ue->frame_parms.samples_per_subframe) / (4096 * 480); + } + } +} + void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) { int nb_connected_gNB = 1; @@ -165,8 +183,8 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) // intialize transport init_nr_ue_transport(ue); - // init N_TA offset - init_N_TA_offset(ue); + ue->ta_frame = -1; + ue->ta_slot = -1; } void init_nrUE_standalone_thread(int ue_idx) @@ -867,7 +885,7 @@ void *UE_thread(void *arg) initNotifiedFIFO_nothreadSafe(&freeBlocks); int timing_advance = UE->timing_advance; - int N_TA_offset = UE->N_TA_offset; + UE->N_TA_offset = determine_N_TA_offset(UE); NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id); bool syncRunning = false; @@ -1090,7 +1108,7 @@ void *UE_thread(void *arg) // use previous timing_advance value to compute writeTimestamp const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, duration_rx_to_tx) - - firstSymSamp - N_TA_offset - timing_advance; + - firstSymSamp - UE->N_TA_offset - timing_advance; // but use current UE->timing_advance value to compute writeBlockSize int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; @@ -1099,10 +1117,11 @@ void *UE_thread(void *arg) writeBlockSize -= new_timing_advance- timing_advance; timing_advance = new_timing_advance; } - int new_N_TA_offset = UE->N_TA_offset; - if (new_N_TA_offset != N_TA_offset) { - writeBlockSize -= new_N_TA_offset - N_TA_offset; - N_TA_offset = new_N_TA_offset; + int new_N_TA_offset = determine_N_TA_offset(UE); + if (new_N_TA_offset != UE->N_TA_offset) { + LOG_I(PHY, "N_TA_offset changed from %d to %d\n", UE->N_TA_offset, new_N_TA_offset); + writeBlockSize -= new_N_TA_offset - UE->N_TA_offset; + UE->N_TA_offset = new_N_TA_offset; } if (curMsg.proc.nr_slot_tx == 0) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 881d7fad8e..a5d6087856 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -551,7 +551,6 @@ typedef struct { int ta_frame; int ta_slot; int ta_command; - int ta_offset; bool is_rar; } fapi_nr_ta_command_pdu; @@ -616,7 +615,7 @@ typedef struct { uint8_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007 uint8_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD - + uint32_t N_TA_offset; } fapi_nr_cell_config_t; typedef struct diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 019e386fd0..19816e215f 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -492,24 +492,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE) } } - -void init_N_TA_offset(PHY_VARS_NR_UE *ue) -{ - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - - // No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5 - if (ue->sl_mode == 2) - ue->N_TA_offset = 0; - else - ue->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe); - ue->ta_frame = -1; - ue->ta_slot = -1; - - LOG_I(PHY, - "UE %d Setting N_TA_offset to %d samples (UL Freq %lu, N_RB %d, mu %d)\n", - ue->Mod_id, ue->N_TA_offset, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); -} - void phy_init_nr_top(PHY_VARS_NR_UE *ue) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; init_delay_table(frame_parms->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, frame_parms->delay_table); diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h index d2c65e939f..1b1a0fa1b0 100644 --- a/openair1/PHY/INIT/nr_phy_init.h +++ b/openair1/PHY/INIT/nr_phy_init.h @@ -36,7 +36,6 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB); void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB); void init_nr_ue_transport(PHY_VARS_NR_UE *ue); -void init_N_TA_offset(PHY_VARS_NR_UE *ue); void nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms); void phy_init_nr_gNB(PHY_VARS_gNB *gNB); int init_codebook_gNB(PHY_VARS_gNB *gNB); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index fbfc9d8389..ba4ad4a0f7 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -419,15 +419,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_ LOG_D(PHY, "TA command received in %d.%d Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", ta_command_pdu->ta_frame, ta_command_pdu->ta_slot, ue->ta_frame, ue->ta_slot); - - if (ta_command_pdu->ta_offset != -1) { - // ta_offset_samples : ta_offset = samples_per_subframe : (Ξ”f_max x N_f / 1000) - // As described in Section 4.3.1 in 38.211 - int ta_offset_samples = (ta_command_pdu->ta_offset * samples_per_subframe) / (4096 * 480); - ue->N_TA_offset = ta_offset_samples; - LOG_D(PHY, "Received N_TA offset %d from upper layers. Corresponds to %d samples.\n", - ta_command_pdu->ta_offset, ta_offset_samples); - } } static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index dd826efb79..c271f72285 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -44,6 +44,24 @@ #include "oai_asn1.h" #include "executables/position_interface.h" +static int get_ta_offset(long *n_TimingAdvanceOffset) +{ + if (!n_TimingAdvanceOffset) + return -1; + + switch (*n_TimingAdvanceOffset) { + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 : + return 0; + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 : + return 25600; + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 : + return 39936; + default : + AssertFatal(false, "Invalid n-TimingAdvanceOffset\n"); + } + return -1; +} + static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_structure_t *fs) { tdd_table->tdd_period_in_slots = fs->numb_slots_period; @@ -143,6 +161,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo // cell config cfg->cell_config.phy_cell_id = mac->physCellId; cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset); // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; @@ -345,6 +364,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t // cell config cfg->cell_config.phy_cell_id = *scc->physCellId; cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset); // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; @@ -1685,24 +1705,6 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t AssertFatal(!ret, "mutex failed %d\n", ret); } -static int get_ta_offset(long *n_TimingAdvanceOffset) -{ - if (!n_TimingAdvanceOffset) - return -1; - - switch (*n_TimingAdvanceOffset) { - case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 : - return 0; - case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 : - return 25600; - case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 : - return 39936; - default : - AssertFatal(false, "Invalid n-TimingAdvanceOffset\n"); - } - return -1; -} - static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac, NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) @@ -1744,7 +1746,6 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si AssertFatal(scc, "SIB1 SCC should not be NULL\n"); UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t); configure_si_schedulingInfo(mac, si_SchedulingInfo, si_SchedulingInfo_v1700); - mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); config_common_ue_sa(mac, scc, cc_idP); configure_common_BWP_dl(mac, @@ -1813,7 +1814,6 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, if (reconfWithSync->spCellConfigCommon) { NR_ServingCellConfigCommon_t *scc = reconfWithSync->spCellConfigCommon; - mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); if (scc->physCellId) mac->physCellId = *scc->physCellId; mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2ba5f992d4..d269cc1c0c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -633,7 +633,6 @@ typedef struct NR_UE_MAC_INST_s { int dmrs_TypeA_Position; int p_Max; int p_Max_alt; - int n_ta_offset; // -1 not present, otherwise value to be applied ntn_timing_advance_componets_t ntn_ta; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 35167b6173..2c68369638 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -68,7 +68,6 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->uecap_maxMIMO_PUSCH_layers_nocb = 0; mac->p_Max = INT_MIN; mac->p_Max_alt = INT_MIN; - mac->n_ta_offset = -1; mac->ntn_ta.ntn_params_changed = false; reset_mac_inst(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 846d344584..255cb43a5e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -3626,7 +3626,6 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MA fapi_nr_ta_command_pdu *ta = &dl_config->dl_config_list[dl_config->number_pdus].ta_command_pdu; ta->ta_frame = ul_time_alignment->frame; ta->ta_slot = ul_time_alignment->slot; - ta->ta_offset = mac->n_ta_offset; ta->is_rar = ul_time_alignment->ta_apply == rar_ta; ta->ta_command = ul_time_alignment->ta_command; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND; From 6b660e40917a459a4f591c00f80a920df350ff06 Mon Sep 17 00:00:00 2001 From: Romain Beurdouche Date: Mon, 10 Mar 2025 14:44:51 +0000 Subject: [PATCH 04/34] fix(nrLDPC_decoder): Cleaning LDPC iteration accounting in NR The idea is to make LDPC iteration accounting more standard from a C coding perspective by making two changes: 1. Now the iteration counter starts at 0 for the first iteration and goes up to max_ldpc_iterations - 1 for the last iteration. If it is equal to max_ldpc_iterations, it means that decoding failed. 2. A chain of useless returns in the UE DLSCH decoding call chain was removed. --- .../nrLDPC_coding_segment_decoder.c | 2 +- .../nrLDPC_coding_xdma/nrLDPC_coding_xdma.c | 10 +++---- .../CODING/nrLDPC_decoder/nrLDPC_decoder.c | 10 +++---- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 28 +++++++++---------- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 16 +++++------ .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 2 +- openair1/PHY/defs_gNB.h | 2 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 +-- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 13 +++------ openair1/SIMULATION/NR_PHY/dlschsim.c | 19 ++++++------- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair1/SIMULATION/NR_PHY/ulsim.c | 2 +- 12 files changed, 52 insertions(+), 58 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c index 9b36197e45..c7bb47c581 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_decoder.c @@ -218,7 +218,7 @@ static void nr_process_decode_segment(void *arg) int decodeIterations = LDPCdecoder(p_decoderParms, 0, 0, 0, l, llrProcBuf, p_procTime, rdata->abort_decode); - if (decodeIterations <= p_decoderParms->numMaxIter) { + if (decodeIterations < p_decoderParms->numMaxIter) { memcpy(rdata->c, llrProcBuf, K >> 3); *rdata->decodeSuccess = true; } else { diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c index 7960215ab7..b23db3781d 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_xdma/nrLDPC_coding_xdma.c @@ -277,8 +277,8 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int s for (uint32_t job = 0; job < num_threads_prepare; job++) { args_fpga_decode_prepare_t *args = &arr[job]; - if (args->no_iteration_ldpc > TB_params->max_ldpc_iterations) - no_iteration_ldpc = TB_params->max_ldpc_iterations + 1; + if (args->no_iteration_ldpc >= TB_params->max_ldpc_iterations) + no_iteration_ldpc = TB_params->max_ldpc_iterations; } // launch decode with FPGA @@ -306,12 +306,12 @@ int decoder_xdma(nrLDPC_TB_decoding_parameters_t *TB_params, int frame_rx, int s #ifdef DEBUG_CRC LOG_I(PHY, "segment %d CRC NOK\n", r); #endif - no_iteration_ldpc = TB_params->max_ldpc_iterations + 1; + no_iteration_ldpc = TB_params->max_ldpc_iterations; } for (int i = 0; i < out_CBoffset; i++) { segment_params->c[i] = multi_outdata[i + r * out_CBoffset]; } - segment_params->decodeSuccess = (no_iteration_ldpc <= TB_params->max_ldpc_iterations); + segment_params->decodeSuccess = (no_iteration_ldpc < TB_params->max_ldpc_iterations); if (segment_params->decodeSuccess) { *TB_params->processedSegments = *TB_params->processedSegments + 1; } @@ -396,7 +396,7 @@ void nr_ulsch_FPGA_decoding_prepare_blocks(void *args) == -1) { stop_meas(&segment_params->ts_rate_unmatch); LOG_E(PHY, "ulsch_decoding.c: Problem in rate_matching\n"); - no_iteration_ldpc = max_ldpc_iterations + 1; + no_iteration_ldpc = max_ldpc_iterations; arguments->no_iteration_ldpc = no_iteration_ldpc; return; } else { diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c index 742c0311d8..e2ed7fce10 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c @@ -187,7 +187,7 @@ int32_t LDPCdecoder(t_nrLDPC_dec_params* p_decParams, // Launch LDPC decoder core for one segment int numIter = nrLDPC_decoder_core(p_llr, p_out, numLLR, p_lut, p_decParams, p_profiler, ab); - if (numIter > p_decParams->numMaxIter) { + if (numIter >= p_decParams->numMaxIter) { LOG_D(PHY, "set abort: %d, %d\n", numIter, p_decParams->numMaxIter); set_abort(ab, true); } @@ -549,11 +549,11 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, // estimated after only one iteration // First iteration finished - uint32_t numIter = 1; + uint32_t numIter = 0; int32_t pcRes = 1; // pcRes is 0 if the ldpc decoder is succesful - while ((numIter <= numMaxIter) && (pcRes != 0)) { + while ((numIter < numMaxIter) && (pcRes != 0)) { if (check_abort(ab)) { - numIter = numMaxIter + 2; + numIter = numMaxIter; break; } // CN processing @@ -845,7 +845,7 @@ static inline uint32_t nrLDPC_decoder_core(int8_t* p_llr, pcRes = nrLDPC_cnProcPc_BG2(p_lut, cnProcBuf, cnProcBufRes, Z); NR_LDPC_PROFILER_DETAIL(stop_meas(&p_profiler->cnProcPc)); } else { - if (numIter > 1) { + if (numIter > 0) { int8_t llrOut[NR_LDPC_MAX_NUM_LLR] __attribute__((aligned(64))) = {0}; int8_t* p_llrOut = outMode == nrLDPC_outMode_LLRINT8 ? p_out : llrOut; nrLDPC_llrRes2llrOut(p_lut, p_llrOut, llrRes, Z, BG); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index a3138f5d7f..e6b4503e1b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -59,14 +59,14 @@ void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, /*! \brief Prepare necessary parameters for nrLDPC_coding_interface */ -uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, - const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t *dlsch, - int16_t **dlsch_llr, - uint8_t **b, - int *G, - int nb_dlsch, - uint8_t *DLSCH_ids) +void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, + const UE_nr_rxtx_proc_t *proc, + NR_UE_DLSCH_t *dlsch, + int16_t **dlsch_llr, + uint8_t **b, + int *G, + int nb_dlsch, + uint8_t *DLSCH_ids) { nrLDPC_TB_decoding_parameters_t TBs[nb_dlsch]; memset(TBs, 0, sizeof(TBs)); @@ -100,7 +100,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (!harq_process) { LOG_E(PHY, "dlsch_decoding_slot.c: NULL harq_process pointer\n"); - return dlsch[DLSCH_id].max_ldpc_iterations + 1; + return; } nrLDPC_TB_decoding_parameters_t *TB_parameters = &TBs[pdsch_id]; @@ -164,7 +164,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (harq_process->C > MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER * TB_parameters->nb_layers) { LOG_E(PHY, "nr_segmentation.c: too many segments %d, A %d\n", harq_process->C, TB_parameters->A); - return dlsch[DLSCH_id].max_ldpc_iterations + 1; + return; } if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD) && (!slot_parameters.frame % 100)) @@ -242,7 +242,8 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, int ret_decoder = phy_vars_ue->nrLDPC_coding_interface.nrLDPC_coding_decoder(&slot_parameters); if (ret_decoder != 0) { - return dlsch->max_ldpc_iterations + 1; + LOG_E(PHY, "nrLDPC_coding_decoder returned an error: %d\n", ret_decoder); + return; } // post decode @@ -316,11 +317,11 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, if (harq_process->decodeResult) { LOG_D(PHY, "DLSCH received ok \n"); harq_process->status = SCH_IDLE; - dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations - 1; } else { LOG_D(PHY, "DLSCH received nok \n"); kpiStructure.nb_nack++; - dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; + dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations; UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK"); } @@ -355,5 +356,4 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, } - return dlsch[0].last_iteration_cnt; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 0ca616ba34..bb1a6c03df 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -81,14 +81,14 @@ void nr_conjch0_mult_ch1(int *ch0, @param[in] DLSCH_ids array of active downlink shared channels @returns 0 on success, 1 on unsuccessful decoding */ -uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, - const UE_nr_rxtx_proc_t *proc, - NR_UE_DLSCH_t *dlsch, - short **dlsch_llr, - uint8_t **b, - int *G, - int nb_dlsch, - uint8_t *DLSCH_ids); +void nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, + const UE_nr_rxtx_proc_t *proc, + NR_UE_DLSCH_t *dlsch, + short **dlsch_llr, + uint8_t **b, + int *G, + int nb_dlsch, + uint8_t *DLSCH_ids); /** \brief This is the alternative top-level entry point for ULSCH encoding in UE. It handles all the HARQ processes in only one call. The routine first diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 419988a961..07917b9075 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -147,7 +147,7 @@ typedef struct { /// Maximum number of LDPC iterations uint8_t max_ldpc_iterations; /// number of iterations used in last turbo decoding - uint8_t last_iteration_cnt; + int8_t last_iteration_cnt; /// bit mask of PT-RS ofdm symbol indicies uint16_t ptrs_symbols; // PTRS symbol index, to be updated every PTRS symbol within a slot. diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index eb0a1acc0e..47d41db44b 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -239,7 +239,7 @@ typedef struct { /// Maximum number of LDPC iterations uint8_t max_ldpc_iterations; /// number of iterations used in last LDPC decoding - uint8_t last_iteration_cnt; + int8_t last_iteration_cnt; /// Status Flag indicating for this ULSCH bool active; /// Flag to indicate that the UL configuration has been handled. Used to remove a stale ULSCH when frame wraps around diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 1484d44ddf..4f1f8ff010 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -424,7 +424,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo LOG_D(PHY, "ULSCH received ok \n"); ulsch->active = false; ulsch_harq->round = 0; - ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure + ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations - 1; // Setting to max_ldpc_iterations - 1 is sufficient given that this variable is only used for checking for failure } else { LOG_D(PHY, "[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, ndi %d, status %d, round %d, RV %d, prb_start %d, prb_size %d, " @@ -444,7 +444,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK"); ulsch->handled = 1; LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); - ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure + ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations; // Setting to max_ldpc_iterations is sufficient given that this variable is only used for checking for failure } } diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index b57bf4eff3..283673a6df 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -686,20 +686,18 @@ static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dls /*! \brief Process the whole DLSCH slot */ -static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, +static void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, NR_UE_DLSCH_t dlsch[2], int16_t *llr[2]) { if (dlsch[0].active == false) { LOG_E(PHY, "DLSCH should be active when calling this function\n"); - return true; + return; } - bool dec = false; int harq_pid = dlsch[0].dlsch_config.harq_process_nbr; int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; - uint32_t ret = UINT32_MAX; NR_DL_UE_HARQ_t *dl_harq0 = &ue->dl_harq_processes[0][harq_pid]; NR_DL_UE_HARQ_t *dl_harq1 = &ue->dl_harq_processes[1][harq_pid]; uint16_t dmrs_len = get_num_dmrs(dlsch[0].dlsch_config.dlDmrsSymbPos); @@ -732,7 +730,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const int ack_nack_slot_and_frame = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) + proc->frame_rx * ue->frame_parms.slots_per_frame; dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]); - return false; + return; } int G[2]; @@ -765,11 +763,9 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, } start_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); - ret = nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids); + nr_dlsch_decoding(ue, proc, dlsch, llr, p_b, G, nb_dlsch, DLSCH_ids); stop_meas_nr_ue_phy(ue, DLSCH_DECODING_STATS); - if (ret < ue->max_ldpc_iterations + 1) dec = true; - int ind_type = -1; switch (dlsch[0].rnti_type) { case TYPE_RA_RNTI_: @@ -829,7 +825,6 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, else if (ue->phy_sim_dlsch_b && is_cw1_active == ACTIVE) memcpy(ue->phy_sim_dlsch_b, p_b[1], dlsch_bytes); - return dec; } static bool is_ssb_index_transmitted(const PHY_VARS_NR_UE *ue, const int index) diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index de5c598015..977970c9f7 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -123,7 +123,6 @@ int main(int argc, char **argv) NR_DL_FRAME_PARMS *frame_parms; double sigma; unsigned char qbits = 8; - int ret; int loglvl = OAILOG_WARNING; uint8_t dlsch_threads = 0; float target_error_rate = 0.01; @@ -577,18 +576,18 @@ int main(int argc, char **argv) short *p_channel_output_fixed = channel_output_fixed; uint8_t *p_b = b; int available_bits_array[1] = { available_bits }; - ret = nr_dlsch_decoding(UE, - &proc, - dlsch0_ue, - &p_channel_output_fixed, - &p_b, - available_bits_array, - 1, - DLSCH_ids); + nr_dlsch_decoding(UE, + &proc, + dlsch0_ue, + &p_channel_output_fixed, + &p_b, + available_bits_array, + 1, + DLSCH_ids); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DECODING0, VCD_FUNCTION_OUT); - if (ret > dlsch0_ue->max_ldpc_iterations) + if (dlsch0_ue->last_iteration_cnt > dlsch0_ue->max_ldpc_iterations) n_errors++; //count errors diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index d6227e7b7d..a74a80d7bc 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1163,7 +1163,7 @@ printf("%d\n", slot); //---------------------- count errors ---------------------- //---------------------------------------------------------- - if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations+1) + if (dlsch0->last_iteration_cnt >= dlsch0->max_ldpc_iterations) n_errors[round]++; int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 946274a7bd..adec328bc4 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1420,7 +1420,7 @@ int main(int argc, char *argv[]) 0); } - if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations + 1) || ul_proc_error == 1) { + if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) { error_flag = 1; n_errors[round]++; crc_status = 1; From c7b561ef825cc9ddc848bfc6251c227aa7d77dde Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 11 Mar 2025 12:09:45 +0100 Subject: [PATCH 05/34] remove wrong assertion for B4 PRACH format --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 6e776b123a..2e265349a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -585,8 +585,6 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP total_prach_slots = get_long_prach_dur(format0, mu_pusch); AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n"); } else { - // TODO: to be revisited for format B4 (also extends beyond current slot for FR1 30kHz SCS and FR2) - AssertFatal((format != 0xb4) || (mu_pusch < 1), "Format B4 not supported for this PUSCH SCS\n"); total_prach_slots = 1; } // reserve PRBs occupied by PRACH in all PRACH slot. From 939ce850a55e506b3c9bcb88980d62087cd54376 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 16 Oct 2024 10:12:57 +0200 Subject: [PATCH 06/34] improved management of RA functions at UE --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 15 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 138 +++++++++---------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 3 files changed, 71 insertions(+), 84 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index fbc98964e3..3f3ae2a141 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -310,18 +310,13 @@ int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon); void nr_get_RA_window(NR_UE_MAC_INST_t *mac); -/* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. -If the UE is not in PUSCH mode for a particular eNB index, this is assumed to be an Msg3 and MAC -attempts to retrieves the CCCH message from RRC. If the UE is in PUSCH mode for a particular eNB -index and PUCCH format 0 (Scheduling Request) is not activated, the MAC may use this resource for -andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4 from 38.321) -@param mod_id Index of UE instance +/*@mac pointer to MAC instance @param CC_id Component Carrier Index @param frame @param gNB_id gNB index @param nr_slot_tx slot for PRACH transmission @returns indication to generate PRACH to phy */ -void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx); +void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx); /* \brief Function implementing the routine for the selection of Random Access resources (5.1.2 TS 38.321). @param mac pointer to MAC instance @@ -348,12 +343,6 @@ void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int */ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id); -void init_RA(NR_UE_MAC_INST_t *mac, - NR_PRACH_RESOURCES_t *prach_resources, - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric, - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated); - int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac); void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id); void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 51a3ad8c9d..ada5c9e0ba 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -53,14 +53,65 @@ int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) // to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) // todo: // - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0) -void init_RA(NR_UE_MAC_INST_t *mac, - NR_PRACH_RESOURCES_t *prach_resources, - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric, - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) +static bool init_RA(NR_UE_MAC_INST_t *mac, + int frame, + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric, + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) { - mac->state = UE_PERFORMING_RA; RA_config_t *ra = &mac->ra; + // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side + LOG_D(NR_MAC, + "ra->ra_state %d frame %d mac->first_sync_frame %d xxx %d", + ra->ra_state, + frame, + mac->first_sync_frame, + ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 10); + if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa) + && ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) { + ra->ra_state = nrRA_GENERATE_PREAMBLE; + LOG_D(NR_MAC, "PRACH Condition met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); + } else { + LOG_D(NR_MAC, "PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); + return false; + } + + // TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function + // Not a good implementation, it needs improvements + int size_sdu = 0; + + // Concerning the C-RNTI MAC CE, + // it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel. + // Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode. + if (get_softmodem_params()->nsa) { + + uint8_t mac_sdus[34 * 1056]; + uint16_t sdu_lengths[NB_RB_MAX] = {0}; + int TBS_bytes = 848; + int mac_ce_len = 0; + unsigned short post_padding = 1; + + // fill ulsch_buffer with random data + for (int i = 0; i < TBS_bytes; i++) { + mac_sdus[i] = (unsigned char)(rand()&0xff); + } + // Sending SDUs with size 1 + // Initialize elements of sdu_lengths + sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len; + size_sdu += sdu_lengths[0]; + + if (size_sdu > 0) { + memcpy(ra->cont_res_id, mac_sdus, sizeof(uint8_t) * 6); + ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); + } + + } else if (!IS_SA_MODE(get_softmodem_params())) { + uint8_t temp_pdu[16] = {0}; + size_sdu = nr_write_ce_msg3_pdu(temp_pdu, mac, mac->crnti, temp_pdu + sizeof(temp_pdu)); + ra->Msg3_size = size_sdu; + } + + mac->state = UE_PERFORMING_RA; ra->RA_active = true; ra->ra_PreambleIndex = -1; ra->RA_usedGroupA = 1; @@ -72,7 +123,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, ra->RA_window_cnt = -1; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - + NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; prach_resources->RA_PREAMBLE_BACKOFF = 0; NR_SubcarrierSpacing_t prach_scs; int scs_for_pcmax; // for long prach the UL BWP SCS is used for calculating RA_PCMAX @@ -216,6 +267,7 @@ void init_RA(NR_UE_MAC_INST_t *mac, ra->preambleTransMax = (int)nr_rach_ConfigCommon->rach_ConfigGeneric.preambleTransMax; } } + return true; } /* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ @@ -558,7 +610,7 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - LOG_D(MAC, "Getting PRACH resources frame (first_Msg3 %d)\n", ra->first_Msg3); + LOG_D(MAC, "Getting PRACH resources (first_Msg3 %d)\n", ra->first_Msg3); if (rach_ConfigDedicated) { if (rach_ConfigDedicated->cfra){ @@ -580,7 +632,6 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER++; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); - } // TbD: RA_attempt_number not used @@ -692,76 +743,23 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS * @gNB_id gNB ID * @nr_slot_tx current UL TX slot */ -void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx) +void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx) { RA_config_t *ra = &mac->ra; NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; - - // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side + NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; if (ra->ra_state == nrRA_UE_IDLE) { - LOG_D(NR_MAC, - "ra->ra_state %d frame %d mac->first_sync_frame %d xxx %d", - ra->ra_state, - frame, - mac->first_sync_frame, - ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 10); - if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa) - && ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) { - ra->ra_state = nrRA_GENERATE_PREAMBLE; - LOG_D(NR_MAC, "PRACH Condition met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); - } else { - LOG_D(NR_MAC, - "PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", - ra->ra_state, - frame, - mac->first_sync_frame); - return; - } + bool init_success = init_RA(mac, frame, setup, rach_ConfigGeneric, rach_ConfigDedicated); + if (!init_success) + return; } LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); - if (ra->ra_state > nrRA_UE_IDLE && ra->ra_state < nrRA_SUCCEEDED) { - if (!ra->RA_active) { - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - init_RA(mac, &ra->prach_resources, setup, rach_ConfigGeneric, ra->rach_ConfigDedicated); - - // TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function - // Not a good implementation, it needs improvements - int size_sdu = 0; - - // Concerning the C-RNTI MAC CE, it has to be included if the UL transmission (Msg3) is not being made for the CCCH logical channel. - // Therefore it has been assumed that this event only occurs only when RA is done and it is not SA mode. - if (get_softmodem_params()->nsa) { - - uint8_t mac_sdus[34*1056]; - uint16_t sdu_lengths[NB_RB_MAX] = {0}; - int TBS_bytes = 848; - int mac_ce_len = 0; - unsigned short post_padding = 1; - - // fill ulsch_buffer with random data - for (int i = 0; i < TBS_bytes; i++){ - mac_sdus[i] = (unsigned char) (rand()&0xff); - } - //Sending SDUs with size 1 - //Initialize elements of sdu_lengths - sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len; - size_sdu += sdu_lengths[0]; - - if (size_sdu > 0) { - memcpy(ra->cont_res_id, mac_sdus, sizeof(uint8_t) * 6); - ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); - } - - } else if (!IS_SA_MODE(get_softmodem_params())) { - uint8_t temp_pdu[16] = {0}; - size_sdu = nr_write_ce_msg3_pdu(temp_pdu, mac, mac->crnti, temp_pdu + sizeof(temp_pdu)); - ra->Msg3_size = size_sdu; - } - } else if (ra->RA_window_cnt != -1) { // RACH is active + if (ra->ra_state < nrRA_SUCCEEDED) { + if (ra->RA_window_cnt != -1) { // RACH is active LOG_D(MAC, "[%d.%d] RA is active: RA window count %d, RA backoff count %d\n", frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 5300c9ed1f..fc85583ad2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1305,7 +1305,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) RA_config_t *ra = &mac->ra; if (mac->state == UE_PERFORMING_RA) { - nr_ue_get_rach(mac, cc_id, frame_tx, gNB_index, slot_tx); + nr_ue_manage_ra_procedure(mac, cc_id, frame_tx, gNB_index, slot_tx); nr_ue_prach_scheduler(mac, frame_tx, slot_tx); } From 796c2a61a3546129624b7ef8aa2c0189c928a67b Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 17 Oct 2024 10:14:44 +0200 Subject: [PATCH 07/34] improvements in RA init procedures according to 5.1.1 in 38.321 --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 19 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 4 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 23 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 5 + openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 349 ++++++++++-------- .../LAYER2/NR_MAC_UE/nr_ue_power_procedures.c | 13 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 +- .../tests/test_nr_ue_ra_procedures.cpp | 44 ++- 8 files changed, 257 insertions(+), 205 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index f3693e2791..29c5e2bfa1 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -571,34 +571,33 @@ NR_tda_info_t get_dl_tda_info(const NR_UE_DL_BWP_t *dl_BWP, return tda_info; } -uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) { - - LOG_D(MAC,"get_NCS: indx %d,format0 %d, restriced_set_config %d\n", - index,format0,restricted_set_config); +uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) +{ + LOG_D(NR_MAC, "get_NCS: indx %d,format0 %d, restriced_set_config %d\n", index, format0, restricted_set_config); if (format0 < 3) { - switch(restricted_set_config){ + switch (restricted_set_config) { case 0: return(NCS_unrestricted_delta_f_RA_125[index]); case 1: return(NCS_restricted_TypeA_delta_f_RA_125[index]); case 2: return(NCS_restricted_TypeB_delta_f_RA_125[index]); - default: - AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config); + default: + AssertFatal(false, "Invalid restricted set config value %d", restricted_set_config); } } else { if (format0 == 3) { - switch(restricted_set_config){ + switch (restricted_set_config) { case 0: return(NCS_unrestricted_delta_f_RA_5[index]); case 1: return(NCS_restricted_TypeA_delta_f_RA_5[index]); case 2: return(NCS_restricted_TypeB_delta_f_RA_5[index]); - default: - AssertFatal(1==0,"Invalid restricted set config value %d",restricted_set_config); + default: + AssertFatal(false, "Invalid restricted set config value %d", restricted_set_config); } } else diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 09d0eb2928..552f0676f6 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1399,7 +1399,7 @@ static void setup_srsconfig(NR_UE_UL_BWP_t *bwp, NR_SRS_Config_t *source, NR_SRS } } -static NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup) +NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup) { NR_UE_DL_BWP_t *bwp = NULL; for (int i = 0; i < mac->dl_BWPs.count; i++) { @@ -1423,7 +1423,7 @@ static NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, b return bwp; } -static NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup) +NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup) { NR_UE_UL_BWP_t *bwp = NULL; for (int i = 0; i < mac->ul_BWPs.count; i++) { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index fbd96532f9..d80a279952 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -275,25 +275,21 @@ typedef struct { /// PRACH format retrieved from prach_ConfigIndex uint16_t prach_format; /// Preamble Tx Counter - uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; + uint8_t preamble_tx_counter; /// Preamble Power Ramping Counter - uint8_t RA_PREAMBLE_POWER_RAMPING_COUNTER; + uint8_t preamble_power_ramping_cnt; /// 2-step RA power offset - int POWER_OFFSET_2STEP_RA; + int power_offset_2step; /// Target received power at gNB. Baseline is range -202..-60 dBm. Depends on delta preamble, power ramping counter and step. int ra_PREAMBLE_RECEIVED_TARGET_POWER; /// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex uint8_t ra_TDD_map_index; /// RA Preamble Power Ramping Step in dB - uint32_t RA_PREAMBLE_POWER_RAMPING_STEP; - /// - uint8_t RA_PREAMBLE_BACKOFF; - /// - uint8_t RA_SCALING_FACTOR_BI; - /// Indicating whether it is 2-step or 4-step RA - nr_ra_type_t RA_TYPE; + uint32_t preamble_power_ramping_step; + uint8_t preamble_backoff; + uint8_t scaling_factor_bi; /// UE configured maximum output power - int RA_PCMAX; + int Pc_max; } NR_PRACH_RESOURCES_t; typedef struct { @@ -303,7 +299,7 @@ typedef struct { /// state of RA procedure nrRA_UE_state_t ra_state; /// RA contention type - uint8_t cfra; + bool cfra; /// RA type nr_ra_type_t ra_type; /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. @@ -329,7 +325,8 @@ typedef struct { int ra_PreambleIndex; // When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble uint8_t ssb_nb_in_ro; - + int zeroCorrelationZoneConfig; + int restricted_set_config; /// Random-access window counter int16_t RA_window_cnt; /// Flag to monitor if matching RAPID was received in RAR diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 3f3ae2a141..22f0cbaf84 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -45,6 +45,9 @@ \param mac MAC pointer */ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac); +NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup); +NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup); + void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data); void update_mac_timers(NR_UE_MAC_INST_t *mac); NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid); @@ -274,6 +277,8 @@ void ul_ports_config(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci, nr_dci_format_t dci_format); +bool init_RA(NR_UE_MAC_INST_t *mac, int frame); + /* Random Access */ /* \brief This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211 tables 6.3.3.2.x and fills the PRACH PDU per each FD occasion. diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index ada5c9e0ba..b16def686f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -46,18 +46,55 @@ int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) RA_config_t *ra = &mac->ra; int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER + pathloss); - return min(ra->prach_resources.RA_PCMAX, ra_preamble_rx_power); + return min(ra->prach_resources.Pc_max, ra_preamble_rx_power); +} + +static void set_preambleTransMax(RA_config_t *ra, long preambleTransMax) +{ + switch (preambleTransMax) { + case 0: + ra->preambleTransMax = 3; + break; + case 1: + ra->preambleTransMax = 4; + break; + case 2: + ra->preambleTransMax = 5; + break; + case 3: + ra->preambleTransMax = 6; + break; + case 4: + ra->preambleTransMax = 7; + break; + case 5: + ra->preambleTransMax = 8; + break; + case 6: + ra->preambleTransMax = 10; + break; + case 7: + ra->preambleTransMax = 20; + break; + case 8: + ra->preambleTransMax = 50; + break; + case 9: + ra->preambleTransMax = 100; + break; + case 10: + ra->preambleTransMax = 200; + break; + default: + AssertFatal(false, "Invalid preambleTransMax\n"); + } } // Random Access procedure initialization as per 5.1.1 and initialization of variables specific // to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) // todo: // - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0) -static bool init_RA(NR_UE_MAC_INST_t *mac, - int frame, - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric, - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) +bool init_RA(NR_UE_MAC_INST_t *mac, int frame) { RA_config_t *ra = &mac->ra; // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side @@ -111,23 +148,50 @@ static bool init_RA(NR_UE_MAC_INST_t *mac, ra->Msg3_size = size_sdu; } + // Random acces procedure initialization mac->state = UE_PERFORMING_RA; ra->RA_active = true; - ra->ra_PreambleIndex = -1; - ra->RA_usedGroupA = 1; - ra->RA_RAPID_found = 0; - ra->preambleTransMax = 0; - ra->first_Msg3 = true; - ra->starting_preamble_nb = 0; - ra->RA_backoff_cnt = 0; - ra->RA_window_cnt = -1; - - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; - prach_resources->RA_PREAMBLE_BACKOFF = 0; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + // flush MSG3 buffer + free_and_zero(ra->Msg3_buffer); + // set the PREAMBLE_TRANSMISSION_COUNTER to 1 + prach_resources->preamble_tx_counter = 1; + // set the PREAMBLE_POWER_RAMPING_COUNTER to 1 + prach_resources->preamble_power_ramping_cnt = 1; + // set the PREAMBLE_BACKOFF to 0 ms TODO to be set as a timer? + prach_resources->preamble_backoff = 0; + // set POWER_OFFSET_2STEP_RA to 0 dB + prach_resources->power_offset_2step = 0; + + const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; + // perform the BWP operation as specified in clause 5.15 + // if PRACH occasions are not configured for the active UL BWP + if (!current_UL_BWP->rach_ConfigCommon) { + // switch the active UL BWP to BWP indicated by initialUplinkBWP + current_UL_BWP = get_ul_bwp_structure(mac, 0, false); + // if the Serving Cell is an SpCell + // switch the active DL BWP to BWP indicated by initialDownlinkBWP + mac->current_DL_BWP = get_dl_bwp_structure(mac, 0, false); + } else { + // if the active DL BWP does not have the same bwp-Id as the active UL BWP + if (current_UL_BWP->bwp_id != mac->current_DL_BWP->bwp_id) { + // switch the active DL BWP to the DL BWP with the same bwp-Id as the active UL BWP + mac->current_DL_BWP = get_dl_bwp_structure(mac, 0, false); + } + } + + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon; + AssertFatal(nr_rach_ConfigCommon, "rach-ConfigCommon should be configured here\n"); + // stop the bwp-InactivityTimer associated with the active DL BWP of this Serving Cell, if running + // TODO bwp-InactivityTimer not implemented + + // if the carrier to use for the Random Access procedure is explicitly signalled (always the case for us) + // PRACH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1) NR_SubcarrierSpacing_t prach_scs; int scs_for_pcmax; // for long prach the UL BWP SCS is used for calculating RA_PCMAX - if (nr_rach_ConfigCommon && nr_rach_ConfigCommon->msg1_SubcarrierSpacing) { + NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric; + if (nr_rach_ConfigCommon->msg1_SubcarrierSpacing) { prach_scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing; scs_for_pcmax = prach_scs; } else { @@ -137,136 +201,111 @@ static bool init_RA(NR_UE_MAC_INST_t *mac, prach_scs = get_delta_f_RA_long(format); scs_for_pcmax = mac->current_UL_BWP->scs; } - int n_prbs = get_N_RA_RB(prach_scs, mac->current_UL_BWP->scs); - int start_prb = rach_ConfigGeneric->msg1_FrequencyStart + mac->current_UL_BWP->BWPStart; - // PRACH shall be as specified for QPSK modulated DFT-s-OFDM of equivalent RB allocation (38.101-1) - prach_resources->RA_PCMAX = nr_get_Pcmax(mac->p_Max, - mac->nr_band, - mac->frame_structure.frame_type, - mac->frequency_range, - mac->current_UL_BWP->channel_bandwidth, - 2, - false, - scs_for_pcmax, - cfg->carrier_config.dl_grid_size[scs_for_pcmax], - true, - n_prbs, - start_prb); - prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1; - prach_resources->POWER_OFFSET_2STEP_RA = 0; - prach_resources->RA_SCALING_FACTOR_BI = 1; + int n_prbs = get_N_RA_RB(prach_scs, current_UL_BWP->scs); + int start_prb = rach_ConfigGeneric->msg1_FrequencyStart + current_UL_BWP->BWPStart; + prach_resources->Pc_max = nr_get_Pcmax(mac->p_Max, + mac->nr_band, + mac->frame_structure.frame_type, + mac->frequency_range, + current_UL_BWP->channel_bandwidth, + 2, + false, + scs_for_pcmax, + cfg->carrier_config.dl_grid_size[scs_for_pcmax], + true, + n_prbs, + start_prb); + // TODO if the Random Access procedure is initiated by PDCCH order + // and if the ra-PreambleIndex explicitly provided by PDCCH is not 0b000000 - // Contention Free - if (rach_ConfigDedicated) { - if (rach_ConfigDedicated->cfra){ - LOG_I(MAC, "Initialization of 4-Step CFRA procedure\n"); - prach_resources->RA_TYPE = RA_4_STEP; - ra->ra_type = RA_4_STEP; - ra->cfra = 1; - } else if (rach_ConfigDedicated->ext1){ - if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16) { - LOG_I(MAC, "Initialization of 2-Step CFRA procedure\n"); - prach_resources->RA_TYPE = RA_2_STEP; - ra->ra_type = RA_2_STEP; - ra->cfra = 1; - } else { - LOG_E(NR_MAC, "Config not handled\n"); - } - } else { - LOG_E(NR_MAC, "Config not handled\n"); - } - // Contention Based - } else if (mac->current_UL_BWP->msgA_ConfigCommon_r16) { - LOG_I(MAC, "Initialization of 2-Step CBRA procedure\n"); - prach_resources->RA_TYPE = RA_2_STEP; - ra->ra_type = RA_2_STEP; - ra->cfra = 0; - } else if (nr_rach_ConfigCommon) { - LOG_I(MAC, "Initialization of 4-Step CBRA procedure\n"); - prach_resources->RA_TYPE = RA_4_STEP; + // TODO if the Random Access procedure was initiated for SI request + // and the Random Access Resources for SI request have been explicitly provided by RRC + + // TODO if the Random Access procedure was initiated for SpCell beam failure recovery + // and if the contention-free Random Access Resources for beam failure recovery request for 4-step RA type + // have been explicitly provided by RRC for the BWP selected for Random Access procedure + + NR_RACH_ConfigCommonTwoStepRA_r16_t *twostep_conf = NULL; + NR_RACH_ConfigDedicated_t *rach_Dedicated = ra->rach_ConfigDedicated; + if (rach_Dedicated && rach_Dedicated->cfra) { + // if the Random Access procedure was initiated for reconfiguration with sync and + // if the contention-free Random Access Resources for 4-step RA type have been explicitly provided + // in rach-ConfigDedicated for the BWP selected for Random Access procedure + LOG_I(MAC, "Initialization of 4-Step CFRA procedure\n"); ra->ra_type = RA_4_STEP; - ra->cfra = 0; + ra->cfra = true; } else { - LOG_E(MAC, "Config not handled\n"); - AssertFatal(false, "In %s: config not handled\n", __FUNCTION__); - } - - switch (rach_ConfigGeneric->powerRampingStep){ // in dB - case 0: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0; - break; - case 1: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2; - break; - case 2: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4; - break; - case 3: - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6; - break; - } - - switch (rach_ConfigGeneric->preambleTransMax) { - case 0: - ra->preambleTransMax = 3; - break; - case 1: - ra->preambleTransMax = 4; - break; - case 2: - ra->preambleTransMax = 5; - break; - case 3: - ra->preambleTransMax = 6; - break; - case 4: - ra->preambleTransMax = 7; - break; - case 5: - ra->preambleTransMax = 8; - break; - case 6: - ra->preambleTransMax = 10; - break; - case 7: - ra->preambleTransMax = 20; - break; - case 8: - ra->preambleTransMax = 50; - break; - case 9: - ra->preambleTransMax = 100; - break; - case 10: - ra->preambleTransMax = 200; - break; - } - - if (ra->ra_type == RA_2_STEP) { - if (nr_rach_ConfigCommon->ext1 && nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16) { - LOG_D(MAC, "Missing implementation for Access Identity initialization procedures\n"); - } - // Perform initialization of variables specific to Random Access type as specified in clause 5.1.1a of TS 38.321 - NR_RACH_ConfigGenericTwoStepRA_r16_t nr_ra_ConfigGenericTwoStepRA_r16 = - mac->current_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16.rach_ConfigGenericTwoStepRA_r16; - // Takes the value of 2-Step RA variable - if (nr_ra_ConfigGenericTwoStepRA_r16.msgA_PreamblePowerRampingStep_r16) { - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = *nr_ra_ConfigGenericTwoStepRA_r16.msgA_PreamblePowerRampingStep_r16; + bool twostep_cfra = (rach_Dedicated && rach_Dedicated->ext1) ? (rach_Dedicated->ext1->cfra_TwoStep_r16 ? true : false) : false; + if (twostep_cfra) { + // if the Random Access procedure was initiated for reconfiguration with sync and + // if the contention-free Random Access Resources for 2-step RA type have been explicitly provided in rach-ConfigDedicated + LOG_I(MAC, "Initialization of 2-Step CFRA procedure\n"); + ra->ra_type = RA_2_STEP; + ra->cfra = true; } else { - // If 2-Step variable does not exist, it takes the value of 4-Step RA variable - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = nr_rach_ConfigCommon->rach_ConfigGeneric.powerRampingStep; - } - prach_resources->RA_SCALING_FACTOR_BI = 1; - // Takes the value of 2-Step RA variable - if (nr_ra_ConfigGenericTwoStepRA_r16.preambleTransMax_r16) { - ra->preambleTransMax = (int)*nr_ra_ConfigGenericTwoStepRA_r16.preambleTransMax_r16; - } else { - // If 2-Step variable does not exist, it takes the value of 4-Step RA variable - ra->preambleTransMax = (int)nr_rach_ConfigCommon->rach_ConfigGeneric.preambleTransMax; + bool twostep = false; + if (current_UL_BWP->msgA_ConfigCommon_r16) { + twostep_conf = ¤t_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16; + if (nr_rach_ConfigCommon) { + // if the BWP selected for Random Access procedure is configured with both 2- and 4-step RA type Random Access Resources + // and the RSRP of the downlink pathloss reference is above msgA-RSRP-Threshold + AssertFatal(twostep_conf->msgA_RSRP_Threshold_r16, + "msgA_RSRP_Threshold_r16 is mandatory present if both 2-step and 4-step random access types are configured\n"); + // For thresholds the RSRP value is (IE value – 156) dBm except for the IE 127 in which case the actual value is infinity + int rsrp_msga_thr = *twostep_conf->msgA_RSRP_Threshold_r16 - 156; + if (*twostep_conf->msgA_RSRP_Threshold_r16 != 127 && mac->ssb_measurements.ssb_rsrp_dBm > rsrp_msga_thr) + twostep = true; + } else { + // if the BWP selected for Random Access procedure is only configured with 2-step RA type Random Access + twostep = true; + } + } + if (twostep) { + LOG_I(MAC, "Initialization of 2-Step CBRA procedure\n"); + ra->ra_type = RA_2_STEP; + ra->cfra = false; + } else { + LOG_I(MAC, "Initialization of 4-Step CBRA procedure\n"); + ra->ra_type = RA_4_STEP; + ra->cfra = false; + } } } + + NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep_generic = twostep_conf ? &twostep_conf->rach_ConfigGenericTwoStepRA_r16 : NULL; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreamblePowerRampingStep_r16) + prach_resources->preamble_power_ramping_step = *twostep_generic->msgA_PreamblePowerRampingStep_r16 << 1; + else + prach_resources->preamble_power_ramping_step = rach_ConfigGeneric->powerRampingStep << 1; + + prach_resources->scaling_factor_bi = 1; + + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->preambleTransMax_r16) + set_preambleTransMax(ra, *twostep_generic->preambleTransMax_r16); + else + set_preambleTransMax(ra, rach_ConfigGeneric->preambleTransMax); + + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_ZeroCorrelationZoneConfig_r16) + ra->zeroCorrelationZoneConfig = *twostep_generic->msgA_ZeroCorrelationZoneConfig_r16; + else + ra->zeroCorrelationZoneConfig = rach_ConfigGeneric->zeroCorrelationZoneConfig; + if (ra->ra_type == RA_2_STEP && twostep_conf && twostep_conf->msgA_RestrictedSetConfig_r16) + ra->restricted_set_config = *twostep_conf->msgA_RestrictedSetConfig_r16; + else + ra->restricted_set_config = nr_rach_ConfigCommon->restrictedSetConfig; + + // TODO msgA-TransMax not implemented + // TODO ra-Prioritization not implemented + + ra->ra_PreambleIndex = -1; + ra->RA_usedGroupA = 1; + ra->RA_RAPID_found = 0; + ra->first_Msg3 = true; + ra->starting_preamble_nb = 0; + ra->RA_backoff_cnt = 0; + ra->RA_window_cnt = -1; + return true; } @@ -359,8 +398,8 @@ static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t * receivedTargerPower = preambleReceivedTargetPower + delta_preamble + - (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP + - prach_resources->POWER_OFFSET_2STEP_RA; + (prach_resources->preamble_power_ramping_cnt - 1) * prach_resources->preamble_power_ramping_step + + prach_resources->power_offset_2step; LOG_D(MAC, "ReceivedTargerPower is %d dBm \n", receivedTargerPower); return receivedTargerPower; @@ -545,7 +584,7 @@ void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", setup->groupBconfigured->messagePowerOffsetGroupB); } - PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; + PLThreshold = prach_resources->Pc_max - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; } @@ -629,8 +668,8 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", ra->ra_PreambleIndex); } - if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER > 1) - prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER++; + if (prach_resources->preamble_tx_counter > 1) + prach_resources->preamble_power_ramping_cnt++; prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); } @@ -748,10 +787,8 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, RA_config_t *ra = &mac->ra; NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; if (ra->ra_state == nrRA_UE_IDLE) { - bool init_success = init_RA(mac, frame, setup, rach_ConfigGeneric, rach_ConfigDedicated); + bool init_success = init_RA(mac, frame); if (!init_success) return; } @@ -764,9 +801,9 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, LOG_D(MAC, "[%d.%d] RA is active: RA window count %d, RA backoff count %d\n", frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); if (ra->RA_BI_found){ - prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * ra->RA_backoff_indicator; + prach_resources->preamble_backoff = prach_resources->scaling_factor_bi * ra->RA_backoff_indicator; } else { - prach_resources->RA_PREAMBLE_BACKOFF = 0; + prach_resources->preamble_backoff = 0; } if (ra->RA_window_cnt >= 0 && ra->RA_RAPID_found == 1) { @@ -987,13 +1024,13 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr ra->ra_PreambleIndex = -1; ra->ra_state = nrRA_UE_IDLE; - prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++; + prach_resources->preamble_tx_counter++; // when the Contention Resolution is considered not successful // stop timeAlignmentTimer nr_timer_stop(&mac->time_alignment_timer); - if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1) { + if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { LOG_D(NR_MAC, "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", @@ -1002,9 +1039,9 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr slot, ra->preambleTransMax); - ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->RA_PREAMBLE_BACKOFF + 1); - prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; - prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += 2; // 2 dB increment + ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->preamble_backoff + 1); + prach_resources->preamble_tx_counter = 1; + prach_resources->preamble_power_ramping_step += 2; // 2 dB increment prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); } else { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c index 7083b4a141..0c024560d7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c @@ -372,8 +372,8 @@ int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, if (mac->pucch_power_control_initialized == false) { // Initialize power control state // Assuming only sending on PCell - NR_PRACH_RESOURCES_t* prach_resources = &mac->ra.prach_resources; - float DELTA_P_rampup_requested = (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; + NR_PRACH_RESOURCES_t *prach_res = &mac->ra.prach_resources; + float DELTA_P_rampup_requested = (prach_res->preamble_power_ramping_cnt - 1) * prach_res->preamble_power_ramping_step; float DELTA_P_rampup = P_CMAX - (P_O_PUCCH + pathloss + delta_F_PUCCH + DELTA_TF + sum_delta_pucch); DELTA_P_rampup = max(min(0, DELTA_P_rampup), DELTA_P_rampup_requested); mac->G_b_f_c = DELTA_P_rampup + sum_delta_pucch; @@ -572,8 +572,8 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac, f_b_f_c = delta_pusch; } else { if (!mac->pusch_power_control_initialized && is_rar_tx_retx) { - NR_PRACH_RESOURCES_t* prach_resources = &mac->ra.prach_resources; - float DELTA_P_rampup_requested = (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; + NR_PRACH_RESOURCES_t *prach_res = &mac->ra.prach_resources; + float DELTA_P_rampup_requested = (prach_res->preamble_power_ramping_cnt - 1) * prach_res->preamble_power_ramping_step; float DELTA_P_rampup = P_CMAX - (P_O_PUSCH + M_pusch_component + alpha * pathloss + DELTA_TF + delta_pusch); DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup)); mac->f_b_f_c = DELTA_P_rampup + delta_pusch; @@ -654,9 +654,8 @@ int get_srs_tx_power_ue(NR_UE_MAC_INST_t *mac, if (!is_tpc_accumulation_provided && (!is_configured_for_pusch_on_current_bwp || separate_pc_adjustment_state)) { if (!current_UL_BWP->srs_power_control_initialized) { - NR_PRACH_RESOURCES_t *prach_resources = &mac->ra.prach_resources; - float DELTA_P_rampup_requested = - (prach_resources->RA_PREAMBLE_POWER_RAMPING_COUNTER - 1) * prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP; + NR_PRACH_RESOURCES_t *prach = &mac->ra.prach_resources; + float DELTA_P_rampup_requested = (prach->preamble_power_ramping_cnt - 1) * prach->preamble_power_ramping_step; float DELTA_P_rampup = P_CMAX - (P_0_SRS + m_srs_component + alpha * pathloss); DELTA_P_rampup = min(DELTA_P_rampup_requested, max(0, DELTA_P_rampup)); current_UL_BWP->srs_power_control_initialized = true; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index fc85583ad2..94f9c80277 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2595,8 +2595,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; fapi_nr_prach_config_t *prach_config = &cfg->prach_config; - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; const int bwp_id = mac->current_UL_BWP->bwp_id; if (is_ul_slot(slotP, &mac->frame_structure)) { @@ -2627,14 +2625,13 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t LOG_E(NR_MAC, "Error in PRACH allocation\n"); return; } - uint16_t ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig); pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){ .phys_cell_id = mac->physCellId, .num_prach_ocas = 1, .prach_slot = prach_occasion_info_p->slot, .prach_start_symbol = prach_occasion_info_p->start_symbol, .num_ra = prach_occasion_info_p->fdm, - .num_cs = ncs, + .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format0, ra->restricted_set_config), .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index, .restricted_set = prach_config->restricted_set_config, .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1}; diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index f5a402c467..8b74a4a725 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -32,14 +32,6 @@ softmodem_params_t *get_softmodem_params(void) void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) { } -int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, - NR_UE_MAC_INST_t *mac, - NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom, - const type_bsr_t *bsr, - uint8_t *mac_ce_end) -{ - return 0; -} int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end) { return 0; @@ -77,6 +69,14 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, { return 0; } +NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup) +{ + return NULL; +} +NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup) +{ + return NULL; +} } #include #include "common/utils/LOG/log.h" @@ -84,22 +84,31 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac, TEST(test_init_ra, four_step_cbra) { NR_UE_MAC_INST_t mac = {0}; - NR_PRACH_RESOURCES_t prach_resources = {0}; + RA_config_t *ra = &mac.ra; NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0}; - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = nullptr; + NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0}; NR_UE_UL_BWP_t current_bwp; + NR_UE_DL_BWP_t dl_bwp; mac.current_UL_BWP = ¤t_bwp; + mac.current_DL_BWP = &dl_bwp; long scs = 1; current_bwp.scs = scs; + current_bwp.bwp_id = 0; + dl_bwp.bwp_id = 0; current_bwp.channel_bandwidth = 40; nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs; + nr_rach_ConfigCommon.rach_ConfigGeneric = rach_ConfigGeneric; + current_bwp.rach_ConfigCommon = &nr_rach_ConfigCommon; + ra->rach_ConfigDedicated = &rach_ConfigDedicated; mac.p_Max = 23; mac.nr_band = 78; mac.frame_structure.frame_type = TDD; mac.frequency_range = FR1; + mac.first_sync_frame = 0; + int frame = 151; - init_RA(&mac, &prach_resources, &nr_rach_ConfigCommon, &rach_ConfigGeneric, rach_ConfigDedicated); + init_RA(&mac, frame); EXPECT_EQ(mac.ra.ra_type, RA_4_STEP); EXPECT_EQ(mac.state, UE_PERFORMING_RA); @@ -110,25 +119,34 @@ TEST(test_init_ra, four_step_cbra) TEST(test_init_ra, four_step_cfra) { NR_UE_MAC_INST_t mac = {0}; - NR_PRACH_RESOURCES_t prach_resources = {0}; + RA_config_t *ra = &mac.ra; NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; NR_RACH_ConfigGeneric_t rach_ConfigGeneric = {0}; NR_UE_UL_BWP_t current_bwp; + NR_UE_DL_BWP_t dl_bwp; mac.current_UL_BWP = ¤t_bwp; + mac.current_DL_BWP = &dl_bwp; long scs = 1; current_bwp.scs = scs; + current_bwp.bwp_id = 0; + dl_bwp.bwp_id = 0; current_bwp.channel_bandwidth = 40; nr_rach_ConfigCommon.msg1_SubcarrierSpacing = &scs; + nr_rach_ConfigCommon.rach_ConfigGeneric = rach_ConfigGeneric; + current_bwp.rach_ConfigCommon = &nr_rach_ConfigCommon; mac.p_Max = 23; mac.nr_band = 78; mac.frame_structure.frame_type = TDD; mac.frequency_range = FR1; + mac.first_sync_frame = 0; + int frame = 151; NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0}; struct NR_CFRA cfra; rach_ConfigDedicated.cfra = &cfra; + ra->rach_ConfigDedicated = &rach_ConfigDedicated; - init_RA(&mac, &prach_resources, &nr_rach_ConfigCommon, &rach_ConfigGeneric, &rach_ConfigDedicated); + init_RA(&mac, frame); EXPECT_EQ(mac.ra.ra_type, RA_4_STEP); EXPECT_EQ(mac.state, UE_PERFORMING_RA); From c17881e8d5ff85bedbdacbc6e7d707113129672b Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 18 Oct 2024 08:19:46 +0200 Subject: [PATCH 08/34] implmenent RA trigger for PDCCH order (DCI initiated RA) --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 9 ++- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 25 ++++++--- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 58 +++++++++++--------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 +- 5 files changed, 60 insertions(+), 38 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index d80a279952..ee0c226af4 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -293,7 +293,13 @@ typedef struct { } NR_PRACH_RESOURCES_t; typedef struct { + bool active; + uint32_t preamble_index; + uint32_t ssb_index; + uint32_t prach_mask; +} NR_pdcch_order_config_t; +typedef struct { // pointer to RACH config dedicated NR_RACH_ConfigDedicated_t *rach_ConfigDedicated; /// state of RA procedure @@ -361,8 +367,7 @@ typedef struct { /// Transmitted UE Contention Resolution Identifier uint8_t cont_res_id[6]; - /// BeamfailurerecoveryConfig - NR_BeamFailureRecoveryConfig_t RA_BeamFailureRecoveryConfig; + NR_pdcch_order_config_t pdcch_order; NR_PRACH_RESOURCES_t prach_resources; } RA_config_t; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 22f0cbaf84..f86f646c5f 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -353,7 +353,7 @@ void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id); void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); -void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac); +void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order); void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac); int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index b16def686f..ccf02df0c1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -216,8 +216,6 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) n_prbs, start_prb); - // TODO if the Random Access procedure is initiated by PDCCH order - // and if the ra-PreambleIndex explicitly provided by PDCCH is not 0b000000 // TODO if the Random Access procedure was initiated for SI request // and the Random Access Resources for SI request have been explicitly provided by RRC @@ -228,10 +226,14 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) NR_RACH_ConfigCommonTwoStepRA_r16_t *twostep_conf = NULL; NR_RACH_ConfigDedicated_t *rach_Dedicated = ra->rach_ConfigDedicated; - if (rach_Dedicated && rach_Dedicated->cfra) { - // if the Random Access procedure was initiated for reconfiguration with sync and - // if the contention-free Random Access Resources for 4-step RA type have been explicitly provided - // in rach-ConfigDedicated for the BWP selected for Random Access procedure + + // if the Random Access procedure is initiated by PDCCH order + // and if the ra-PreambleIndex explicitly provided by PDCCH is not 0b000000 + bool pdcch_order = (ra->pdcch_order.active && ra->pdcch_order.preamble_index != 0xb000000) ? true : false; + // or if the Random Access procedure was initiated for reconfiguration with sync and + // if the contention-free Random Access Resources for 4-step RA type have been explicitly provided + // in rach-ConfigDedicated for the BWP selected for Random Access procedure + if ((rach_Dedicated && rach_Dedicated->cfra) || pdcch_order) { LOG_I(MAC, "Initialization of 4-Step CFRA procedure\n"); ra->ra_type = RA_4_STEP; ra->cfra = true; @@ -1049,12 +1051,19 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr } } -void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac) +void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order) { LOG_W(NR_MAC, "Triggering new RA procedure for UE with RNTI %x\n", mac->crnti); mac->state = UE_PERFORMING_RA; reset_ra(mac, false); - mac->ra.msg3_C_RNTI = true; + RA_config_t *ra = &mac->ra; + ra->msg3_C_RNTI = true; + if (pdcch_order) { + ra->pdcch_order.active = true; + ra->pdcch_order.preamble_index = pdcch_order->ra_preamble_index; + ra->pdcch_order.ssb_index = pdcch_order->ss_pbch_index; + ra->pdcch_order.prach_mask = pdcch_order->prach_mask_index; + } } void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index c150cc29cd..d6f0226482 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2929,7 +2929,7 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in nr_timer_start(mac->data_inactivity_timer); // DL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised" if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) { - trigger_MAC_UE_RA(mac); + trigger_MAC_UE_RA(mac, NULL); break; } nr_ue_process_mac_pdu(mac, dl_info, pdu_id); @@ -2991,7 +2991,11 @@ static void extract_10_si_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dc EXTRACT_DCI_ITEM(dci_pdu_rel15->system_info_indicator, 1); } -static void extract_10_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos, const int N_RB) +static bool extract_10_c_rnti(NR_UE_MAC_INST_t *mac, + dci_pdu_rel15_t *dci_pdu_rel15, + const uint8_t *dci_pdu, + int pos, + const int N_RB) { LOG_D(NR_MAC_DCI, "Received dci 1_0 C rnti\n"); @@ -3014,29 +3018,31 @@ static void extract_10_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci EXTRACT_DCI_ITEM(dci_pdu_rel15->ss_pbch_index, 6); // prach_mask_index 4 bits EXTRACT_DCI_ITEM(dci_pdu_rel15->prach_mask_index, 4); + trigger_MAC_UE_RA(mac, dci_pdu_rel15); + return true; } // end if - else { - // Time domain assignment 4bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->time_domain_assignment.val, 4); - // VRB to PRB mapping 1bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->vrb_to_prb_mapping.val, 1); - // MCS 5bit //bit over 32, so dci_pdu ++ - EXTRACT_DCI_ITEM(dci_pdu_rel15->mcs, 5); - // New data indicator 1bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->ndi, 1); - // Redundancy version 2bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2); - // HARQ process number 4/5 bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->harq_pid.val, dci_pdu_rel15->harq_pid.nbits); - // Downlink assignment index 2bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->dai[0].val, 2); - // TPC command for scheduled PUCCH 2bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->tpc, 2); - // PUCCH resource indicator 3bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->pucch_resource_indicator, 3); - // PDSCH-to-HARQ_feedback timing indicator 3bit - EXTRACT_DCI_ITEM(dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, 3); - } // end else + + // Time domain assignment 4bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->time_domain_assignment.val, 4); + // VRB to PRB mapping 1bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->vrb_to_prb_mapping.val, 1); + // MCS 5bit //bit over 32, so dci_pdu ++ + EXTRACT_DCI_ITEM(dci_pdu_rel15->mcs, 5); + // New data indicator 1bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->ndi, 1); + // Redundancy version 2bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->rv, 2); + // HARQ process number 4/5 bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->harq_pid.val, dci_pdu_rel15->harq_pid.nbits); + // Downlink assignment index 2bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->dai[0].val, 2); + // TPC command for scheduled PUCCH 2bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->tpc, 2); + // PUCCH resource indicator 3bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->pucch_resource_indicator, 3); + // PDSCH-to-HARQ_feedback timing indicator 3bit + EXTRACT_DCI_ITEM(dci_pdu_rel15->pdsch_to_harq_feedback_timing_indicator.val, 3); + return false; } static void extract_00_c_rnti(dci_pdu_rel15_t *dci_pdu_rel15, const uint8_t *dci_pdu, int pos) @@ -3297,7 +3303,9 @@ static nr_dci_format_t nr_extract_dci_00_10(NR_UE_MAC_INST_t *mac, int n_RB = get_nrb_for_dci(mac, format, ss_type); if (n_RB == 0) return NR_DCI_NONE; - extract_10_c_rnti(dci_pdu_rel15, dci_pdu, pos, n_RB); + bool pdcch_order = extract_10_c_rnti(mac, dci_pdu_rel15, dci_pdu, pos, n_RB); + if (pdcch_order) + return NR_DCI_NONE; } else { format = NR_UL_DCI_FORMAT_0_0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 94f9c80277..0872787bd5 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1144,7 +1144,7 @@ void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac) { if (get_softmodem_params()->phy_test) return; // cannot trigger RA in phytest mode - trigger_MAC_UE_RA(mac); + trigger_MAC_UE_RA(mac, NULL); // release PUCCH for all Serving Cells; // release SRS for all Serving Cells; release_PUCCH_SRS(mac); @@ -1352,7 +1352,7 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) && (mac->state == UE_CONNECTED || (ra->ra_state == nrRA_WAIT_RAR && ra->cfra))) { if (!nr_timer_is_active(&mac->time_alignment_timer) && mac->state == UE_CONNECTED && !get_softmodem_params()->phy_test) { // UL data arrival during RRC_CONNECTED when UL synchronisation status is "non-synchronised" - trigger_MAC_UE_RA(mac); + trigger_MAC_UE_RA(mac, NULL); return; } // Getting IP traffic to be transmitted From 60920ed16199ff5eb93738b2ecde10766db1c7fb Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 21 Oct 2024 11:58:37 +0200 Subject: [PATCH 09/34] avoid unnecessary call to nr_write_ce_msg3_pdu this is for do-ra mostly and it was just called to compute MSG3 size which is fixed and known --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 -- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 7 ++----- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 15 --------------- .../NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp | 4 ---- 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index f86f646c5f..b0627c7bec 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -180,8 +180,6 @@ typedef struct { enum { b_none, b_long, b_short, b_short_trunc, b_long_trunc } type_bsr; } type_bsr_t; -int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end); - int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, NR_SINGLE_ENTRY_PHR_MAC_CE *power_headroom, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index ccf02df0c1..1a46e65eb2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -142,11 +142,8 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) ra->Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT); } - } else if (!IS_SA_MODE(get_softmodem_params())) { - uint8_t temp_pdu[16] = {0}; - size_sdu = nr_write_ce_msg3_pdu(temp_pdu, mac, mac->crnti, temp_pdu + sizeof(temp_pdu)); - ra->Msg3_size = size_sdu; - } + } else if (!IS_SA_MODE(get_softmodem_params())) + ra->Msg3_size = sizeof(uint16_t) + sizeof(NR_MAC_SUBHEADER_FIXED); // Random acces procedure initialization mac->state = UE_PERFORMING_RA; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index d6f0226482..54f047f46d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3739,21 +3739,6 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i } } -int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end) -{ - uint8_t *pdu = mac_ce; - if (IS_SA_MODE(get_softmodem_params()) && mac->ra.ra_state != nrRA_SUCCEEDED) { - LOG_D(NR_MAC, "Generating C-RNTI MAC CE with C-RNTI %x\n", crnti); - *(NR_MAC_SUBHEADER_FIXED *)mac_ce = (NR_MAC_SUBHEADER_FIXED){.R = 0, .LCID = UL_SCH_LCID_C_RNTI}; - mac_ce += sizeof(NR_MAC_SUBHEADER_FIXED); - // C-RNTI MAC CE (2 octets) - memcpy(mac_ce, &crnti, sizeof(crnti)); - // update pointer and length - mac_ce += sizeof(crnti); - } - return mac_ce - pdu; -} - /** * Function: generating MAC CEs (MAC CE and subheader) for the ULSCH PDU * Parameters: diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index 8b74a4a725..914d0ef984 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -32,10 +32,6 @@ softmodem_params_t *get_softmodem_params(void) void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) { } -int nr_write_ce_msg3_pdu(uint8_t *mac_ce, NR_UE_MAC_INST_t *mac, rnti_t crnti, uint8_t *mac_ce_end) -{ - return 0; -} tbs_size_t mac_rlc_data_req(const module_id_t module_idP, const rnti_t rntiP, const eNB_index_t eNB_index, From 95971514a06162ca054c71ef820b75dd4c510899 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 22 Oct 2024 19:09:52 +0200 Subject: [PATCH 10/34] Random Access Resource selection for 4- and 2-step RA --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 16 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 12 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 639 ++++++++++-------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 1 - .../tests/test_nr_ue_ra_procedures.cpp | 4 +- openair2/RRC/NR/nr_rrc_config.c | 6 +- 6 files changed, 378 insertions(+), 300 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index ee0c226af4..79fdb4c0d1 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -333,6 +333,8 @@ typedef struct { uint8_t ssb_nb_in_ro; int zeroCorrelationZoneConfig; int restricted_set_config; + // selected SSB for RACH + int ra_ssb; /// Random-access window counter int16_t RA_window_cnt; /// Flag to monitor if matching RAPID was received in RAR @@ -341,25 +343,21 @@ typedef struct { uint8_t RA_BI_found; /// Random-access backoff counter int16_t RA_backoff_indicator; - /// Flag to indicate whether preambles Group A was used - uint8_t RA_usedGroupA; + /// Flag to indicate whether preambles Group A is selected + bool RA_GroupA; /// RA backoff counter int16_t RA_backoff_cnt; /// RA max number of preamble transmissions int preambleTransMax; - /// Nb of preambles per SSB - long cb_preambles_per_ssb; - int starting_preamble_nb; - /// Received TPC command (in dB) from RAR int8_t Msg3_TPC; - /// Flag to indicate whether it is the first Msg3 to be transmitted - bool first_Msg3; /// RA Msg3 size in bytes uint8_t Msg3_size; /// Msg3 buffer uint8_t *Msg3_buffer; - + // initial Random Access Preamble power + int preambleRxTargetPower; + int deltaPreamble; bool msg3_C_RNTI; /// Random-access Contention Resolution Timer diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index b0627c7bec..724ef743ba 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -321,18 +321,6 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac); @returns indication to generate PRACH to phy */ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx); -/* \brief Function implementing the routine for the selection of Random Access resources (5.1.2 TS 38.321). -@param mac pointer to MAC instance -@param CC_id Component Carrier Index -@param gNB_index gNB index -@param rach_ConfigDedicated -@returns void */ -void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, - int CC_id, - uint8_t gNB_id, - NR_PRACH_RESOURCES_t *prach_resources, - NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); - void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 1a46e65eb2..229a977be2 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -40,7 +40,6 @@ #include "openair2/LAYER2/RLC/rlc.h" #include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" - int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; @@ -90,10 +89,337 @@ static void set_preambleTransMax(RA_config_t *ra, long preambleTransMax) } } +static int get_Msg3SizeGroupA(long ra_Msg3SizeGroupA) +{ + int bits = 0; + switch (ra_Msg3SizeGroupA) { + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b56: + bits = 56; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b144: + bits = 144; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b208: + bits = 208; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b256: + bits = 256; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b282: + bits = 282; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b480: + bits = 480; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b640: + bits = 640; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b800: + bits = 800; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b1000: + bits = 1000; + break; + case NR_RACH_ConfigCommon__groupBconfigured__ra_Msg3SizeGroupA_b72: + bits = 72; + break; + default: + AssertFatal(false, "Unknown ra-Msg3SizeGroupA %lu\n", ra_Msg3SizeGroupA); + } + return bits / 8; // returning bytes +} + +static int get_messagePowerOffsetGroupB(long messagePowerOffsetGroupB) +{ + int pow_offset = 0; + switch (messagePowerOffsetGroupB) { + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_minusinfinity: + pow_offset = INT_MIN; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB0: + pow_offset = 0; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB5: + pow_offset = 5; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB8: + pow_offset = 8; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB10: + pow_offset = 10; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB12: + pow_offset = 12; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB15: + pow_offset = 15; + break; + case NR_RACH_ConfigCommon__groupBconfigured__messagePowerOffsetGroupB_dB18: + pow_offset = 18; + break; + default: + AssertFatal(false, "Unknown messagePowerOffsetGroupB %lu\n", messagePowerOffsetGroupB); + } + return pow_offset; +} + +static void select_preamble_group(NR_UE_MAC_INST_t *mac) +{ + RA_config_t *ra = &mac->ra; + // TODO if the RA_TYPE is switched from 2-stepRA to 4-stepRA + + if (!ra->Msg3_buffer) { // if Msg3 buffer is empty + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; + if (nr_rach_ConfigCommon && nr_rach_ConfigCommon->groupBconfigured) { // if Random Access Preambles group B is configured + struct NR_RACH_ConfigCommon__groupBconfigured *groupB = nr_rach_ConfigCommon->groupBconfigured; + // if the potential Msg3 size (UL data available for transmission plus MAC subheader(s) and, + // where required, MAC CEs) is greater than ra-Msg3SizeGroupA + // if the pathloss is less than PCMAX (of the Serving Cell performing the Random Access Procedure) + // – preambleReceivedTargetPower – msg3-DeltaPreamble – messagePowerOffsetGroupB + int groupB_pow_offset = get_messagePowerOffsetGroupB(groupB->messagePowerOffsetGroupB); + int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->deltaPreamble - groupB_pow_offset; + int pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); + // TODO if the Random Access procedure was initiated for the CCCH logical channel and the CCCH SDU size + // plus MAC subheader is greater than ra-Msg3SizeGroupA + if (ra->Msg3_size > get_Msg3SizeGroupA(groupB->ra_Msg3SizeGroupA) && pathloss < PLThreshold) + ra->RA_GroupA = false; + else + ra->RA_GroupA = true; + } else + ra->RA_GroupA = true; + } + // else if Msg3 is being retransmitted, we keep what used in first transmission of Msg3 +} + +typedef struct{ + float ssb_per_ro; + int preambles_per_ssb; +} ssb_ro_preambles_t; + +static ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config) +{ + ssb_ro_preambles_t ret = {0}; + switch (config->present) { + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: + ret.ssb_per_ro = 1 / 8; + ret.preambles_per_ssb = (config->choice.oneEighth + 1) << 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: + ret.ssb_per_ro = 1 / 4; + ret.preambles_per_ssb = (config->choice.oneFourth + 1) << 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: + ret.ssb_per_ro = 1 / 2; + ret.preambles_per_ssb = (config->choice.oneHalf + 1) << 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: + ret.ssb_per_ro = 1; + ret.preambles_per_ssb = (config->choice.one + 1) << 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: + ret.ssb_per_ro = 2; + ret.preambles_per_ssb = (config->choice.two + 1) << 2; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: + ret.ssb_per_ro = 4; + ret.preambles_per_ssb = config->choice.four; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: + ret.ssb_per_ro = 8; + ret.preambles_per_ssb = config->choice.eight; + break; + case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: + ret.ssb_per_ro = 16; + ret.preambles_per_ssb = config->choice.sixteen; + break; + default: + AssertFatal(false, "Invalid ssb_perRACH_OccasionAndCB_PreamblesPerSSB\n"); + } + return ret; +} + +static ssb_ro_preambles_t get_ssb_ro_preambles_2step(struct NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16 *config) +{ + ssb_ro_preambles_t ret = {0}; + switch (config->present) { + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneEighth : + ret.ssb_per_ro = 1 / 8; + ret.preambles_per_ssb = (config->choice.oneEighth + 1) << 2; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneFourth : + ret.ssb_per_ro = 1 / 4; + ret.preambles_per_ssb = (config->choice.oneFourth + 1) << 2; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneHalf : + ret.ssb_per_ro = 1 / 2; + ret.preambles_per_ssb = (config->choice.oneHalf + 1) << 2; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_one : + ret.ssb_per_ro = 1; + ret.preambles_per_ssb = (config->choice.one + 1) << 2; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_two : + ret.ssb_per_ro = 2; + ret.preambles_per_ssb = (config->choice.two + 1) << 2; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_four : + ret.ssb_per_ro = 4; + ret.preambles_per_ssb = config->choice.four; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_eight : + ret.ssb_per_ro = 8; + ret.preambles_per_ssb = config->choice.eight; + break; + case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_sixteen : + ret.ssb_per_ro = 16; + ret.preambles_per_ssb = config->choice.sixteen; + break; + default : + AssertFatal(false, "Invalid msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16\n"); + } + return ret; +} + +static void config_preamble_index(NR_UE_MAC_INST_t *mac) +{ + RA_config_t *ra = &mac->ra; + // Random seed generation + unsigned int seed; + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // Overwrite seed with non-random seed for IQ player/recorder + seed = 1; + } else { + // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int) + seed = (unsigned int)(rdtsc_oai() & ~0); + } + + NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; + ssb_ro_preambles_t config_info; + int nb_of_preambles = 64; + bool groupBconfigured = false; + int preamb_ga = 0; + if (ra->ra_type == RA_4_STEP) { + AssertFatal(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB, + "Not expeting ssb_perRACH_OccasionAndCB_PreamblesPerSSB to be NULL here\n"); + config_info = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles) + nb_of_preambles = *nr_rach_ConfigCommon->totalNumberOfRA_Preambles; + // Amongst the contention-based Random Access Preambles associated with an SSB the first numberOfRA-PreamblesGroupA + // included in groupBconfigured Random Access Preambles belong to Random Access Preambles group A. + // The remaining Random Access Preambles associated with the SSB belong to Random Access Preambles group B (if configured) + select_preamble_group(mac); + if (nr_rach_ConfigCommon->groupBconfigured) { + groupBconfigured = true; + preamb_ga = nr_rach_ConfigCommon->groupBconfigured->numberOfRA_PreamblesGroupA; + } + } else { + NR_RACH_ConfigCommonTwoStepRA_r16_t *twostep = &mac->current_UL_BWP->msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16; + AssertFatal(twostep->groupB_ConfiguredTwoStepRA_r16 == NULL, "GroupB preambles not supported for 2-step RA\n"); + ra->RA_GroupA = true; + // The field is mandatory present if the 2-step random access type occasions are shared with 4-step random access type, + // otherwise the field is not present + bool sharedROs = twostep->msgA_CB_PreamblesPerSSB_PerSharedRO_r16 != NULL; + AssertFatal(sharedROs == false, "Shared ROs between 2- and 4-step RA not supported\n"); + + // For Type-2 random access procedure with separate configuration of PRACH occasions with Type-1 random access procedure + // configuration by msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB when provided; + // otherwise, by ssb-perRACH-OccasionAndCB-PreamblesPerSSB + if (twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16) + config_info = get_ssb_ro_preambles_2step(twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16); + else + config_info = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + if (twostep->msgA_TotalNumberOfRA_Preambles_r16) + nb_of_preambles = *twostep->msgA_TotalNumberOfRA_Preambles_r16; + } + + int groupOffset = 0; + if (groupBconfigured) { + AssertFatal(preamb_ga < nb_of_preambles, "Nb of preambles for groupA not compatible with total number of preambles\n"); + if (!ra->RA_GroupA) { // groupB + groupOffset = preamb_ga; + nb_of_preambles = nb_of_preambles - preamb_ga; + } else { + nb_of_preambles = preamb_ga; + } + } + int rand_preamb = (rand_r(&seed) % config_info.preambles_per_ssb); + if (config_info.ssb_per_ro < 1) + ra->ra_PreambleIndex = groupOffset + rand_preamb; + else { + ssb_list_info_t *ssb_list = &mac->ssb_list[mac->current_DL_BWP->bwp_id]; + int ssb_pr_idx = ssb_list->nb_ssb_per_index[ra->ra_ssb] % (int)config_info.ssb_per_ro; + ra->ra_PreambleIndex = groupOffset + (ssb_pr_idx * config_info.preambles_per_ssb) + rand_preamb; + } + AssertFatal(ra->ra_PreambleIndex < nb_of_preambles, + "Error! Selected preamble %d which exceeds number of prambles available %d\n", + ra->ra_PreambleIndex, + nb_of_preambles); +} + +// 38.321 Section 5.1.2 Random Access Resource selection +static void ra_resource_selection(NR_UE_MAC_INST_t *mac) +{ + RA_config_t *ra = &mac->ra; + ra->ra_ssb = -1; // init as not selected + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; + if (ra->ra_type == RA_4_STEP) { + // TODO if the Random Access procedure was initiated for SpCell beam failure recovery + // TODO if the Random Access procedure was initiated for SI request + + if (ra->pdcch_order.active && ra->pdcch_order.preamble_index != 0xb000000) { + // set the PREAMBLE_INDEX to the signalled ra-PreambleIndex; + ra->ra_PreambleIndex = ra->pdcch_order.preamble_index; + // select the SSB signalled by PDCCH + ra->ra_ssb = ra->pdcch_order.ssb_index; + } else if (rach_ConfigDedicated && rach_ConfigDedicated->cfra) { + NR_CFRA_t *cfra = rach_ConfigDedicated->cfra; + AssertFatal(cfra->occasions == NULL, "Dedicated PRACH occasions for CFRA not supported\n"); + AssertFatal(cfra->resources.present == NR_CFRA__resources_PR_ssb, "SSB-based CFRA supported only\n"); + struct NR_CFRA__resources__ssb *ssb_list = cfra->resources.choice.ssb; + for (int i = 0; i < ssb_list->ssb_ResourceList.list.count; i++) { + NR_CFRA_SSB_Resource_t *res = ssb_list->ssb_ResourceList.list.array[i]; + // TODO select an SSB with SS-RSRP above rsrp-ThresholdSSB amongst the associated SSBs + if (res->ssb == mac->mib_ssb) { + ra->ra_ssb = mac->mib_ssb; + // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB + ra->ra_PreambleIndex = res->ra_PreambleIndex; + break; + } + } + } else { // for the contention-based Random Access preamble selection + // TODO if at least one of the SSBs with SS-RSRP above rsrp-ThresholdSSB is available + // else select any SSB + ra->ra_ssb = mac->mib_ssb; + config_preamble_index(mac); + } + } else { // 2-step RA + // if the contention-free 2-step RA type Resources associated with SSBs have been explicitly provided in rach-ConfigDedicated + // TODO and at least one SSB with SS-RSRP above msgA-RSRP-ThresholdSSB amongst the associated SSBs is available + if (ra->cfra) { + AssertFatal(rach_ConfigDedicated->ext1 && rach_ConfigDedicated->ext1->cfra_TwoStep_r16, + "Two-step CFRA should be configured here\n"); + NR_CFRA_TwoStep_r16_t *cfra = rach_ConfigDedicated->ext1->cfra_TwoStep_r16; + AssertFatal(cfra->occasionsTwoStepRA_r16 == NULL, "Dedicated PRACH occasions for CFRA not supported\n"); + for (int i = 0; i < cfra->resourcesTwoStep_r16.ssb_ResourceList.list.count; i++) { + NR_CFRA_SSB_Resource_t *res = cfra->resourcesTwoStep_r16.ssb_ResourceList.list.array[i]; + if (res->ssb == mac->mib_ssb) { + ra->ra_ssb = mac->mib_ssb; + // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB + ra->ra_PreambleIndex = res->ra_PreambleIndex; + break; + } + } + } else { // for the contention-based Random Access Preamble selection + // TODO if at least one of the SSBs with SS-RSRP above msgA-RSRP-ThresholdSSB is available + // else select any SSB + ra->ra_ssb = mac->mib_ssb; + config_preamble_index(mac); + } + } +} + // Random Access procedure initialization as per 5.1.1 and initialization of variables specific // to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) -// todo: -// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX (currently hardcoded to 0) bool init_RA(NR_UE_MAC_INST_t *mac, int frame) { RA_config_t *ra = &mac->ra; @@ -297,11 +623,20 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) // TODO msgA-TransMax not implemented // TODO ra-Prioritization not implemented - ra->ra_PreambleIndex = -1; - ra->RA_usedGroupA = 1; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreambleReceivedTargetPower_r16) + ra->preambleRxTargetPower = *twostep_generic->msgA_PreambleReceivedTargetPower_r16; + else + ra->preambleRxTargetPower = rach_ConfigGeneric->preambleReceivedTargetPower; + + if (ra->ra_type == RA_2_STEP + && current_UL_BWP->msgA_ConfigCommon_r16 + && current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16 + && current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16) + ra->deltaPreamble = *current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16 << 1; + else + ra->deltaPreamble = mac->current_UL_BWP->msg3_DeltaPreamble ? *mac->current_UL_BWP->msg3_DeltaPreamble << 1 : 0; + ra->RA_RAPID_found = 0; - ra->first_Msg3 = true; - ra->starting_preamble_nb = 0; ra->RA_backoff_cnt = 0; ra->RA_window_cnt = -1; @@ -309,15 +644,12 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) } /* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ -static int8_t nr_get_DELTA_PREAMBLE(const NR_UE_MAC_INST_t *mac, int CC_id, uint16_t prach_format) +static int8_t nr_get_DELTA_PREAMBLE(const NR_UE_MAC_INST_t *mac, uint16_t prach_format) { const NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; int prach_sequence_length = nr_rach_ConfigCommon->prach_RootSequenceIndex.present - 1; - AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); - // Preamble formats given by prach_ConfigurationIndex and tables 6.3.3.2-2 and 6.3.3.2-2 in TS 38.211 - unsigned int prachConfigIndex = nr_rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; if (prach_sequence_length == 0) { @@ -343,37 +675,36 @@ static int8_t nr_get_DELTA_PREAMBLE(const NR_UE_MAC_INST_t *mac, int CC_id, uint } } else { // SCS configuration from msg1_SubcarrierSpacing and table 4.2-1 in TS 38.211 - AssertFatal(nr_rach_ConfigCommon->msg1_SubcarrierSpacing, "msg1_SubcarrierSpacing required but missing\n"); NR_SubcarrierSpacing_t scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing; AssertFatal(scs >= NR_SubcarrierSpacing_kHz15 && scs <= NR_SubcarrierSpacing_spare1, "Unknown msg1_SubcarrierSpacing %lu\n", scs); const unsigned int mu = scs; - switch (prach_format) { // short preamble formats case 0: case 3: - return 8 + 3*mu; + return 8 + 3 * mu; case 1: case 4: case 8: - return 5 + 3*mu; + return 5 + 3 * mu; case 2: case 5: - return 3 + 3*mu; + return 3 + 3 * mu; case 6: - return 3*mu; + return 3 * mu; case 7: - return 5 + 3*mu; + return 5 + 3 * mu; default: - AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", - mac->ue_id, - prach_format, - prachConfigIndex); + AssertFatal(false, + "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", + mac->ue_id, + prach_format, + prachConfigIndex); } } return 0; @@ -386,14 +717,14 @@ static int8_t nr_get_DELTA_PREAMBLE(const NR_UE_MAC_INST_t *mac, int CC_id, uint // - RA_PREAMBLE_POWER_RAMPING_STEP dB // - POWER_OFFSET_2STEP_RA dB // returns receivedTargerPower in dBm -static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources, uint8_t CC_id) +static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources) { int8_t receivedTargerPower; int8_t delta_preamble; NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; - delta_preamble = nr_get_DELTA_PREAMBLE(mac, CC_id, prach_resources->prach_format); + delta_preamble = nr_get_DELTA_PREAMBLE(mac, prach_resources->prach_format); receivedTargerPower = preambleReceivedTargetPower + delta_preamble + @@ -404,220 +735,6 @@ static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t * return receivedTargerPower; } -void ssb_rach_config(RA_config_t *ra, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon) -{ - // Determine the SSB to RACH mapping ratio - // ======================================= - - NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - bool multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB - uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB - int total_preambles_per_ssb; - uint8_t ssb_nb_in_ro; - int numberOfRA_Preambles = 64; - - switch (ssb_perRACH_config){ - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 8; - ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 4; - ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1); - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: - multiple_ssb_per_ro = false; - ssb_rach_ratio = 2; - ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1); - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 1; - ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1); - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 2; - ra->cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1); - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 4; - ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 8; - ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight; - break; - case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen: - multiple_ssb_per_ro = true; - ssb_rach_ratio = 16; - ra->cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen; - break; - default: - AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config); - } - - if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles) - numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles); - - // Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration - if ((true == multiple_ssb_per_ro) && (ssb_rach_ratio > 1)) { - total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio; - - ssb_nb_in_ro = ra->ssb_nb_in_ro; - ra->starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro; - } else { - total_preambles_per_ssb = numberOfRA_Preambles; - ra->starting_preamble_nb = 0; - } -} - -// This routine implements RA preamble configuration according to -// section 5.1 (Random Access procedure) of 3GPP TS 38.321 version 16.2.1 Release 16 -void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t *mac, int16_t dl_pathloss){ - - int messageSizeGroupA = 0; - int sizeOfRA_PreamblesGroupA = 0; - int messagePowerOffsetGroupB = 0; - int PLThreshold = 0; - long deltaPreamble_Msg3 = 0; - uint8_t noGroupB = 0; - // Random seed generation - unsigned int seed; - - if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { - // Overwrite seed with non-random seed for IQ player/recorder - seed = 1; - } else { - // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int) - seed = (unsigned int) (rdtsc_oai() & ~0); - } - - RA_config_t *ra = &mac->ra; - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - - if (mac->current_UL_BWP->msg3_DeltaPreamble) { - deltaPreamble_Msg3 = (*mac->current_UL_BWP->msg3_DeltaPreamble) * 2; // dB - LOG_D(MAC, "In %s: deltaPreamble_Msg3 set to %ld\n", __FUNCTION__, deltaPreamble_Msg3); - } - - if (!setup->groupBconfigured) { - noGroupB = 1; - LOG_D(MAC, "In %s:%d: preambles group B is not configured...\n", __FUNCTION__, __LINE__); - } else { - // RA preambles group B is configured - // - Random Access Preambles group B is configured for 4-step RA type - // - Defining the number of RA preambles in RA Preamble Group A for each SSB - LOG_D(MAC, "In %s:%d: preambles group B is configured...\n", __FUNCTION__, __LINE__); - sizeOfRA_PreamblesGroupA = setup->groupBconfigured->numberOfRA_PreamblesGroupA; - switch (setup->groupBconfigured->ra_Msg3SizeGroupA){ - /* - Threshold to determine the groups of RA preambles */ - case 0: - messageSizeGroupA = 56; - break; - case 1: - messageSizeGroupA = 144; - break; - case 2: - messageSizeGroupA = 208; - break; - case 3: - messageSizeGroupA = 256; - break; - case 4: - messageSizeGroupA = 282; - break; - case 5: - messageSizeGroupA = 480; - break; - case 6: - messageSizeGroupA = 640; - break; - case 7: - messageSizeGroupA = 800; - break; - case 8: - messageSizeGroupA = 1000; - break; - case 9: - messageSizeGroupA = 72; - break; - default: - AssertFatal(1 == 0, "Unknown ra_Msg3SizeGroupA %lu\n", setup->groupBconfigured->ra_Msg3SizeGroupA); - /* todo cases 10 -15*/ - } - - /* Power offset for preamble selection in dB */ - messagePowerOffsetGroupB = -9999; - switch (setup->groupBconfigured->messagePowerOffsetGroupB){ - case 0: - messagePowerOffsetGroupB = -9999; - break; - case 1: - messagePowerOffsetGroupB = 0; - break; - case 2: - messagePowerOffsetGroupB = 5; - break; - case 3: - messagePowerOffsetGroupB = 8; - break; - case 4: - messagePowerOffsetGroupB = 10; - break; - case 5: - messagePowerOffsetGroupB = 12; - break; - case 6: - messagePowerOffsetGroupB = 15; - break; - case 7: - messagePowerOffsetGroupB = 18; - break; - default: - AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", setup->groupBconfigured->messagePowerOffsetGroupB); - } - - PLThreshold = prach_resources->Pc_max - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB; - - } - - /* Msg3 has not been transmitted yet */ - if (ra->first_Msg3) { - if(ra->ra_PreambleIndex < 0 || ra->ra_PreambleIndex > 63) { - if (noGroupB) { - // use Group A preamble - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % ra->cb_preambles_per_ssb); - ra->RA_usedGroupA = 1; - } else if ((ra->Msg3_size < messageSizeGroupA) && (dl_pathloss > PLThreshold)) { - // Group B is configured and RA preamble Group A is used - // - todo add condition on CCCH_sdu_size for initiation by CCCH - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % sizeOfRA_PreamblesGroupA); - ra->RA_usedGroupA = 1; - } else { - // Group B preamble is configured and used - // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A - // the remaining belong to RA Preambles Group B - ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r(&seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); - ra->RA_usedGroupA = 0; - } - } - } else { // Msg3 is being retransmitted - if (ra->RA_usedGroupA && noGroupB) { - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % ra->cb_preambles_per_ssb); - } else if (ra->RA_usedGroupA && !noGroupB){ - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % sizeOfRA_PreamblesGroupA); - } else { - ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r(&seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); - } - } -} - // This routine implements Section 5.1.2 (UE Random Access Resource Selection) // and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 // - currently the PRACH preamble is set through RRC configuration for 4-step CFRA mode @@ -638,38 +755,13 @@ void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t // - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission // - Contention-based RA preamble selection: // -- selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB -void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, - int CC_id, - uint8_t gNB_id, - NR_PRACH_RESOURCES_t *prach_resources, - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) +static void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, + NR_PRACH_RESOURCES_t *prach_resources, + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) { - RA_config_t *ra = &mac->ra; - - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - - LOG_D(MAC, "Getting PRACH resources (first_Msg3 %d)\n", ra->first_Msg3); - - if (rach_ConfigDedicated) { - if (rach_ConfigDedicated->cfra){ - uint8_t cfra_ssb_resource_idx = 0; - ra->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex; - LOG_D(MAC, "Selected RA preamble index %d for contention-free random access procedure for SSB with Id %d\n", - ra->ra_PreambleIndex, - cfra_ssb_resource_idx); - } - } else { - /* TODO: This controls the tx_power of UE and the ramping procedure of RA of UE. Later we - can abstract this, perhaps in the proxy. But for the time being lets leave it as below. */ - int16_t dl_pathloss = !get_softmodem_params()->emulate_l1 ? compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm) : 0; - ssb_rach_config(ra, prach_resources, nr_rach_ConfigCommon); - ra_preambles_config(prach_resources, mac, dl_pathloss); - LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", ra->ra_PreambleIndex); - } - if (prach_resources->preamble_tx_counter > 1) prach_resources->preamble_power_ramping_cnt++; - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources); } // TbD: RA_attempt_number not used @@ -790,6 +882,10 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, bool init_success = init_RA(mac, frame); if (!init_success) return; + else { + // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a) + ra_resource_selection(mac); + } } LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); @@ -824,7 +920,7 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, // Fill in preamble and PRACH resources ra->RA_window_cnt--; if (ra->ra_state == nrRA_GENERATE_PREAMBLE) { - nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mac, prach_resources, rach_ConfigDedicated); } } else if (ra->RA_backoff_cnt > 0) { @@ -833,7 +929,7 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, ra->RA_backoff_cnt--; if ((ra->RA_backoff_cnt > 0 && ra->ra_state == nrRA_GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) { - nr_get_prach_resources(mac, CC_id, gNB_id, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mac, prach_resources, rach_ConfigDedicated); } } } @@ -1016,10 +1112,9 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr seed = 1; } else { // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int) - seed = (unsigned int) (rdtsc_oai() & ~0); + seed = (unsigned int)(rdtsc_oai() & ~0); } - ra->first_Msg3 = true; ra->ra_PreambleIndex = -1; ra->ra_state = nrRA_UE_IDLE; @@ -1041,7 +1136,7 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->preamble_backoff + 1); prach_resources->preamble_tx_counter = 1; prach_resources->preamble_power_ramping_step += 2; // 2 dB increment - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); + prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources); } else { nr_get_RA_window(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 0872787bd5..1bfdc034ee 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2706,7 +2706,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t } } // if format1 - nr_get_prach_resources(mac, 0, 0, &ra->prach_resources, ra->rach_ConfigDedicated); pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex; pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac); unsigned int slot_RA; diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index 914d0ef984..6e8916f6f0 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -88,6 +88,7 @@ TEST(test_init_ra, four_step_cbra) NR_UE_DL_BWP_t dl_bwp; mac.current_UL_BWP = ¤t_bwp; mac.current_DL_BWP = &dl_bwp; + mac.mib_ssb = 0; long scs = 1; current_bwp.scs = scs; current_bwp.bwp_id = 0; @@ -122,6 +123,7 @@ TEST(test_init_ra, four_step_cfra) NR_UE_DL_BWP_t dl_bwp; mac.current_UL_BWP = ¤t_bwp; mac.current_DL_BWP = &dl_bwp; + mac.mib_ssb = 0; long scs = 1; current_bwp.scs = scs; current_bwp.bwp_id = 0; @@ -138,7 +140,7 @@ TEST(test_init_ra, four_step_cfra) int frame = 151; NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0}; - struct NR_CFRA cfra; + NR_CFRA_t cfra; rach_ConfigDedicated.cfra = &cfra; ra->rach_ConfigDedicated = &rach_ConfigDedicated; diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index f6dead1213..a6c2ae1c9c 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -3819,11 +3819,7 @@ NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t u uplink->ra_Prioritization = NULL; uplink->cfra = calloc(1, sizeof(struct NR_CFRA)); uplink->cfra->ext1 = NULL; - uplink->cfra->occasions = calloc(1, sizeof(struct NR_CFRA__occasions)); - memcpy(&uplink->cfra->occasions->rach_ConfigGeneric, - &scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric, - sizeof(NR_RACH_ConfigGeneric_t)); - asn1cCallocOne(uplink->cfra->occasions->ssb_perRACH_Occasion, NR_CFRA__occasions__ssb_perRACH_Occasion_one); + uplink->cfra->occasions = NULL; uplink->cfra->resources.present = NR_CFRA__resources_PR_ssb; uplink->cfra->resources.choice.ssb = calloc(1, sizeof(struct NR_CFRA__resources__ssb)); uplink->cfra->resources.choice.ssb->ra_ssb_OccasionMaskIndex = 0; From a7e3e8a3120190e011b1c96337785ab42cf8c26a Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 24 Oct 2024 09:26:22 +0200 Subject: [PATCH 11/34] harmonization of functions to get info from PRACH config tables --- openair1/SIMULATION/NR_PHY/prachsim.c | 41 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 377 ++++++------------ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 51 ++- openair2/LAYER2/NR_MAC_UE/config_ue.c | 6 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 63 +-- openair2/LAYER2/NR_MAC_gNB/config.c | 3 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 120 ++---- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + 8 files changed, 227 insertions(+), 435 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index ce00f6ae9e..eb3537650b 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -136,13 +136,11 @@ int main(int argc, char **argv){ c16_t **txdata; int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0; uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0; - uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; - uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1; + uint8_t config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0; + uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format0, format1; uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB; uint64_t SSB_positions = 0x01; uint16_t RA_sfn_index; - uint8_t N_RA_slot; - uint8_t config_period; int prachOccasion = 0; double DS_TDL = .03; @@ -482,25 +480,24 @@ int main(int argc, char **argv){ gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions; gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t)); - gNB->proc.slot_rx = slot; + gNB->proc.slot_rx = slot; + frequency_range_t freq_range = absoluteFrequencyPointA > 2016666 ? FR2 : FR1; + nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, freq_range, frame_parms->frame_type); + int ret = get_nr_prach_sched_from_info(prach_info, + config_index, + frame, + slot, + mu, + freq_range, + &RA_sfn_index, + frame_parms->frame_type); - int ret = get_nr_prach_info_from_index(config_index, - (int)frame, - (int)slot, - absoluteFrequencyPointA, - mu, - frame_parms->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period); - - if (ret == 0) {printf("No prach in %d.%d, mu %d, config_index %d\n",frame,slot,mu,config_index); exit(-1);} - format0 = format&0xff; // first column of format from table - format1 = (format>>8)&0xff; // second column of format from table + if (ret == 0) { + printf("No prach in %d.%d, mu %d, config_index %d\n", frame, slot, mu, config_index); + exit(-1); + } + format0 = prach_info.format & 0xff; // first column of format from table + format1 = (prach_info.format >> 8) & 0xff; // second column of format from table if (format1 != 0xff) { switch(format0) { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 29c5e2bfa1..fd3fb5e8e4 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1417,11 +1417,9 @@ static const int64_t table_6_3_3_2_4_prachConfig_Index[256][10] = { {0xa3, 0xb3, 1, 0, -1, 733007751850, 2, 1, 2, 6} // (subframe number :1,3,5,7,…,37,39) }; -int get_format0(uint8_t index, - uint8_t unpaired, - frequency_range_t frequency_range){ - - uint16_t format=0; +int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range) +{ + int format = 0; if (unpaired) { if (frequency_range==FR1) format = table_6_3_3_2_3_prachConfig_Index[index][0]; @@ -1437,23 +1435,6 @@ int get_format0(uint8_t index, return format; } -const int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired) -{ - const int64_t *prach_config_info_p; - - if (freq_range == FR2) { //FR2 - prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index]; - } - else { // FR1 - if (unpaired) - prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index]; - else - prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index]; - } // FR2 / FR1 - - return prach_config_info_p; -} - void find_aggregation_candidates(uint8_t *aggregation_level, uint8_t *nr_of_candidates, const NR_SearchSpace_t *ss, @@ -1566,97 +1547,81 @@ void set_monitoring_periodicity_offset(NR_SearchSpace_t *ss, } -int get_nr_prach_occasion_info_from_index(uint8_t index, - uint32_t pointa, - uint8_t mu, - uint8_t unpaired, - uint16_t *format, - uint8_t *start_symbol, - uint8_t *N_t_slot, - uint8_t *N_dur, - uint8_t *N_RA_slot, - uint16_t *N_RA_sfn, - uint8_t *max_association_period) +nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired) { - int x; - uint64_t s_map; uint8_t format2 = 0xff; - if (pointa > 2016666) { //FR2 - x = table_6_3_3_2_4_prachConfig_Index[index][2]; - s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; - *N_RA_sfn += count_bits64(s_map); - *N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe - *max_association_period = 160/(x * 10); - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6];//multiple prach occasions in diff slot - *N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; - *N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; - if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; - - *format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n", - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur, - *N_RA_sfn); - } - return 1; - } - else { - if (unpaired) { - x = table_6_3_3_2_3_prachConfig_Index[index][2]; - s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; - *N_RA_sfn += count_bits64(s_map); - *N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe - *max_association_period = 160/(x * 10); - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; - *N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; - *N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; - if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(NR_MAC,"Getting Total PRACH info from index %d (col %lu ) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n", - index, table_6_3_3_2_3_prachConfig_Index[index][6], - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur, - *N_RA_sfn); - } - return 1; - } - else { // FDD - x = table_6_3_3_2_2_prachConfig_Index[index][2]; - s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; - *N_RA_sfn += count_bits64(s_map); - *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; - *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; - *N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; - if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Getting Total PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); - } - return 1; - } + nr_prach_info_t info; + if (freq_range == FR2) { + info.x = table_6_3_3_2_4_prachConfig_Index[index][2]; + info.y = table_6_3_3_2_4_prachConfig_Index[index][3]; + info.y2 = table_6_3_3_2_4_prachConfig_Index[index][4]; + info.s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; + info.N_RA_sfn += count_bits64(info.s_map); + info.N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; + info.max_association_period = 160 / (info.x * 10); + info.start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6]; + info.N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; + info.N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; + if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) + format2 = (uint8_t)table_6_3_3_2_4_prachConfig_Index[index][1]; + info.format = ((uint8_t)table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2 << 8); + LOG_D(NR_MAC, + "PRACH info from index %d frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n", + index, + unpaired, + info.start_symbol, + info.N_t_slot, + info.N_dur, + info.N_RA_sfn); + return info; } + + if (unpaired) { // FR1 TDD + info.x = table_6_3_3_2_3_prachConfig_Index[index][2]; + info.y = table_6_3_3_2_3_prachConfig_Index[index][3]; + info.s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; + info.N_RA_sfn += count_bits64(info.s_map); + info.N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; + info.max_association_period = 160 / (info.x * 10); + info.start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; + info.N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; + info.N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; + if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) + format2 = (uint8_t)table_6_3_3_2_3_prachConfig_Index[index][1]; + info.format = ((uint8_t)table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2 << 8); + LOG_D(NR_MAC, + "PRACH info from index %d (col %lu) frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_sfn = %u\n", + index, + table_6_3_3_2_3_prachConfig_Index[index][6], + unpaired, + info.start_symbol, + info.N_t_slot, + info.N_dur, + info.N_RA_sfn); + return info; + } + + // FR1 FDD + info.x = table_6_3_3_2_2_prachConfig_Index[index][2]; + info.y = table_6_3_3_2_2_prachConfig_Index[index][3]; + info.s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; + info.N_RA_sfn += count_bits64(info.s_map); + info.N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; + info.max_association_period = 160 / (info.x * 10); + info.start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; + info.N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; + info.N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; + if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) + format2 = (uint8_t)table_6_3_3_2_2_prachConfig_Index[index][1]; + info.format = ((uint8_t)table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2 << 8); + LOG_D(NR_MAC, + "PRACH info from index %d frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", + index, + unpaired, + info.start_symbol, + info.N_t_slot, + info.N_dur); + return info; } uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired) @@ -1681,177 +1646,83 @@ uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t return format; } -int get_nr_prach_info_from_index(uint8_t index, - int frame, - int slot, - uint32_t pointa, - uint8_t mu, - uint8_t unpaired, - uint16_t *format, - uint8_t *start_symbol, - uint8_t *N_t_slot, - uint8_t *N_dur, - uint16_t *RA_sfn_index, - uint8_t *N_RA_slot, - uint8_t *config_period) +bool get_nr_prach_sched_from_info(nr_prach_info_t info, + int config_index, + int frame, + int slot, + int mu, + frequency_range_t freq_range, + uint16_t *RA_sfn_index, + uint8_t unpaired) { - int x,y; - int64_t s_map; - uint8_t format2 = 0xff; - - if (pointa > 2016666) { //FR2 - int y2; - uint8_t slot_60khz; - x = table_6_3_3_2_4_prachConfig_Index[index][2]; - y = table_6_3_3_2_4_prachConfig_Index[index][3]; - y2 = table_6_3_3_2_4_prachConfig_Index[index][4]; + if (freq_range == FR2) { // checking n_sfn mod x = y - if ((frame % x) == y || (frame % x) == y2) { - slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz - s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; - if ((s_map >> slot_60khz) & 0x01) { + if ((frame % info.x) == info.y || (frame % info.x) == info.y2) { + int slot_60khz = slot >> (mu - 2); // in table slots are numbered wrt 60kHz + if ((info.s_map >> slot_60khz) & 0x01) { for(int i = 0; i <= slot_60khz ;i++) { - if ((s_map >> i) & 0x01) { + if ((info.s_map >> i) & 0x01) { (*RA_sfn_index)++; } } } - if (((s_map >> slot_60khz) & 0x01)) { - *N_RA_slot = table_6_3_3_2_4_prachConfig_Index[index][7]; // Number of RACH slots within a subframe + if (((info.s_map >> slot_60khz) & 0x01)) { if (mu == 3) { - if ((*N_RA_slot == 1) && (slot % 2 == 0) ) - return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot + if ((info.N_RA_slot == 1) && (slot % 2 == 0)) + return false; // no prach in even slots @ 120kHz for 1 prach per 60khz slot } - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *config_period = x; - *start_symbol = table_6_3_3_2_4_prachConfig_Index[index][6]; - *N_t_slot = table_6_3_3_2_4_prachConfig_Index[index][8]; - *N_dur = table_6_3_3_2_4_prachConfig_Index[index][9]; - if (table_6_3_3_2_4_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_4_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_4_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u\n", - frame, - slot, - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur, - *N_RA_slot, - *RA_sfn_index); - } - return 1; - } - else - return 0; // no prach in current slot + return true; + } else + return false; // no prach in current slot } else - return 0; // no prach in current frame - } - else { - uint8_t subframe; - if (unpaired) { - x = table_6_3_3_2_3_prachConfig_Index[index][2]; - y = table_6_3_3_2_3_prachConfig_Index[index][3]; - if ((frame % x) == y) { - subframe = slot >> mu; - s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; - if ((s_map >> subframe) & 0x01) { + return false; // no prach in current frame + } else { + if (unpaired) { // TDD + if ((frame % info.x) == info.y) { + int subframe = slot >> mu; + if ((info.s_map >> subframe) & 0x01) { for(int i = 0; i <= subframe ;i++) { - if ((s_map >> i) & 0x01) { + if ((info.s_map >> i) & 0x01) { (*RA_sfn_index)++; } } } - if ((s_map >> subframe) & 0x01 ) { - *N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; // Number of RACH slots within a subframe - if (index >= 67) { - if ((mu == 1) && (*N_RA_slot <= 1) && (slot % 2 == 0)) - return 0; // no prach in even slots @ 30kHz for 1 prach per subframe + if ((info.s_map >> subframe) & 0x01) { + if (config_index >= 67) { + if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0)) + return false; // no prach in even slots @ 30kHz for 1 prach per subframe } else { if ((slot % 2) && (mu > 0)) - return 0; // slot does not contain start symbol of this prach time resource + return false; // slot does not contain start symbol of this prach time resource } - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL) { - *config_period = x; - *start_symbol = table_6_3_3_2_3_prachConfig_Index[index][5]; - *N_t_slot = table_6_3_3_2_3_prachConfig_Index[index][7]; - *N_dur = table_6_3_3_2_3_prachConfig_Index[index][8]; - if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %lu) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u N_RA_slot %u RA_sfn_index %u \n", - frame, - slot, - index, - table_6_3_3_2_3_prachConfig_Index[index][6], - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur, - *N_RA_slot, - *RA_sfn_index); - } - return 1; - } - else - return 0; // no prach in current slot - } - else - return 0; // no prach in current frame - } - else { // FDD - x = table_6_3_3_2_2_prachConfig_Index[index][2]; - y = table_6_3_3_2_2_prachConfig_Index[index][3]; - if ((frame % x) == y) { - subframe = slot >> mu; - s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; - if ((s_map>>subframe) & 0x01) { - *N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; // Number of RACH slots within a subframe - if (index >= 87) { - if ((mu == 1) && (*N_RA_slot <= 1) && (slot % 2 == 0)) { - return 0; // no prach in even slots @ 30kHz for 1 prach per subframe + return true; + } else + return false; // no prach in current slot + } else + return false; // no prach in current frame + } else { // FDD + if ((frame % info.x) == info.y) { + int subframe = slot >> mu; + if ((info.s_map >> subframe) & 0x01) { + if (config_index >= 87) { + if ((mu == 1) && (info.N_RA_slot <= 1) && (slot % 2 == 0)) { + return false; // no prach in even slots @ 30kHz for 1 prach per subframe } } else { if ((slot % 2) && (mu > 0)) return 0; // slot does not contain start symbol of this prach time resource } for(int i = 0; i <= subframe ; i++) { - if ((s_map >> i) & 0x01) { + if ((info.s_map >> i) & 0x01) { (*RA_sfn_index)++; } } - if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ - *start_symbol = table_6_3_3_2_2_prachConfig_Index[index][5]; - *config_period = x; - *N_t_slot = table_6_3_3_2_2_prachConfig_Index[index][7]; - *N_dur = table_6_3_3_2_2_prachConfig_Index[index][8]; - if (table_6_3_3_2_2_prachConfig_Index[index][1] != -1) - format2 = (uint8_t) table_6_3_3_2_2_prachConfig_Index[index][1]; - *format = ((uint8_t) table_6_3_3_2_2_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", - frame, - slot, - index, - pointa, - mu, - unpaired, - *start_symbol, - *N_t_slot, - *N_dur); - } - return 1; - } - else - return 0; // no prach in current slot - } - else - return 0; // no prach in current frame + return true; + } else + return false; // no prach in current slot + } else + return false; // no prach in current frame } } } diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index e5f7fb4fcf..b8d1fae38c 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -52,6 +52,20 @@ typedef enum { pusch_len2 = 2 } pusch_maxLength_t; +typedef struct { + uint32_t format; + uint32_t start_symbol; + uint32_t N_t_slot; + uint32_t N_dur; + uint32_t N_RA_slot; + uint32_t N_RA_sfn; + uint32_t max_association_period; + int x; + int y; + int y2; + uint64_t s_map; +} nr_prach_info_t; + uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti); uint8_t get_BG(uint32_t A, uint16_t R); @@ -144,31 +158,16 @@ void find_aggregation_candidates(uint8_t *aggregation_level, uint16_t get_nr_prach_format_from_index(uint8_t index, uint32_t pointa, uint8_t unpaired); -int get_nr_prach_info_from_index(uint8_t index, - int frame, - int slot, - uint32_t pointa, - uint8_t mu, - uint8_t unpaired, - uint16_t *format, - uint8_t *start_symbol, - uint8_t *N_t_slot, - uint8_t *N_dur, - uint16_t *RA_sfn_index, - uint8_t *N_RA_slot, - uint8_t *config_period); +bool get_nr_prach_sched_from_info(nr_prach_info_t info, + int config_index, + int frame, + int slot, + int mu, + frequency_range_t freq_range, + uint16_t *RA_sfn_index, + uint8_t unpaired); -int get_nr_prach_occasion_info_from_index(uint8_t index, - uint32_t pointa, - uint8_t mu, - uint8_t unpaired, - uint16_t *format, - uint8_t *start_symbol, - uint8_t *N_t_slot, - uint8_t *N_dur, - uint8_t *N_RA_slot, - uint16_t *N_RA_sfn, - uint8_t *max_association_period); +nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_range_t freq_range, uint8_t unpaired); uint8_t get_pusch_mcs_table(long *mcs_Table, int is_tp, @@ -186,9 +185,7 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrec uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type); -int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t); - -const int64_t *get_prach_config_info(frequency_range_t freq_range, uint8_t index, uint8_t unpaired); +int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_range); uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); int compute_pucch_crc_size(int O_uci); diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 552f0676f6..cd266d8a1d 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -187,8 +187,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo else { // If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839) int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, frame_type); - int format = prach_config_info_p[0]; + int format = get_format0(config_index, frame_type, mac->frequency_range); cfg->prach_config.prach_sub_c_spacing = get_delta_f_RA_long(format); } @@ -411,8 +410,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t else { // If absent, the UE applies the SCS as derived from the prach-ConfigurationIndex (for 839) int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, frame_type); - int format = prach_config_info_p[0]; + int format = get_format0(config_index, frame_type, mac->frequency_range); cfg->prach_config.prach_sub_c_spacing = format == 3 ? 5 : 4; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 1bfdc034ee..ef6c902416 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1564,17 +1564,10 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config static void build_ro_list(NR_UE_MAC_INST_t *mac) { - int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers uint8_t slot_shift_for_map; uint8_t map_shift; bool even_slot_invalid; - int64_t s_map; - uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot - uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot - uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols) - uint16_t format = 0xffff; - uint8_t format2 = 0xff; int nb_fdm; uint8_t config_index; @@ -1604,61 +1597,35 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type; - const int64_t *prach_config_info_p = get_prach_config_info(mac->frequency_range, config_index, unpaired); const int ul_mu = mac->current_UL_BWP->scs; const int mu = nr_get_prach_or_ul_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, setup, ul_mu); + nr_prach_info_t prach_config = get_nr_prach_occasion_info_from_index(config_index, mac->frequency_range, unpaired); // Identify the proper PRACH Configuration Index table according to the operating frequency LOG_D(NR_MAC,"mu = %u, PRACH config index = %u, unpaired = %u\n", mu, config_index, unpaired); if (mac->frequency_range == FR2) { //FR2 - - x = prach_config_info_p[2]; - y = prach_config_info_p[3]; - y2 = prach_config_info_p[4]; - - s_map = prach_config_info_p[5]; - - prach_conf_start_symbol = prach_config_info_p[6]; - N_t_slot = prach_config_info_p[8]; - N_dur = prach_config_info_p[9]; - if (prach_config_info_p[1] != -1) - format2 = (uint8_t) prach_config_info_p[1]; - format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); - + y2 = prach_config.y2; slot_shift_for_map = mu-2; - if ( (mu == 3) && (prach_config_info_p[7] == 1) ) + if ((mu == 3) && (prach_config.N_RA_slot == 1)) even_slot_invalid = true; else even_slot_invalid = false; } else { // FR1 - x = prach_config_info_p[2]; - y = prach_config_info_p[3]; - y2 = y; - - s_map = prach_config_info_p[4]; - - prach_conf_start_symbol = prach_config_info_p[5]; - N_t_slot = prach_config_info_p[7]; - N_dur = prach_config_info_p[8]; - LOG_D(NR_MAC,"N_t_slot %d, N_dur %d\n",N_t_slot,N_dur); - if (prach_config_info_p[1] != -1) - format2 = (uint8_t) prach_config_info_p[1]; - format = ((uint8_t) prach_config_info_p[0]) | (format2<<8); - + y2 = prach_config.y; slot_shift_for_map = mu; - if ( (mu == 1) && (prach_config_info_p[6] == 1) && ((format & 0xff) > 3) ) + if ((mu == 1) && (prach_config.N_RA_slot == 1) && ((prach_config.format & 0xff) > 3)) // no prach in even slots @ 30kHz for 1 prach per subframe even_slot_invalid = true; else even_slot_invalid = false; - } // FR2 / FR1 + } // FR1 const int bwp_id = mac->current_UL_BWP->bwp_id; prach_association_pattern_t *prach_assoc_pattern = &mac->prach_assoc_pattern[bwp_id]; - prach_assoc_pattern->nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x; - nb_of_frames_per_prach_conf_period = x; + prach_assoc_pattern->nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / prach_config.x; + nb_of_frames_per_prach_conf_period = prach_config.x; int slots_per_frame = mac->frame_structure.numb_slots_frame; LOG_D(NR_MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern->nb_of_prach_conf_period_in_max_period); @@ -1682,14 +1649,14 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) LOG_D(NR_MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", frame_idx, frame_rach); // Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y) - if ((frame_rach % x) == y || (frame_rach % x) == y2) { + if ((frame_rach % prach_config.x) == prach_config.y || (frame_rach % prach_config.x) == y2) { // For every slot in a frame // ------------------------- for (int slot = 0; slot < slots_per_frame; slot++) { // Is it a valid slot? map_shift = slot >> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz - if ((s_map>>map_shift) & 0x01) { + if ((prach_config.s_map >> map_shift) & 0x01) { // Valid slot // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also @@ -1700,12 +1667,12 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) // Compute all the PRACH occasions in the slot prach_occasion_slot_t *slot_map = &prach_conf_period_list->prach_occasion_slot_map[frame_idx][slot]; - slot_map->nb_of_prach_occasion_in_time = N_t_slot; + slot_map->nb_of_prach_occasion_in_time = prach_config.N_t_slot; slot_map->nb_of_prach_occasion_in_freq = nb_fdm; - slot_map->prach_occasion = malloc(N_t_slot * nb_fdm * sizeof(*slot_map->prach_occasion)); + slot_map->prach_occasion = malloc(prach_config.N_t_slot * nb_fdm * sizeof(*slot_map->prach_occasion)); AssertFatal(slot_map->prach_occasion, "no memory available\n"); - for (int n_prach_occ_in_time = 0; n_prach_occ_in_time < N_t_slot; n_prach_occ_in_time++) { - uint8_t start_symbol = prach_conf_start_symbol + n_prach_occ_in_time * N_dur; + for (int n_prach_occ_in_time = 0; n_prach_occ_in_time < prach_config.N_t_slot; n_prach_occ_in_time++) { + uint8_t start_symbol = prach_config.start_symbol + n_prach_occ_in_time * prach_config.N_dur; LOG_D(NR_MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time); for (int n_prach_occ_in_freq = 0; n_prach_occ_in_freq < nb_fdm; n_prach_occ_in_freq++) { @@ -1714,7 +1681,7 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) .fdm = n_prach_occ_in_freq, .frame = frame_idx, .slot = slot, - .format = format}; + .format = prach_config.format}; prach_assoc_pattern->prach_conf_period_list[period_idx].nb_of_prach_occasion++; LOG_D(NR_MAC, diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index d7b9b5e129..0abe35b80d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -521,8 +521,7 @@ static void config_common(gNB_MAC_INST *nrmac, // If absent, use SCS as derived from the prach-ConfigurationIndex (for 839) int config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; int frame_type = get_frame_type(band, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing); - const int64_t *prach_config_info_p = get_prach_config_info(frequency_range, config_index, frame_type); - int format = prach_config_info_p[0]; + int format = get_nr_prach_format_from_index(config_index, UL_pointA, frame_type) & 0xff; cfg->prach_config.prach_sub_c_spacing.value = get_delta_f_RA_long(format); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index cc0317cf51..9044927f34 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -83,9 +83,8 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; uint16_t start_symbol_index = 0; - uint8_t N_dur=0,N_t_slot=0,start_symbol = 0, temp_start_symbol = 0, N_RA_slot=0; - uint16_t format,RA_sfn_index = -1; - uint8_t config_period = 1; + uint8_t temp_start_symbol = 0; + uint16_t RA_sfn_index = -1; uint16_t prach_occasion_id = -1; uint8_t num_active_ssb = cc->num_active_ssb; NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; @@ -93,42 +92,32 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu); + frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1; + get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type); - get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period); uint8_t index = 0, slot_index = 0; - for (slot_index = 0; slot_index < N_RA_slot; slot_index++) { - if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + for (slot_index = 0; slot_index < cc->prach_info.N_RA_slot; slot_index++) { + if (cc->prach_info.N_RA_slot <= 1) { // 1 PRACH slot in a subframe if((mu == 1) || (mu == 3)) - slot_index = 1; //For scs = 30khz and 120khz + slot_index = 1; // For scs = 30khz and 120khz } - for (int i = 0; i < N_t_slot; i++) { - temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14; + for (int i = 0; i < cc->prach_info.N_t_slot; i++) { + temp_start_symbol = (cc->prach_info.start_symbol + i * cc->prach_info.N_dur + 14 * slot_index) % 14; if(symbol == temp_start_symbol) { start_symbol_index = i; break; } } } - if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + if (cc->prach_info.N_RA_slot <= 1) { // 1 PRACH slot in a subframe if((mu == 1) || (mu == 3)) - slot_index = 0; //For scs = 30khz and 120khz + slot_index = 0; // For scs = 30khz and 120khz } - + int config_period = cc->prach_info.x; // prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; - prach_occasion_id = (((frameP % (cc->max_association_period * config_period)) / config_period) * cc->total_prach_occasions_per_config_period) + - (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; + prach_occasion_id = + (((frameP % (cc->max_association_period * config_period)) / config_period) * cc->total_prach_occasions_per_config_period) + + (RA_sfn_index + slot_index) * cc->prach_info.N_t_slot * fdm + start_symbol_index * fdm + freq_index; //one SSB have more than one continuous RO if(num_ssb_per_RO <= 1) @@ -159,14 +148,12 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; uint8_t config_index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - uint8_t N_dur=0,N_t_slot=0,start_symbol=0,N_RA_slot = 0; - uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0; + uint16_t unused_RA_occasion, repetition = 0; uint8_t num_active_ssb = 0; - uint8_t max_association_period = 1; struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *ssb_perRACH_OccasionAndCB_PreamblesPerSSB = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB; - switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present){ + switch (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present) { case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: cc->cb_preambles_per_ssb = 4 * (ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1); break; @@ -194,31 +181,16 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) default: AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present); break; - } - - 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; - const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu); + } // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 - get_nr_prach_occasion_info_from_index(config_index, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &N_RA_slot, - &N_RA_sfn, - &max_association_period); + frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1; + nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(config_index, freq_range, cc->frame_type); float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value]; uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value; uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value) << 32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value; - uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm; + uint32_t total_RA_occasions = prach_info.N_RA_sfn * prach_info.N_t_slot * prach_info.N_RA_slot * fdm; for(int i = 0; i < 64; i++) { if ((L_ssb >> (63 - i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1 @@ -228,7 +200,7 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) } cc->total_prach_occasions_per_config_period = total_RA_occasions; - for(int i = 1; (1 << (i-1)) <= max_association_period; i++) { + for (int i = 1; (1 << (i - 1)) <= prach_info.max_association_period; i++) { cc->max_association_period = (1 << (i - 1)); total_RA_occasions = total_RA_occasions * cc->max_association_period; if(total_RA_occasions >= (int) (num_active_ssb / num_ssb_per_RO)) { @@ -240,14 +212,16 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition) / num_ssb_per_RO); cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion; cc->num_active_ssb = num_active_ssb; + cc->prach_info = prach_info; LOG_D(NR_MAC, - "Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u total_prach_occasions_per_config_period %u\n", + "Total available RO %d, num of active SSB %d: unused RO = %d association_period %u N_RA_sfn %u " + "total_prach_occasions_per_config_period %u\n", cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, cc->max_association_period, - N_RA_sfn, + prach_info.N_RA_sfn, cc->total_prach_occasions_per_config_period); } @@ -396,10 +370,6 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) { const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot; - uint16_t RA_sfn_index = -1; - uint8_t config_period = 1; - uint16_t format; int slot_index = 0; uint16_t prach_occasion_id = -1; @@ -409,29 +379,18 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu); // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4 - if (get_nr_prach_info_from_index(config_index, - (int)frameP, - (int)slotP, - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, - mu, - cc->frame_type, - &format, - &start_symbol, - &N_t_slot, - &N_dur, - &RA_sfn_index, - &N_RA_slot, - &config_period)) { + uint16_t RA_sfn_index = -1; + frequency_range_t freq_range = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666 ? FR2 : FR1; + if (get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type)) { + uint16_t format0 = cc->prach_info.format & 0xff; // first column of format from table + uint16_t format1 = (cc->prach_info.format >> 8) & 0xff; // second column of format from table - uint16_t format0 = format & 0xff; // first column of format from table - uint16_t format1 = (format >> 8) & 0xff; // second column of format from table - - if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe + if (cc->prach_info.N_RA_slot > 1) { // more than 1 PRACH slot in a subframe if (slotP % 2 == 1) slot_index = 1; else slot_index = 0; - } else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe + } else if (cc->prach_info.N_RA_slot <= 1) { // 1 PRACH slot in a subframe slot_index = 0; } @@ -439,9 +398,11 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) UL_tti_req->Slot = slotP; UL_tti_req->rach_present = 1; NR_beam_alloc_t beam = {0}; + uint32_t N_t_slot = cc->prach_info.N_t_slot; + uint32_t start_symb = cc->prach_info.start_symbol; for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion for (int td_index = 0; td_index < N_t_slot; td_index++) { - + uint32_t config_period = cc->prach_info.x; prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index; @@ -482,7 +443,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) // filling the prach fapi structure prach_pdu->phys_cell_id = *scc->physCellId; prach_pdu->num_prach_ocas = N_t_slot; - prach_pdu->prach_start_symbol = start_symbol; + prach_pdu->prach_start_symbol = start_symb; prach_pdu->num_ra = fdm_index; prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, @@ -499,7 +460,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) slotP, prach_occasion_id, prach_pdu->num_ra, - prach_pdu->prach_start_symbol, + start_symb, slot_index, RA_sfn_index); // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities @@ -579,13 +540,14 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch); // mark PRBs as occupied for current and future slots if prach extends beyond current slot int total_prach_slots; + uint32_t N_dur = cc->prach_info.N_dur; if (format0 < 4) { N_dur = 14; // number of PRACH symbols in PRACH slot total_prach_slots = get_long_prach_dur(format0, mu_pusch); AssertFatal(slotP + total_prach_slots - 1 < slots_frame, "PRACH cannot extend across frames\n"); } else { // TODO: to be revisited for format B4 (also extends beyond current slot for FR1 30kHz SCS and FR2) - AssertFatal((format != 0xb4) || (mu_pusch < 1), "Format B4 not supported for this PUSCH SCS\n"); + AssertFatal((format0 != 0xb4) || (mu_pusch < 1), "Format B4 not supported for this PUSCH SCS\n"); total_prach_slots = 1; } // reserve PRBs occupied by PRACH in all PRACH slot. @@ -597,7 +559,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) gNB->vrb_map_UL_size, slots_frame, bwp_start + rach_ConfigGeneric->msg1_FrequencyStart, - start_symbol, + start_symb, N_t_slot * N_dur, cc); } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3f992f0409..8b1bb3ec5c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -302,6 +302,7 @@ typedef struct { int cb_preambles_per_ssb; /// Max prach length in slots int prach_len; + nr_prach_info_t prach_info; } NR_COMMON_channels_t; // SP ZP CSI-RS Resource Set Activation/Deactivation MAC CE From 220af3f66945dd088685533e516344e87e3355d8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 24 Oct 2024 10:34:06 +0200 Subject: [PATCH 12/34] move function to build ssb list after common configuration (reception of SSB information) also removed unnecessary BWP dependence --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 40 ++++++++++++++++--- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 5 +-- .../NR_MAC_UE/nr_ue_dci_configuration.c | 4 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 32 ++------------- 6 files changed, 43 insertions(+), 43 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index cd266d8a1d..44e01d4d04 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -44,6 +44,28 @@ #include "oai_asn1.h" #include "executables/position_interface.h" +// Build the list of all the valid/transmitted SSBs according to the config +static void build_ssb_list(NR_UE_MAC_INST_t *mac) +{ + // Create the list of transmitted SSBs + free(mac->ssb_list.tx_ssb); + memset(&mac->ssb_list, 0, sizeof(ssb_list_info_t)); + ssb_list_info_t *ssb_list = &mac->ssb_list; + fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; + ssb_list->nb_tx_ssb = 0; + + for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) { + uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index / 32].ssb_mask; + // check if if current SSB is transmitted + if ((curr_mask >> (31 - (ssb_index % 32))) & 0x01) { + ssb_list->nb_ssb_per_index[ssb_index] = ssb_list->nb_tx_ssb; + ssb_list->nb_tx_ssb++; + } else + ssb_list->nb_ssb_per_index[ssb_index] = -1; + } + ssb_list->tx_ssb = calloc(ssb_list->nb_tx_ssb, sizeof(*ssb_list->tx_ssb)); +} + static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_structure_t *fs) { tdd_table->tdd_period_in_slots = fs->numb_slots_period; @@ -1744,14 +1766,16 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); config_common_ue_sa(mac, scc, cc_idP); - configure_common_BWP_dl(mac, - 0, // bwp-id - &scc->downlinkConfigCommon.initialDownlinkBWP); + + // Build the list of all the valid/transmitted SSBs according to the config + LOG_D(NR_MAC, "Build SSB list\n"); + build_ssb_list(mac); + + int bwp_id = 0; + configure_common_BWP_dl(mac, bwp_id, &scc->downlinkConfigCommon.initialDownlinkBWP); if (scc->uplinkConfigCommon) { mac->timeAlignmentTimerCommon = scc->uplinkConfigCommon->timeAlignmentTimerCommon; - configure_common_BWP_ul(mac, - 0, // bwp-id - &scc->uplinkConfigCommon->initialUplinkBWP); + configure_common_BWP_ul(mac, bwp_id, &scc->uplinkConfigCommon->initialUplinkBWP); } // set current BWP only if coming from non-connected state // otherwise it is just a periodically update of the SIB1 content @@ -1816,6 +1840,10 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t); config_common_ue(mac, scc, cc_idP); + // Build the list of all the valid/transmitted SSBs according to the config + LOG_D(NR_MAC,"Build SSB list\n"); + build_ssb_list(mac); + const int bwp_id = 0; if (scc->downlinkConfigCommon) configure_common_BWP_dl(mac, bwp_id, scc->downlinkConfigCommon->initialDownlinkBWP); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 79fdb4c0d1..4a34fd3a5f 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -577,7 +577,7 @@ typedef struct NR_UE_MAC_INST_s { NR_MIB_t *mib; si_schedInfo_t si_SchedInfo; - ssb_list_info_t ssb_list[MAX_NUM_BWP_UE]; + ssb_list_info_t ssb_list; prach_association_pattern_t prach_assoc_pattern[MAX_NUM_BWP_UE]; NR_UE_ServingCell_Info_t sc_info; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 35167b6173..1b865a78eb 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -77,7 +77,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); - memset(mac->ssb_list, 0, sizeof(mac->ssb_list)); + memset(&mac->ssb_list, 0, sizeof(mac->ssb_list)); memset(mac->prach_assoc_pattern, 0, sizeof(mac->prach_assoc_pattern)); for (int i = 0; i < NR_MAX_SR_ID; i++) @@ -302,3 +302,4 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca for (int i = mac->TAG_list.count; i > 0 ; i--) asn_sequence_del(&mac->TAG_list, i - 1, 1); } + diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 229a977be2..903b740f10 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -346,8 +346,7 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) if (config_info.ssb_per_ro < 1) ra->ra_PreambleIndex = groupOffset + rand_preamb; else { - ssb_list_info_t *ssb_list = &mac->ssb_list[mac->current_DL_BWP->bwp_id]; - int ssb_pr_idx = ssb_list->nb_ssb_per_index[ra->ra_ssb] % (int)config_info.ssb_per_ro; + int ssb_pr_idx = mac->ssb_list.nb_ssb_per_index[ra->ra_ssb] % (int)config_info.ssb_per_ro; ra->ra_PreambleIndex = groupOffset + (ssb_pr_idx * config_info.preambles_per_ssb) + rand_preamb; } AssertFatal(ra->ra_PreambleIndex < nb_of_preambles, @@ -1190,8 +1189,6 @@ void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id) for (int k = 0; k < MAX_NB_FRAME_IN_PRACH_CONF_PERIOD; k++) for (int l = 0; l < MAX_NB_SLOT_IN_FRAME; l++) free(nr_mac->prach_assoc_pattern[bwp_id].prach_conf_period_list[j].prach_occasion_slot_map[k][l].prach_occasion); - - free(nr_mac->ssb_list[bwp_id].tx_ssb); } void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index aeeab40b74..b2fcab87c3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -442,8 +442,8 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac, get_monitoring_period_offset(ss, &period, &offset); for (int i = 0; i < duration; i++) { if (((frame * slots_per_frame + slot - offset - i) % period) == 0) { - int N = mac->ssb_list[bwp_id].nb_tx_ssb; - int K = mac->ssb_list->nb_ssb_per_index[mac->mib_ssb]; + int N = mac->ssb_list.nb_tx_ssb; + int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb]; // numbering current frame and slot in terms of monitoring occasions in window int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ef6c902416..b2e1edd19e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1703,28 +1703,6 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) } // For every prach configuration periods in the maximum association pattern period (160ms) } -// Build the list of all the valid/transmitted SSBs according to the config -static void build_ssb_list(NR_UE_MAC_INST_t *mac) -{ - // Create the list of transmitted SSBs - const int bwp_id = mac->current_UL_BWP->bwp_id; - ssb_list_info_t *ssb_list = &mac->ssb_list[bwp_id]; - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - ssb_list->nb_tx_ssb = 0; - - for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) { - uint32_t curr_mask = cfg->ssb_table.ssb_mask_list[ssb_index / 32].ssb_mask; - // check if if current SSB is transmitted - if ((curr_mask >> (31 - (ssb_index % 32))) & 0x01) { - ssb_list->nb_ssb_per_index[ssb_index] = ssb_list->nb_tx_ssb; - ssb_list->nb_tx_ssb++; - } - else - ssb_list->nb_ssb_per_index[ssb_index] = -1; - } - ssb_list->tx_ssb = calloc(ssb_list->nb_tx_ssb, sizeof(*ssb_list->tx_ssb)); -} - static int get_ssb_idx_from_list(ssb_list_info_t *ssb_list, int idx) { for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) { @@ -1758,7 +1736,7 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) LOG_D(NR_MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); const int bwp_id = mac->current_UL_BWP->bwp_id; - ssb_list_info_t *ssb_list = &mac->ssb_list[bwp_id]; + ssb_list_info_t *ssb_list = &mac->ssb_list; // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same @@ -2052,17 +2030,13 @@ void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) // Clear all the lists and maps const int bwp_id = mac->current_UL_BWP->bwp_id; free_rach_structures(mac, bwp_id); - memset(&mac->ssb_list[bwp_id], 0, sizeof(ssb_list_info_t)); + memset(&mac->prach_assoc_pattern[bwp_id], 0, sizeof(prach_association_pattern_t)); // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config LOG_D(NR_MAC,"Build RO list\n"); build_ro_list(mac); - // Build the list of all the valid/transmitted SSBs according to the config - LOG_D(NR_MAC,"Build SSB list\n"); - build_ssb_list(mac); - // Map the transmitted SSBs to the ROs and create the association pattern according to the config LOG_D(NR_MAC,"Map SSB to RO\n"); map_ssb_to_ro(mac); @@ -2575,7 +2549,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t selected_gnb_ssb_idx, (int)frameP, (int)slotP, - &mac->ssb_list[bwp_id], + &mac->ssb_list, &prach_occasion_info_p); if (is_nr_prach_slot) { From 8f1661c66ca45e38f22c9905e106e0dd9eb9f4b9 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 26 Nov 2024 11:50:09 +0100 Subject: [PATCH 13/34] PRACH occasion configuration --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 30 --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 + openair2/LAYER2/NR_MAC_UE/mac_defs.h | 40 +++- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 200 +++++++++++++++--- 4 files changed, 216 insertions(+), 56 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 143d4623d7..a83c85dd25 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -461,36 +461,6 @@ typedef struct { #define NR_MAX_NUM_LCGID 8 #define MAX_RLC_SDU_SUBHEADER_SIZE 3 -//=========== -// PRACH defs -//=========== - -// =============================================== -// SSB to RO mapping public defines and structures -// =============================================== -#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO -#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot -#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot - -// PRACH occasion details -typedef struct prach_occasion_info { - uint8_t start_symbol; // 0 - 13 (14 symbols in a slot) - uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) - uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz) - uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) - uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs - uint8_t nb_mapped_ssb; - uint16_t format; // RO preamble format -} prach_occasion_info_t; - -// PRACH occasion slot details -// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency -typedef struct prach_occasion_slot { - prach_occasion_info_t *prach_occasion; // Starting symbol of each PRACH occasions in a slot - uint8_t nb_of_prach_occasion_in_time; - uint8_t nb_of_prach_occasion_in_freq; -} prach_occasion_slot_t; - //========= // DCI defs //========= diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index fd3fb5e8e4..2da3d9df93 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1579,6 +1579,7 @@ nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_r if (unpaired) { // FR1 TDD info.x = table_6_3_3_2_3_prachConfig_Index[index][2]; info.y = table_6_3_3_2_3_prachConfig_Index[index][3]; + info.y2 = -1; info.s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; info.N_RA_sfn += count_bits64(info.s_map); info.N_RA_slot = table_6_3_3_2_3_prachConfig_Index[index][6]; @@ -1604,6 +1605,7 @@ nr_prach_info_t get_nr_prach_occasion_info_from_index(uint8_t index, frequency_r // FR1 FDD info.x = table_6_3_3_2_2_prachConfig_Index[index][2]; info.y = table_6_3_3_2_2_prachConfig_Index[index][3]; + info.y2 = -1; info.s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; info.N_RA_sfn += count_bits64(info.s_map); info.N_RA_slot = table_6_3_3_2_2_prachConfig_Index[index][6]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 4a34fd3a5f..4dc295acf3 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -169,6 +169,34 @@ UE_STATE(UE_CONNECTED) \ UE_STATE(UE_DETACHING) +// =============================================== +// SSB to RO mapping public defines and structures +// =============================================== +#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO +#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot +#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot + +// PRACH occasion details +typedef struct prach_occasion_info { + int start_symbol; // 0 - 13 (14 symbols in a slot) + int fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) + int slot; + int frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) + uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs + uint8_t nb_mapped_ssb; + int format; // RO preamble format + int frame_info[2]; + int association_period_idx; +} prach_occasion_info_t; + +// PRACH occasion slot details +// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency +typedef struct prach_occasion_slot { + prach_occasion_info_t *prach_occasion; // Starting symbol of each PRACH occasions in a slot + uint8_t nb_of_prach_occasion_in_time; + uint8_t nb_of_prach_occasion_in_freq; +} prach_occasion_slot_t; + typedef enum { phr_cause_prohibit_timer = 0, phr_cause_periodic_timer, @@ -292,6 +320,11 @@ typedef struct { int Pc_max; } NR_PRACH_RESOURCES_t; +typedef struct{ + float ssb_per_ro; + int preambles_per_ssb; +} ssb_ro_preambles_t; + typedef struct { bool active; uint32_t preamble_index; @@ -333,7 +366,7 @@ typedef struct { uint8_t ssb_nb_in_ro; int zeroCorrelationZoneConfig; int restricted_set_config; - // selected SSB for RACH + // selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs) int ra_ssb; /// Random-access window counter int16_t RA_window_cnt; @@ -368,6 +401,11 @@ typedef struct { NR_pdcch_order_config_t pdcch_order; NR_PRACH_RESOURCES_t prach_resources; + + ssb_ro_preambles_t ssb_ro_config; + int association_periods; + prach_occasion_info_t sched_ro_info; + int ro_mask_index; } RA_config_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 903b740f10..039788b62e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -191,25 +191,20 @@ static void select_preamble_group(NR_UE_MAC_INST_t *mac) // else if Msg3 is being retransmitted, we keep what used in first transmission of Msg3 } -typedef struct{ - float ssb_per_ro; - int preambles_per_ssb; -} ssb_ro_preambles_t; - static ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config) { ssb_ro_preambles_t ret = {0}; switch (config->present) { case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth: - ret.ssb_per_ro = 1 / 8; + ret.ssb_per_ro = 0.125; ret.preambles_per_ssb = (config->choice.oneEighth + 1) << 2; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth: - ret.ssb_per_ro = 1 / 4; + ret.ssb_per_ro = 0.25; ret.preambles_per_ssb = (config->choice.oneFourth + 1) << 2; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf: - ret.ssb_per_ro = 1 / 2; + ret.ssb_per_ro = 0.5; ret.preambles_per_ssb = (config->choice.oneHalf + 1) << 2; break; case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one: @@ -235,6 +230,7 @@ static ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon default: AssertFatal(false, "Invalid ssb_perRACH_OccasionAndCB_PreamblesPerSSB\n"); } + LOG_D(NR_MAC, "SSB per RO %f preambles per SSB %d\n", ret.ssb_per_ro, ret.preambles_per_ssb); return ret; } @@ -243,15 +239,15 @@ static ssb_ro_preambles_t get_ssb_ro_preambles_2step(struct NR_RACH_ConfigCommon ssb_ro_preambles_t ret = {0}; switch (config->present) { case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneEighth : - ret.ssb_per_ro = 1 / 8; + ret.ssb_per_ro = 0.125; ret.preambles_per_ssb = (config->choice.oneEighth + 1) << 2; break; case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneFourth : - ret.ssb_per_ro = 1 / 4; + ret.ssb_per_ro = 0.25; ret.preambles_per_ssb = (config->choice.oneFourth + 1) << 2; break; case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_oneHalf : - ret.ssb_per_ro = 1 / 2; + ret.ssb_per_ro = 0.5; ret.preambles_per_ssb = (config->choice.oneHalf + 1) << 2; break; case NR_RACH_ConfigCommonTwoStepRA_r16__msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16_PR_one : @@ -294,14 +290,13 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) } NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - ssb_ro_preambles_t config_info; int nb_of_preambles = 64; bool groupBconfigured = false; int preamb_ga = 0; if (ra->ra_type == RA_4_STEP) { AssertFatal(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB, "Not expeting ssb_perRACH_OccasionAndCB_PreamblesPerSSB to be NULL here\n"); - config_info = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + ra->ssb_ro_config = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles) nb_of_preambles = *nr_rach_ConfigCommon->totalNumberOfRA_Preambles; // Amongst the contention-based Random Access Preambles associated with an SSB the first numberOfRA-PreamblesGroupA @@ -325,9 +320,9 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) // configuration by msgA-SSB-PerRACH-OccasionAndCB-PreamblesPerSSB when provided; // otherwise, by ssb-perRACH-OccasionAndCB-PreamblesPerSSB if (twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16) - config_info = get_ssb_ro_preambles_2step(twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16); + ra->ssb_ro_config = get_ssb_ro_preambles_2step(twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16); else - config_info = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + ra->ssb_ro_config = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); if (twostep->msgA_TotalNumberOfRA_Preambles_r16) nb_of_preambles = *twostep->msgA_TotalNumberOfRA_Preambles_r16; } @@ -342,12 +337,12 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) nb_of_preambles = preamb_ga; } } - int rand_preamb = (rand_r(&seed) % config_info.preambles_per_ssb); - if (config_info.ssb_per_ro < 1) + int rand_preamb = (rand_r(&seed) % ra->ssb_ro_config.preambles_per_ssb); + if (ra->ssb_ro_config.ssb_per_ro < 1) ra->ra_PreambleIndex = groupOffset + rand_preamb; else { - int ssb_pr_idx = mac->ssb_list.nb_ssb_per_index[ra->ra_ssb] % (int)config_info.ssb_per_ro; - ra->ra_PreambleIndex = groupOffset + (ssb_pr_idx * config_info.preambles_per_ssb) + rand_preamb; + int ssb_pr_idx = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb] % (int)ra->ssb_ro_config.ssb_per_ro; + ra->ra_PreambleIndex = groupOffset + (ssb_pr_idx * ra->ssb_ro_config.preambles_per_ssb) + rand_preamb; } AssertFatal(ra->ra_PreambleIndex < nb_of_preambles, "Error! Selected preamble %d which exceeds number of prambles available %d\n", @@ -359,7 +354,8 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) static void ra_resource_selection(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; - ra->ra_ssb = -1; // init as not selected + int ssb = -1; // init as not selected + ra->ro_mask_index = -1; // init as not selected NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; if (ra->ra_type == RA_4_STEP) { // TODO if the Random Access procedure was initiated for SpCell beam failure recovery @@ -369,7 +365,8 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) // set the PREAMBLE_INDEX to the signalled ra-PreambleIndex; ra->ra_PreambleIndex = ra->pdcch_order.preamble_index; // select the SSB signalled by PDCCH - ra->ra_ssb = ra->pdcch_order.ssb_index; + ssb = ra->pdcch_order.ssb_index; + ra->ro_mask_index = ra->pdcch_order.prach_mask; } else if (rach_ConfigDedicated && rach_ConfigDedicated->cfra) { NR_CFRA_t *cfra = rach_ConfigDedicated->cfra; AssertFatal(cfra->occasions == NULL, "Dedicated PRACH occasions for CFRA not supported\n"); @@ -379,16 +376,17 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) NR_CFRA_SSB_Resource_t *res = ssb_list->ssb_ResourceList.list.array[i]; // TODO select an SSB with SS-RSRP above rsrp-ThresholdSSB amongst the associated SSBs if (res->ssb == mac->mib_ssb) { - ra->ra_ssb = mac->mib_ssb; + ssb = mac->mib_ssb; // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB ra->ra_PreambleIndex = res->ra_PreambleIndex; + ra->ro_mask_index = ssb_list->ra_ssb_OccasionMaskIndex; break; } } } else { // for the contention-based Random Access preamble selection // TODO if at least one of the SSBs with SS-RSRP above rsrp-ThresholdSSB is available // else select any SSB - ra->ra_ssb = mac->mib_ssb; + ssb = mac->mib_ssb; config_preamble_index(mac); } } else { // 2-step RA @@ -402,19 +400,156 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) for (int i = 0; i < cfra->resourcesTwoStep_r16.ssb_ResourceList.list.count; i++) { NR_CFRA_SSB_Resource_t *res = cfra->resourcesTwoStep_r16.ssb_ResourceList.list.array[i]; if (res->ssb == mac->mib_ssb) { - ra->ra_ssb = mac->mib_ssb; + ssb = mac->mib_ssb; // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB ra->ra_PreambleIndex = res->ra_PreambleIndex; + ra->ro_mask_index = cfra->resourcesTwoStep_r16.ra_ssb_OccasionMaskIndex; break; } } } else { // for the contention-based Random Access Preamble selection // TODO if at least one of the SSBs with SS-RSRP above msgA-RSRP-ThresholdSSB is available // else select any SSB - ra->ra_ssb = mac->mib_ssb; + ssb = mac->mib_ssb; config_preamble_index(mac); } } + AssertFatal(ra->ra_ssb >= 0, "Something wrong! RA resource selection didn't set any SSB\n"); + // setting the RA ssb value as the progressive number of SSB transmitted + // non-transmitted SSBs are not taken into account + ra->ra_ssb = mac->ssb_list.nb_ssb_per_index[ssb]; +} + +static bool check_mixed_slot_prach(frame_structure_t *fs, int slot, int start_prach, int end_prach) +{ + bool is_mixed = is_mixed_slot(slot, fs); + if (is_mixed) { + tdd_bitmap_t *bitmap = &fs->period_cfg.tdd_slot_bitmap[slot % fs->numb_slots_period]; + if (bitmap->num_ul_symbols == 0) + return false; + int ul_end = NR_NUMBER_OF_SYMBOLS_PER_SLOT - 1; + int ul_start = NR_NUMBER_OF_SYMBOLS_PER_SLOT - bitmap->num_ul_symbols; + if (start_prach < ul_start || end_prach > ul_end) + return false; + } + return true; +} + +static void select_prach_occasion(RA_config_t *ra, + int nb_tx_ssb, + int n, + prach_occasion_info_t ra_occasions_period[n], + int num_ra_occasions_period) +{ + unsigned int seed; + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // Overwrite seed with non-random seed for IQ player/recorder + seed = 1; + } else { + // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int) + seed = (unsigned int) (rdtsc_oai() & ~0); + } + + int num_ros_per_ssb = 0; + int idx_ssb = 0; + int temp_idx = 0; + if (ra->ssb_ro_config.ssb_per_ro < 1) { + num_ros_per_ssb = (int) (1 / ra->ssb_ro_config.ssb_per_ro); + idx_ssb = (rand_r(&seed) % num_ros_per_ssb); + temp_idx = ra->ra_ssb * num_ros_per_ssb + idx_ssb; + } else { + int ssb_per_ro = nb_tx_ssb < ra->ssb_ro_config.ssb_per_ro ? nb_tx_ssb : ra->ssb_ro_config.ssb_per_ro; + num_ros_per_ssb = ra->association_periods * ssb_per_ro * num_ra_occasions_period / nb_tx_ssb; + idx_ssb = (rand_r(&seed) % num_ros_per_ssb); + int eq_ssb = ra->ra_ssb + (idx_ssb * nb_tx_ssb); + temp_idx = eq_ssb / ra->ssb_ro_config.ssb_per_ro; + } + int ro_index = temp_idx % num_ra_occasions_period; + int ass_period_idx = temp_idx / num_ra_occasions_period; + ra->sched_ro_info = ra_occasions_period[ro_index]; + ra->sched_ro_info.association_period_idx = ass_period_idx; +} + +static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_index, int num_fd_occasions, int scs) +{ + RA_config_t *ra = &mac->ra; + int num_ra_occasions_period = 0; + frame_structure_t *fs = &mac->frame_structure; + nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(prach_config_index, mac->frequency_range, fs->frame_type); + int max_num_occasions = prach_info.N_RA_sfn * prach_info.N_t_slot * prach_info.N_RA_slot * num_fd_occasions; + prach_occasion_info_t ra_occasions_period[max_num_occasions]; + // Number of PRACH slots within a subframe (or 60kHz slot) to be taken into account only for 30 and 120kHz + // as defined in 5.3.2 of 211 + int prach_slots_in_sf = (scs == 1 || scs == 3) ? prach_info.N_RA_slot : 1; + uint64_t temp_s_map = prach_info.s_map; + int n_frames = prach_info.y2 == -1 ? 1 : 2; + for (int n = 0; n < n_frames; n++) { + int sf = 0; + for (int s = 0; s < prach_info.N_RA_sfn; s++) { // subframe/60kHz slot occasions in period + while (((temp_s_map >> sf) & 0x01) == 0) + sf++; + int sl = sf; + for (int i = 0; i < prach_slots_in_sf; i++) { // slot per subframe/60kHz slot + int add_slot = i; + if (scs == 1 || scs == 3) { + sl *= 2; + // if only 1 slot per subframe (or 60kHz slot) in case of 30 or 120kHz it's the odd one + // as defined in 5.3.2 of 211 + if (prach_slots_in_sf == 1) + add_slot = 1; + } + int slot = sl + add_slot; + if (!is_ul_slot(slot, fs)) + continue; // valid PRACH occasion only if slot is UL + for (int t = 0; t < prach_info.N_t_slot; t++) { // td occasions within a slot + int start_symbol = prach_info.start_symbol + t * prach_info.N_dur; + int end_symbol = start_symbol + prach_info.N_dur; + // valid occasion only if PRACH symbols are UL symbols in mixed slot + if (fs->frame_type == TDD && !check_mixed_slot_prach(fs, slot, start_symbol, end_symbol)) + continue; + for (int f = 0; f < num_fd_occasions; f++) { // fd occasions + ra_occasions_period[num_ra_occasions_period] = (prach_occasion_info_t) { + .slot = slot, + .frame_info[0] = prach_info.x, + .frame_info[1] = n == 0 ? prach_info.y : prach_info.y2, + .start_symbol = start_symbol, + .fdm = f, + .format = prach_info.format}; + LOG_D(NR_MAC, + "RA occasion %d: slot %d start symbol %d fd occasion %d\n", + num_ra_occasions_period, + slot, + start_symbol, + f); + num_ra_occasions_period++; + } + } + } + sf++; + } + } + + int config_period = prach_info.x; // configuration period + ra->association_periods = 1; + int nb_eq_ssb = mac->ssb_list.nb_tx_ssb; + if (ra->ssb_ro_config.ssb_per_ro < 1) + nb_eq_ssb *= (int) (1 / ra->ssb_ro_config.ssb_per_ro); + int nb_eq_ro = num_ra_occasions_period; + if (ra->ssb_ro_config.ssb_per_ro > 1) + nb_eq_ro *= (int) ra->ssb_ro_config.ssb_per_ro; + while (nb_eq_ssb > nb_eq_ro) { + // not enough PRACH occasions -> need to increase association period + ra->association_periods <<= 1; + AssertFatal(ra->association_periods * config_period <= 16, + "Cannot find an association period for %d SSB and %d RO with %f SSB per RO\n", + mac->ssb_list.nb_tx_ssb, + num_ra_occasions_period, + ra->ssb_ro_config.ssb_per_ro); + nb_eq_ro <<= 1; // doubling the association period -> doubling ROs + } + LOG_D(NR_MAC, "PRACH configuration period %d association period %d\n", config_period, ra->association_periods); + + select_prach_occasion(ra, mac->ssb_list.nb_tx_ssb, max_num_occasions, ra_occasions_period, num_ra_occasions_period); } // Random Access procedure initialization as per 5.1.1 and initialization of variables specific @@ -639,6 +774,21 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) ra->RA_backoff_cnt = 0; ra->RA_window_cnt = -1; + int ra_config_index = 0; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PRACH_ConfigurationIndex_r16) + ra_config_index = *twostep_generic->msgA_PRACH_ConfigurationIndex_r16; + else { + if (rach_ConfigGeneric->ext1 && rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610) + ra_config_index = *rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610; + else + ra_config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + } + int fdm = 0; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_RO_FDM_r16) + fdm = 1 << *twostep_generic->msgA_RO_FDM_r16; + else + fdm = 1 << rach_ConfigGeneric->msg1_FDM; + configure_prach_occasions(mac, ra_config_index, fdm, prach_scs); return true; } From 24fed617b51029361c62990f2c2edeb76a471090 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 29 Nov 2024 11:54:46 +0100 Subject: [PATCH 14/34] reworking prach scheduler to use new rach occasion information --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 4 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 22 +-- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 160 ++++--------------- 4 files changed, 46 insertions(+), 141 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 4dc295acf3..d305b0246c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -320,7 +320,7 @@ typedef struct { int Pc_max; } NR_PRACH_RESOURCES_t; -typedef struct{ +typedef struct { float ssb_per_ro; int preambles_per_ssb; } ssb_ro_preambles_t; @@ -362,8 +362,6 @@ typedef struct { bool RA_active; /// Random-access preamble index int ra_PreambleIndex; - // When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble - uint8_t ssb_nb_in_ro; int zeroCorrelationZoneConfig; int restricted_set_config; // selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs) diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 1b865a78eb..95cc1b12ac 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -302,4 +302,3 @@ void release_mac_configuration(NR_UE_MAC_INST_t *mac, NR_UE_MAC_reset_cause_t ca for (int i = mac->TAG_list.count; i > 0 ; i--) asn_sequence_del(&mac->TAG_list, i - 1, 1); } - diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 039788b62e..d162168575 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -403,7 +403,7 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) ssb = mac->mib_ssb; // set the PREAMBLE_INDEX to a ra-PreambleIndex corresponding to the selected SSB ra->ra_PreambleIndex = res->ra_PreambleIndex; - ra->ro_mask_index = cfra->resourcesTwoStep_r16.ra_ssb_OccasionMaskIndex; + ra->ro_mask_index = cfra->resourcesTwoStep_r16.ra_ssb_OccasionMaskIndex; break; } } @@ -454,7 +454,7 @@ static void select_prach_occasion(RA_config_t *ra, int idx_ssb = 0; int temp_idx = 0; if (ra->ssb_ro_config.ssb_per_ro < 1) { - num_ros_per_ssb = (int) (1 / ra->ssb_ro_config.ssb_per_ro); + num_ros_per_ssb = (int)(1 / ra->ssb_ro_config.ssb_per_ro); idx_ssb = (rand_r(&seed) % num_ros_per_ssb); temp_idx = ra->ra_ssb * num_ros_per_ssb + idx_ssb; } else { @@ -508,13 +508,13 @@ static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_in if (fs->frame_type == TDD && !check_mixed_slot_prach(fs, slot, start_symbol, end_symbol)) continue; for (int f = 0; f < num_fd_occasions; f++) { // fd occasions - ra_occasions_period[num_ra_occasions_period] = (prach_occasion_info_t) { - .slot = slot, - .frame_info[0] = prach_info.x, - .frame_info[1] = n == 0 ? prach_info.y : prach_info.y2, - .start_symbol = start_symbol, - .fdm = f, - .format = prach_info.format}; + ra_occasions_period[num_ra_occasions_period] = + (prach_occasion_info_t){.slot = slot, + .frame_info[0] = prach_info.x, + .frame_info[1] = n == 0 ? prach_info.y : prach_info.y2, + .start_symbol = start_symbol, + .fdm = f, + .format = prach_info.format}; LOG_D(NR_MAC, "RA occasion %d: slot %d start symbol %d fd occasion %d\n", num_ra_occasions_period, @@ -533,10 +533,10 @@ static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_in ra->association_periods = 1; int nb_eq_ssb = mac->ssb_list.nb_tx_ssb; if (ra->ssb_ro_config.ssb_per_ro < 1) - nb_eq_ssb *= (int) (1 / ra->ssb_ro_config.ssb_per_ro); + nb_eq_ssb *= (int)(1 / ra->ssb_ro_config.ssb_per_ro); int nb_eq_ro = num_ra_occasions_period; if (ra->ssb_ro_config.ssb_per_ro > 1) - nb_eq_ro *= (int) ra->ssb_ro_config.ssb_per_ro; + nb_eq_ro *= (int)ra->ssb_ro_config.ssb_per_ro; while (nb_eq_ssb > nb_eq_ro) { // not enough PRACH occasions -> need to increase association period ra->association_periods <<= 1; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index b2e1edd19e..bfdac6474e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1939,91 +1939,6 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) } } -// Returns a RACH occasion if any matches the SSB idx, the frame and the slot -static int get_nr_prach_info_from_ssb_index(prach_association_pattern_t *prach_assoc_pattern, - int ssb_idx, - int frame, - int slot, - ssb_list_info_t *ssb_list, - prach_occasion_info_t **prach_occasion_info_pp) -{ - prach_occasion_slot_t *prach_occasion_slot_p = NULL; - - *prach_occasion_info_pp = NULL; - - // Search for a matching RO slot in the SSB_to_RO map - // A valid RO slot will match: - // - ssb_idx mapped to one of the ROs in that RO slot - // - exact slot number - // - frame offset - int idx_list = ssb_list->nb_ssb_per_index[ssb_idx]; - ssb_info_t *ssb_info_p = &ssb_list->tx_ssb[idx_list]; - LOG_D(NR_MAC, "checking for prach : ssb_info_p->nb_mapped_ro %d\n", ssb_info_p->nb_mapped_ro); - for (int n_mapped_ro = 0; n_mapped_ro < ssb_info_p->nb_mapped_ro; n_mapped_ro++) { - LOG_D(NR_MAC, - "%d.%d: mapped_ro[%d]->frame.slot %d.%d, prach_assoc_pattern->nb_of_frame %d\n", - frame, - slot, - n_mapped_ro, - ssb_info_p->mapped_ro[n_mapped_ro]->frame, - ssb_info_p->mapped_ro[n_mapped_ro]->slot, - prach_assoc_pattern->nb_of_frame); - if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) && prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame != 0 && - (ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern->nb_of_frame))) { - uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame; - uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern->prach_conf_period_list[0].nb_of_frame; - prach_occasion_slot_p = &prach_assoc_pattern->prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot]; - } - } - - // If there is a matching RO slot in the SSB_to_RO map - if (NULL != prach_occasion_slot_p) { - // A random RO mapped to the SSB index should be selected in the slot - - // First count the number of times the SSB index is found in that RO - uint8_t nb_mapped_ssb = 0; - - for (int ro_in_time = 0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { - for (int ro_in_freq = 0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = - prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq; - for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) { - if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { - nb_mapped_ssb++; - } - } - } - } - - // Choose a random SSB nb - uint8_t random_ssb_nb = 0; - - random_ssb_nb = ((taus()) % nb_mapped_ssb); - - // Select the RO according to the chosen random SSB nb - nb_mapped_ssb=0; - for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) { - for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = - prach_occasion_slot_p->prach_occasion + ro_in_time * prach_occasion_slot_p->nb_of_prach_occasion_in_freq + ro_in_freq; - for (uint8_t ssb_nb = 0; ssb_nb < ro_p->nb_mapped_ssb; ssb_nb++) { - if (ro_p->mapped_ssb_idx[ssb_nb] == ssb_idx) { - if (nb_mapped_ssb == random_ssb_nb) { - *prach_occasion_info_pp = ro_p; - return 1; - } - else { - nb_mapped_ssb++; - } - } - } - } - } - } - - return 0; -} - // Build the SSB to RO mapping upon RRC configuration update void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) { @@ -2522,6 +2437,23 @@ void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) } } +static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_info, int association_periods) +{ + int config_period = prach_occasion_info->frame_info[0]; + int frame_period = config_period * association_periods; + int frame_in_period = frame % frame_period; + if (association_periods > 1) { + int current_assoc_period = frame_in_period / config_period; + if (current_assoc_period != prach_occasion_info->association_period_idx) + return false; + frame_in_period %= config_period; + } + if (frame_in_period == prach_occasion_info->frame_info[1]) // SFN % x == y (see Tables in Table 6.3.3.2 of 38.211) + return true; + else + return false; +} + // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3. // - todo: @@ -2533,49 +2465,36 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t if (ra->ra_state != nrRA_GENERATE_PREAMBLE) return; - fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; - fapi_nr_prach_config_t *prach_config = &cfg->prach_config; + // Get any valid PRACH occasion in the current slot for the selected SSB index + prach_occasion_info_t *prach_occasion_info = &ra->sched_ro_info; - const int bwp_id = mac->current_UL_BWP->bwp_id; + if (!is_prach_frame(frameP, prach_occasion_info, ra->association_periods)) + return; if (is_ul_slot(slotP, &mac->frame_structure)) { - // WIP Need to get the proper selected ssb_idx - // Initial beam selection functionality is not available yet - uint8_t selected_gnb_ssb_idx = mac->mib_ssb; - - // Get any valid PRACH occasion in the current slot for the selected SSB index - prach_occasion_info_t *prach_occasion_info_p; - int is_nr_prach_slot = get_nr_prach_info_from_ssb_index(&mac->prach_assoc_pattern[bwp_id], - selected_gnb_ssb_idx, - (int)frameP, - (int)slotP, - &mac->ssb_list, - &prach_occasion_info_p); - - if (is_nr_prach_slot) { - AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n"); - + if (slotP == prach_occasion_info->slot) { nr_get_RA_window(mac); - - uint16_t format = prach_occasion_info_p->format; - uint16_t format0 = format & 0xff; // single PRACH format - uint16_t format1 = (format >> 8) & 0xff; // dual PRACH format - fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); if (!pdu) { LOG_E(NR_MAC, "Error in PRACH allocation\n"); return; } + + uint16_t format = prach_occasion_info->format; + uint16_t format0 = format & 0xff; // single PRACH format + uint16_t format1 = (format >> 8) & 0xff; // dual PRACH format + + fapi_nr_prach_config_t *prach_config = &mac->phy_config.config_req.prach_config; pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){ .phys_cell_id = mac->physCellId, .num_prach_ocas = 1, - .prach_slot = prach_occasion_info_p->slot, - .prach_start_symbol = prach_occasion_info_p->start_symbol, - .num_ra = prach_occasion_info_p->fdm, + .prach_slot = prach_occasion_info->slot, + .prach_start_symbol = prach_occasion_info->start_symbol, + .num_ra = prach_occasion_info->fdm, .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format0, ra->restricted_set_config), - .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index, + .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].prach_root_sequence_index, .restricted_set = prach_config->restricted_set_config, - .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1}; + .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].k1}; LOG_I(NR_MAC, "PRACH scheduler: Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", @@ -2584,15 +2503,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t pdu->prach_config_pdu.prach_start_symbol, pdu->prach_config_pdu.num_ra); - // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO) - for (int ssb_nb_in_ro=0; ssb_nb_in_ronb_mapped_ssb; ssb_nb_in_ro++) { - if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb_in_ro] == selected_gnb_ssb_idx) { - ra->ssb_nb_in_ro = ssb_nb_in_ro; - break; - } - } - AssertFatal(ra->ssb_nb_in_ronb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx); - if (format1 != 0xff) { switch (format0) { // dual PRACH format case 0xa1: @@ -2706,7 +2616,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t // Compute MsgB RNTI ra->MsgB_rnti = - nr_get_MsgB_rnti(prach_occasion_info_p->start_symbol, slot_RA, prach_occasion_info_p->fdm, 0); + nr_get_MsgB_rnti(prach_occasion_info->start_symbol, slot_RA, prach_occasion_info->fdm, 0); LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]); ra->ra_state = nrRA_WAIT_MSGB; ra->t_crnti = 0; @@ -2715,8 +2625,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t } else { AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type); } - - // rnti = ra->t_crnti; } // is_nr_prach_slot } // if is_nr_UL_slot } From 9f3f7b041cbe15ab18539f153a9a916e853a1ee8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 29 Nov 2024 12:38:00 +0100 Subject: [PATCH 15/34] clearing old structures and functions for rach occasions --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 10 - openair2/LAYER2/NR_MAC_UE/mac_defs.h | 59 --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 5 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 11 - openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 397 ------------------- 6 files changed, 1 insertion(+), 482 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 44e01d4d04..9cafa8f579 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -48,7 +48,6 @@ static void build_ssb_list(NR_UE_MAC_INST_t *mac) { // Create the list of transmitted SSBs - free(mac->ssb_list.tx_ssb); memset(&mac->ssb_list, 0, sizeof(ssb_list_info_t)); ssb_list_info_t *ssb_list = &mac->ssb_list; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; @@ -63,7 +62,6 @@ static void build_ssb_list(NR_UE_MAC_INST_t *mac) } else ssb_list->nb_ssb_per_index[ssb_index] = -1; } - ssb_list->tx_ssb = calloc(ssb_list->nb_tx_ssb, sizeof(*ssb_list->tx_ssb)); } static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_structure_t *fs) @@ -1789,9 +1787,6 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si if (mac->state == UE_RECEIVING_SIB && can_start_ra) mac->state = UE_PERFORMING_RA; - // Setup the SSB to Rach Occasions mapping according to the config - build_ssb_to_ro_map(mac); - if (!get_softmodem_params()->emulate_l1) mac->if_module->phy_config_request(&mac->phy_config); ret = pthread_mutex_unlock(&mac->if_mutex); @@ -2651,11 +2646,6 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, if (ue_Capability) handle_mac_uecap_info(mac, ue_Capability); - // Setup the SSB to Rach Occasions mapping according to the config - // Only if RACH is configured for current BWP - if (mac->current_UL_BWP->rach_ConfigCommon) - build_ssb_to_ro_map(mac); - if (!mac->dl_config_request || !mac->ul_config_request) ue_init_config_request(mac, mac->frame_structure.numb_slots_frame); ret = pthread_mutex_unlock(&mac->if_mutex); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index d305b0246c..8536e4a081 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -79,23 +79,7 @@ /*!\brief value for indicating BSR Timer is not running */ #define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) -// ================================================ -// SSB to RO mapping private defines and structures -// ================================================ - -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16 -#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms -#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms -#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms -#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160) -#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period #define MAX_NB_SSB (64) // Maximum number of possible SSB indexes -#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config - -// Maximum number of ROs that can be mapped to an SSB in an association pattern -// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB -// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot -#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD) // =============== // DCI fields defs @@ -181,22 +165,11 @@ typedef struct prach_occasion_info { int start_symbol; // 0 - 13 (14 symbols in a slot) int fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8) int slot; - int frame; // 0 - 15 (maximum number of frames in a 160ms association pattern) - uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs - uint8_t nb_mapped_ssb; int format; // RO preamble format int frame_info[2]; int association_period_idx; } prach_occasion_info_t; -// PRACH occasion slot details -// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency -typedef struct prach_occasion_slot { - prach_occasion_info_t *prach_occasion; // Starting symbol of each PRACH occasions in a slot - uint8_t nb_of_prach_occasion_in_time; - uint8_t nb_of_prach_occasion_in_freq; -} prach_occasion_slot_t; - typedef enum { phr_cause_prohibit_timer = 0, phr_cause_periodic_timer, @@ -471,39 +444,8 @@ typedef struct NR_UL_TIME_ALIGNMENT { int slot; } NR_UL_TIME_ALIGNMENT_t; -// The PRACH Config period is a series of selected slots in one or multiple frames -typedef struct prach_conf_period { - prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME]; - uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period - uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames - uint8_t nb_of_slot; // Nb of slots in each frame -} prach_conf_period_t; - -// The association period is a series of PRACH Config periods -typedef struct prach_association_period { - prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD]; - uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period - uint8_t nb_of_frame; // Total number of frames included in the association period -} prach_association_period_t; - -// The association pattern is a series of Association periods -typedef struct prach_association_pattern { - prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD]; - uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern - uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH - uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length) -} prach_association_pattern_t; - -// SSB details -typedef struct ssb_info { - prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index - uint32_t nb_mapped_ro; // Total number of mapped ROs to this SSB index -} ssb_info_t; - // List of all the possible SSBs and their details typedef struct ssb_list_info { - ssb_info_t *tx_ssb; int nb_tx_ssb; int nb_ssb_per_index[MAX_NB_SSB]; } ssb_list_info_t; @@ -614,7 +556,6 @@ typedef struct NR_UE_MAC_INST_s { si_schedInfo_t si_SchedInfo; ssb_list_info_t ssb_list; - prach_association_pattern_t prach_assoc_pattern[MAX_NUM_BWP_UE]; NR_UE_ServingCell_Info_t sc_info; A_SEQUENCE_OF(NR_UE_DL_BWP_t) dl_BWPs; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 724ef743ba..848cbce9b1 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -335,7 +335,6 @@ void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id); int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac); -void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id); void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); @@ -350,9 +349,7 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p int start_DLBWP, dci_field_t frequency_domain_assignment); -void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac); - -void ue_init_config_request(NR_UE_MAC_INST_t *mac, int slots_per_frame); +void ue_init_config_request(NR_UE_MAC_INST_t *mac, int scs); fapi_nr_dl_config_request_t *get_dl_config_request(NR_UE_MAC_INST_t *mac, int slot); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 95cc1b12ac..7cac155bc6 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -78,7 +78,6 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); memset(&mac->ssb_list, 0, sizeof(mac->ssb_list)); - memset(mac->prach_assoc_pattern, 0, sizeof(mac->prach_assoc_pattern)); for (int i = 0; i < NR_MAX_SR_ID; i++) memset(&mac->scheduling_info.sr_info[i], 0, sizeof(mac->scheduling_info.sr_info[i])); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index d162168575..7996980884 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1333,14 +1333,6 @@ void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) release_ul_config(pdu, false); } -void free_rach_structures(NR_UE_MAC_INST_t *nr_mac, int bwp_id) -{ - for (int j = 0; j < MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD; j++) - for (int k = 0; k < MAX_NB_FRAME_IN_PRACH_CONF_PERIOD; k++) - for (int l = 0; l < MAX_NB_SLOT_IN_FRAME; l++) - free(nr_mac->prach_assoc_pattern[bwp_id].prach_conf_period_list[j].prach_occasion_slot_map[k][l].prach_occasion); -} - void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) { RA_config_t *ra = &nr_mac->ra; @@ -1350,7 +1342,4 @@ void reset_ra(NR_UE_MAC_INST_t *nr_mac, bool free_prach) if (!free_prach) return; - - for (int i = 0; i < MAX_NUM_BWP_UE; i++) - free_rach_structures(nr_mac, i); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index bfdac6474e..85a6cd5942 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1561,403 +1561,6 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac, return 0; } -// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config -static void build_ro_list(NR_UE_MAC_INST_t *mac) -{ - int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers - uint8_t slot_shift_for_map; - uint8_t map_shift; - bool even_slot_invalid; - int nb_fdm; - - uint8_t config_index; - int msg1_FDM; - - uint8_t nb_of_frames_per_prach_conf_period; - - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; - - config_index = rach_ConfigGeneric->prach_ConfigurationIndex; - msg1_FDM = rach_ConfigGeneric->msg1_FDM; - - switch (msg1_FDM){ - case 0: - case 1: - case 2: - case 3: - nb_fdm = 1 << msg1_FDM; - break; - default: - AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM); - } - - // Create the PRACH occasions map - // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule - - int unpaired = mac->phy_config.config_req.cell_config.frame_duplex_type; - - const int ul_mu = mac->current_UL_BWP->scs; - const int mu = nr_get_prach_or_ul_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, setup, ul_mu); - nr_prach_info_t prach_config = get_nr_prach_occasion_info_from_index(config_index, mac->frequency_range, unpaired); - - // Identify the proper PRACH Configuration Index table according to the operating frequency - LOG_D(NR_MAC,"mu = %u, PRACH config index = %u, unpaired = %u\n", mu, config_index, unpaired); - - if (mac->frequency_range == FR2) { //FR2 - y2 = prach_config.y2; - slot_shift_for_map = mu-2; - if ((mu == 3) && (prach_config.N_RA_slot == 1)) - even_slot_invalid = true; - else - even_slot_invalid = false; - } - else { // FR1 - y2 = prach_config.y; - slot_shift_for_map = mu; - if ((mu == 1) && (prach_config.N_RA_slot == 1) && ((prach_config.format & 0xff) > 3)) - // no prach in even slots @ 30kHz for 1 prach per subframe - even_slot_invalid = true; - else - even_slot_invalid = false; - } // FR1 - - const int bwp_id = mac->current_UL_BWP->bwp_id; - prach_association_pattern_t *prach_assoc_pattern = &mac->prach_assoc_pattern[bwp_id]; - prach_assoc_pattern->nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / prach_config.x; - nb_of_frames_per_prach_conf_period = prach_config.x; - int slots_per_frame = mac->frame_structure.numb_slots_frame; - LOG_D(NR_MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern->nb_of_prach_conf_period_in_max_period); - - // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // ---------------------------------------------------------------------------------------------------------------------------------------------- - // For every PRACH configuration periods - // ------------------------------------- - for (int period_idx = 0; period_idx < prach_assoc_pattern->nb_of_prach_conf_period_in_max_period; period_idx++) { - prach_conf_period_t *prach_conf_period_list = &prach_assoc_pattern->prach_conf_period_list[period_idx]; - prach_conf_period_list->nb_of_prach_occasion = 0; - prach_conf_period_list->nb_of_frame = nb_of_frames_per_prach_conf_period; - prach_conf_period_list->nb_of_slot = slots_per_frame; - - LOG_D(NR_MAC,"PRACH Conf Period Idx %d\n", period_idx); - - // For every frames in a PRACH configuration period - // ------------------------------------------------ - for (int frame_idx = 0; frame_idx < nb_of_frames_per_prach_conf_period; frame_idx++) { - int frame_rach = (period_idx * nb_of_frames_per_prach_conf_period) + frame_idx; - - LOG_D(NR_MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", frame_idx, frame_rach); - // Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y) - if ((frame_rach % prach_config.x) == prach_config.y || (frame_rach % prach_config.x) == y2) { - - // For every slot in a frame - // ------------------------- - for (int slot = 0; slot < slots_per_frame; slot++) { - // Is it a valid slot? - map_shift = slot >> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz - if ((prach_config.s_map >> map_shift) & 0x01) { - // Valid slot - - // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also - if (even_slot_invalid && (slot%2 == 0)) - continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe - - // We're good: valid frame and valid slot - // Compute all the PRACH occasions in the slot - - prach_occasion_slot_t *slot_map = &prach_conf_period_list->prach_occasion_slot_map[frame_idx][slot]; - slot_map->nb_of_prach_occasion_in_time = prach_config.N_t_slot; - slot_map->nb_of_prach_occasion_in_freq = nb_fdm; - slot_map->prach_occasion = malloc(prach_config.N_t_slot * nb_fdm * sizeof(*slot_map->prach_occasion)); - AssertFatal(slot_map->prach_occasion, "no memory available\n"); - for (int n_prach_occ_in_time = 0; n_prach_occ_in_time < prach_config.N_t_slot; n_prach_occ_in_time++) { - uint8_t start_symbol = prach_config.start_symbol + n_prach_occ_in_time * prach_config.N_dur; - LOG_D(NR_MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time); - - for (int n_prach_occ_in_freq = 0; n_prach_occ_in_freq < nb_fdm; n_prach_occ_in_freq++) { - slot_map->prach_occasion[n_prach_occ_in_time * nb_fdm + n_prach_occ_in_freq] = - (prach_occasion_info_t){.start_symbol = start_symbol, - .fdm = n_prach_occ_in_freq, - .frame = frame_idx, - .slot = slot, - .format = prach_config.format}; - prach_assoc_pattern->prach_conf_period_list[period_idx].nb_of_prach_occasion++; - - LOG_D(NR_MAC, - "Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n", - frame_rach, - slot, - start_symbol, - n_prach_occ_in_time, - n_prach_occ_in_freq, - prach_conf_period_list->nb_of_prach_occasion, - slot_map->nb_of_prach_occasion_in_time, - slot_map->nb_of_prach_occasion_in_freq); - } // For every freq in the slot - } // For every time occasions in the slot - } // Valid slot? - } // For every slots in a frame - } // Valid frame? - } // For every frames in a prach configuration period - } // For every prach configuration periods in the maximum association pattern period (160ms) -} - -static int get_ssb_idx_from_list(ssb_list_info_t *ssb_list, int idx) -{ - for (int ssb_index = 0; ssb_index < MAX_NB_SSB; ssb_index++) { - if (ssb_list->nb_ssb_per_index[ssb_index] == idx) - return ssb_index; - } - AssertFatal(false, "Couldn't find SSB index in SSB list\n"); - return 0; -} - -// Map the transmitted SSBs to the ROs and create the association pattern according to the config -static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) -{ - // Map SSBs to PRACH occasions - // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - - const struct { - // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB - bool multiple_ssb_per_ro; - // Nb of SSBs per RACH or RACHs per SSB - int ssb_rach_ratio; - } config[] = {{false, 0}, {false, 8}, {false, 4}, {false, 2}, {true, 1}, {true, 2}, {true, 4}, {true, 8}, {true, 16}}; - AssertFatal(ssb_perRACH_config <= NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen, - "Unsupported ssb_perRACH_config %d\n", - ssb_perRACH_config); - const bool multiple_ssb_per_ro = config[ssb_perRACH_config].multiple_ssb_per_ro; - const int ssb_rach_ratio = config[ssb_perRACH_config].ssb_rach_ratio; - - LOG_D(NR_MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro); - - const int bwp_id = mac->current_UL_BWP->bwp_id; - ssb_list_info_t *ssb_list = &mac->ssb_list; - - // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period - // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same - // number of PRACH occasions - // (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule) - // There is only one possible association period which can contain up to 16 PRACH configuration periods - LOG_D(NR_MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n"); - const int required_nb_of_prach_occasion = - multiple_ssb_per_ro ? ((ssb_list->nb_tx_ssb - 1) + ssb_rach_ratio) / ssb_rach_ratio : ssb_list->nb_tx_ssb * ssb_rach_ratio; - - prach_association_pattern_t *prach_assoc_pattern = &mac->prach_assoc_pattern[bwp_id]; - const prach_conf_period_t *prach_conf_period = &prach_assoc_pattern->prach_conf_period_list[0]; - AssertFatal(prach_conf_period->nb_of_prach_occasion > 0, - "prach_conf_period->nb_of_prach_occasion shouldn't be 0 (nb_tx_ssb %d, ssb_rach_ratio %d)\n", - ssb_list->nb_tx_ssb, - ssb_rach_ratio); - prach_association_period_t *prach_association_period = &prach_assoc_pattern->prach_association_period_list[0]; - const int required_nb_of_prach_conf_period = - ((required_nb_of_prach_occasion - 1) + prach_conf_period->nb_of_prach_occasion) / prach_conf_period->nb_of_prach_occasion; - - if (required_nb_of_prach_conf_period == 1) { - prach_association_period->nb_of_prach_conf_period = 1; - } - else if (required_nb_of_prach_conf_period == 2) { - prach_association_period->nb_of_prach_conf_period = 2; - } - else if (required_nb_of_prach_conf_period <= 4) { - prach_association_period->nb_of_prach_conf_period = 4; - } - else if (required_nb_of_prach_conf_period <= 8) { - prach_association_period->nb_of_prach_conf_period = 8; - } - else if (required_nb_of_prach_conf_period <= 16) { - prach_association_period->nb_of_prach_conf_period = 16; - } - else { - AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period); - } - - prach_assoc_pattern->nb_of_assoc_period = 1; // WIP: only one possible association period - prach_association_period->nb_of_frame = prach_association_period->nb_of_prach_conf_period * prach_conf_period->nb_of_frame; - prach_assoc_pattern->nb_of_frame = prach_association_period->nb_of_frame; - - LOG_D(NR_MAC, - "Assoc period %d, Nb of frames in assoc period %d\n", - prach_association_period->nb_of_prach_conf_period, - prach_association_period->nb_of_frame); - - // Set the starting PRACH Configuration period index in the association_pattern map for this particular association period - int prach_configuration_period_idx = - 0; // WIP: only one possible association period so the starting PRACH configuration period is automatically 0 - - // Map all the association periods within the association pattern period - LOG_D(NR_MAC,"Proceed to the SSB to RO mapping\n"); - // Check if we need to map multiple SSBs per RO or multiple ROs per SSB - - if (multiple_ssb_per_ro) { - const prach_association_period_t *end = - prach_assoc_pattern->prach_association_period_list + prach_assoc_pattern->nb_of_assoc_period; - for (prach_association_period_t *prach_period = prach_assoc_pattern->prach_association_period_list; prach_period < end; - prach_period++) { - // Set the starting PRACH Configuration period index in the association_pattern map for this particular association period - // WIP: only one possible association period so the starting PRACH configuration period is automatically 0 - // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - int idx = 0; - bool done = false; - for (int i = 0; i < prach_period->nb_of_prach_conf_period && !done; i++, prach_configuration_period_idx++) { - prach_period->prach_conf_period_list[i] = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx]; - prach_conf_period_t *prach_conf = prach_period->prach_conf_period_list[i]; - // Build the association period with its association PRACH Configuration indexes - // Go through all the ROs within the PRACH config period - for (int frame = 0; frame < prach_conf->nb_of_frame && !done; frame++) { - for (int slot = 0; slot < prach_conf->nb_of_slot && !done; slot++) { - prach_occasion_slot_t *slot_map = &prach_conf->prach_occasion_slot_map[frame][slot]; - for (int ro_in_time = 0; ro_in_time < slot_map->nb_of_prach_occasion_in_time && !done; ro_in_time++) { - for (int ro_in_freq = 0; ro_in_freq < slot_map->nb_of_prach_occasion_in_freq && !done; ro_in_freq++) { - prach_occasion_info_t *ro_p = - slot_map->prach_occasion + ro_in_time * slot_map->nb_of_prach_occasion_in_freq + ro_in_freq; - // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO - // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - for (; idx < ssb_list->nb_tx_ssb; idx++) { - ssb_info_t *tx_ssb = ssb_list->tx_ssb + idx; - // Map only the transmitted ssb_idx - int ssb_idx = get_ssb_idx_from_list(ssb_list, idx); - ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx; - ro_p->nb_mapped_ssb++; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > tx_ssb->nb_mapped_ro + 1, - "Too many mapped ROs (%d) to a single SSB\n", - tx_ssb->nb_mapped_ro); - tx_ssb->mapped_ro[tx_ssb->nb_mapped_ro] = ro_p; - tx_ssb->nb_mapped_ro++; - LOG_D(NR_MAC, - "Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n" - "Nb mapped ROs for this ssb idx: in the association period only %u\n", - ssb_idx, - ro_p->slot, - ro_p->start_symbol, - slot, - ro_in_time, - ro_in_freq, - slot_map->nb_of_prach_occasion_in_freq, - tx_ssb->nb_mapped_ro); - // If all the required SSBs are mapped to this RO, exit the loop of SSBs - if (ro_p->nb_mapped_ssb == ssb_rach_ratio) { - idx++; - break; - } - } - done = MAX_NB_SSB == idx; - } - } - } - } - } - } - } else { - int frame = 0; - int slot = 0; - int ro_in_time = 0; - int ro_in_freq = 0; - prach_association_period_t *end = prach_assoc_pattern->prach_association_period_list + prach_assoc_pattern->nb_of_assoc_period; - for (prach_association_period_t *prach_period = prach_assoc_pattern->prach_association_period_list; prach_period < end; - prach_period++) { - // Go through the list of transmitted SSBs - for (int idx = 0; idx < ssb_list->nb_tx_ssb; idx++) { - ssb_info_t *tx_ssb = ssb_list->tx_ssb + idx; - uint8_t nb_mapped_ro_in_association_period = 0; // Reset the nb of mapped ROs for the new SSB index - bool done = false; - // Map all the required ROs to this SSB - // Go through the list of PRACH config periods within this association period - for (int i = 0; i < prach_period->nb_of_prach_conf_period && !done; i++, prach_configuration_period_idx++) { - // Build the association period with its association PRACH Configuration indexes - prach_period->prach_conf_period_list[i] = &prach_assoc_pattern->prach_conf_period_list[prach_configuration_period_idx]; - prach_conf_period_t *prach_conf = prach_period->prach_conf_period_list[i]; - for (; frame < prach_conf->nb_of_frame; frame++) { - for (; slot < prach_conf->nb_of_slot; slot++) { - prach_occasion_slot_t *slot_map = &prach_conf->prach_occasion_slot_map[frame][slot]; - for (; ro_in_time < slot_map->nb_of_prach_occasion_in_time; ro_in_time++) { - for (; ro_in_freq < slot_map->nb_of_prach_occasion_in_freq; ro_in_freq++) { - prach_occasion_info_t *ro_p = - slot_map->prach_occasion + ro_in_time * slot_map->nb_of_prach_occasion_in_freq + ro_in_freq; - int ssb_idx = get_ssb_idx_from_list(ssb_list, idx); - ro_p->mapped_ssb_idx[0] = ssb_idx; - ro_p->nb_mapped_ssb = 1; - AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > tx_ssb->nb_mapped_ro + 1, - "Too many mapped ROs (%d) to a single SSB\n", - tx_ssb->nb_mapped_ro); - tx_ssb->mapped_ro[tx_ssb->nb_mapped_ro] = ro_p; - tx_ssb->nb_mapped_ro++; - nb_mapped_ro_in_association_period++; - - LOG_D(NR_MAC, - "Mapped ssb_idx %u to RO slot-symbol %u-%u-%u, %u-%u-%u-%u/%u\n" - "Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", - ssb_idx, - ro_p->frame, - ro_p->slot, - ro_p->start_symbol, - frame, - slot, - ro_in_time, - ro_in_freq, - slot_map->nb_of_prach_occasion_in_freq, - tx_ssb->nb_mapped_ro, - nb_mapped_ro_in_association_period); - - // Exit the loop if this SSB has been mapped to all the required ROs - // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an - // association period: - // this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) { - ro_in_freq++; - break; - } - } - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) - break; - else - ro_in_freq = 0; - } - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) - break; - else - ro_in_time = 0; - } - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) - break; - else - slot = 0; - } - if (nb_mapped_ro_in_association_period == ssb_rach_ratio) - break; - else - frame = 0; - } - } - } - } -} - -// Build the SSB to RO mapping upon RRC configuration update -void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac) -{ - // Clear all the lists and maps - const int bwp_id = mac->current_UL_BWP->bwp_id; - free_rach_structures(mac, bwp_id); - - memset(&mac->prach_assoc_pattern[bwp_id], 0, sizeof(prach_association_pattern_t)); - - // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config - LOG_D(NR_MAC,"Build RO list\n"); - build_ro_list(mac); - - // Map the transmitted SSBs to the ROs and create the association pattern according to the config - LOG_D(NR_MAC,"Map SSB to RO\n"); - map_ssb_to_ro(mac); - LOG_D(NR_MAC,"Map SSB to RO done\n"); -} - static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, From 878bbc65ad0083ca0ff0d5a9acc7a262355b60bc Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 2 Dec 2024 10:11:28 +0100 Subject: [PATCH 16/34] assertion for handling of RO mask --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 7996980884..df9290ec3b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -418,6 +418,9 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) // setting the RA ssb value as the progressive number of SSB transmitted // non-transmitted SSBs are not taken into account ra->ra_ssb = mac->ssb_list.nb_ssb_per_index[ssb]; + + // TODO not sure how to handle the RO mask when it is limiting the RO occasions + AssertFatal(ra->ro_mask_index <= 0, "Handling of RACH occasion masking indication not implemented\n"); } static bool check_mixed_slot_prach(frame_structure_t *fs, int slot, int start_prach, int end_prach) From 108fdae15904ab34ed2c97ae0f95ee7f019ad9f4 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 2 Dec 2024 11:30:48 +0100 Subject: [PATCH 17/34] removing unnecessary nr_Msg1_transmitted function --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 15 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 1 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 270 +++++++++---------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 112 +++----- 4 files changed, 166 insertions(+), 232 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 8536e4a081..ddb522dfb5 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -273,8 +273,6 @@ static const char *const nrra_ue_text[] = {"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_MSGB", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"}; typedef struct { - /// PRACH format retrieved from prach_ConfigIndex - uint16_t prach_format; /// Preamble Tx Counter uint8_t preamble_tx_counter; /// Preamble Power Ramping Counter @@ -282,9 +280,7 @@ typedef struct { /// 2-step RA power offset int power_offset_2step; /// Target received power at gNB. Baseline is range -202..-60 dBm. Depends on delta preamble, power ramping counter and step. - int ra_PREAMBLE_RECEIVED_TARGET_POWER; - /// PRACH index for TDD (0 ... 6) depending on TDD configuration and prachConfigIndex - uint8_t ra_TDD_map_index; + int ra_preamble_rx_target_power; /// RA Preamble Power Ramping Step in dB uint32_t preamble_power_ramping_step; uint8_t preamble_backoff; @@ -329,8 +325,6 @@ typedef struct { uint16_t MsgB_rnti; /// Temporary CRNTI uint16_t t_crnti; - /// number of attempt for rach - uint8_t RA_attempt_number; /// Random-access procedure flag bool RA_active; /// Random-access preamble index @@ -361,9 +355,9 @@ typedef struct { uint8_t *Msg3_buffer; // initial Random Access Preamble power int preambleRxTargetPower; - int deltaPreamble; + int msg3_deltaPreamble; bool msg3_C_RNTI; - + int preambleReceivedTargetPower_config; /// Random-access Contention Resolution Timer NR_timer_t contention_resolution_timer; /// Transmitted UE Contention Resolution Identifier @@ -373,6 +367,9 @@ typedef struct { NR_PRACH_RESOURCES_t prach_resources; + bool new_ssb; + int num_fd_occasions; + int ra_config_index; ssb_ro_preambles_t ssb_ro_config; int association_periods; prach_occasion_info_t sched_ro_info; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 848cbce9b1..6d2c7a1efd 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -336,7 +336,6 @@ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id); int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac); void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); -void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order); void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index df9290ec3b..9a4caa7038 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -38,13 +38,12 @@ #include "LAYER2/NR_MAC_UE/mac_proto.h" #include #include "openair2/LAYER2/RLC/rlc.h" -#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; int16_t pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); - int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER + pathloss); + int16_t ra_preamble_rx_power = (int16_t)(ra->prach_resources.ra_preamble_rx_target_power + pathloss); return min(ra->prach_resources.Pc_max, ra_preamble_rx_power); } @@ -177,7 +176,7 @@ static void select_preamble_group(NR_UE_MAC_INST_t *mac) // if the pathloss is less than PCMAX (of the Serving Cell performing the Random Access Procedure) // – preambleReceivedTargetPower – msg3-DeltaPreamble – messagePowerOffsetGroupB int groupB_pow_offset = get_messagePowerOffsetGroupB(groupB->messagePowerOffsetGroupB); - int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->deltaPreamble - groupB_pow_offset; + int PLThreshold = ra->prach_resources.Pc_max - ra->preambleRxTargetPower - ra->msg3_deltaPreamble - groupB_pow_offset; int pathloss = compute_nr_SSB_PL(mac, mac->ssb_measurements.ssb_rsrp_dBm); // TODO if the Random Access procedure was initiated for the CCCH logical channel and the CCCH SDU size // plus MAC subheader is greater than ra-Msg3SizeGroupA @@ -350,8 +349,7 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) nb_of_preambles); } -// 38.321 Section 5.1.2 Random Access Resource selection -static void ra_resource_selection(NR_UE_MAC_INST_t *mac) +static void configure_ra_preamble(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; int ssb = -1; // init as not selected @@ -414,10 +412,12 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) config_preamble_index(mac); } } - AssertFatal(ra->ra_ssb >= 0, "Something wrong! RA resource selection didn't set any SSB\n"); + AssertFatal(ssb >= 0, "Something wrong! RA resource selection didn't set any SSB\n"); // setting the RA ssb value as the progressive number of SSB transmitted // non-transmitted SSBs are not taken into account - ra->ra_ssb = mac->ssb_list.nb_ssb_per_index[ssb]; + int ssb_idx = mac->ssb_list.nb_ssb_per_index[ssb]; + ra->new_ssb = ssb != ssb_idx ? true : false; + ra->ra_ssb = ssb_idx; // TODO not sure how to handle the RO mask when it is limiting the RO occasions AssertFatal(ra->ro_mask_index <= 0, "Handling of RACH occasion masking indication not implemented\n"); @@ -473,13 +473,13 @@ static void select_prach_occasion(RA_config_t *ra, ra->sched_ro_info.association_period_idx = ass_period_idx; } -static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_index, int num_fd_occasions, int scs) +static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int scs) { RA_config_t *ra = &mac->ra; int num_ra_occasions_period = 0; frame_structure_t *fs = &mac->frame_structure; - nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(prach_config_index, mac->frequency_range, fs->frame_type); - int max_num_occasions = prach_info.N_RA_sfn * prach_info.N_t_slot * prach_info.N_RA_slot * num_fd_occasions; + nr_prach_info_t prach_info = get_nr_prach_occasion_info_from_index(ra->ra_config_index, mac->frequency_range, fs->frame_type); + int max_num_occasions = prach_info.N_RA_sfn * prach_info.N_t_slot * prach_info.N_RA_slot * ra->num_fd_occasions; prach_occasion_info_t ra_occasions_period[max_num_occasions]; // Number of PRACH slots within a subframe (or 60kHz slot) to be taken into account only for 30 and 120kHz // as defined in 5.3.2 of 211 @@ -505,19 +505,23 @@ static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_in if (!is_ul_slot(slot, fs)) continue; // valid PRACH occasion only if slot is UL for (int t = 0; t < prach_info.N_t_slot; t++) { // td occasions within a slot + // see 5.3.2 in 211 + int temp_format = prach_info.format >> 8; // B1, B2 or B3 if A1/B1, A2/B2 or A3/B3 formats in tables + if (t != prach_info.N_t_slot - 1 || temp_format == 0xff) + temp_format = prach_info.format & 0xff; int start_symbol = prach_info.start_symbol + t * prach_info.N_dur; int end_symbol = start_symbol + prach_info.N_dur; // valid occasion only if PRACH symbols are UL symbols in mixed slot if (fs->frame_type == TDD && !check_mixed_slot_prach(fs, slot, start_symbol, end_symbol)) continue; - for (int f = 0; f < num_fd_occasions; f++) { // fd occasions + for (int f = 0; f < ra->num_fd_occasions; f++) { // fd occasions ra_occasions_period[num_ra_occasions_period] = (prach_occasion_info_t){.slot = slot, .frame_info[0] = prach_info.x, .frame_info[1] = n == 0 ? prach_info.y : prach_info.y2, .start_symbol = start_symbol, .fdm = f, - .format = prach_info.format}; + .format = temp_format}; LOG_D(NR_MAC, "RA occasion %d: slot %d start symbol %d fd occasion %d\n", num_ra_occasions_period, @@ -555,6 +559,87 @@ static void configure_prach_occasions(NR_UE_MAC_INST_t *mac, int prach_config_in select_prach_occasion(ra, mac->ssb_list.nb_tx_ssb, max_num_occasions, ra_occasions_period, num_ra_occasions_period); } +/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ +static int nr_get_delta_preamble(int scs, int prach_format) +{ + int delta = 0; + switch (prach_format) { + case 0: + case 3: + delta = 0; + break; + case 1: + delta = -3; + break; + case 2: + delta = -6; + break; + case 0xa1: + case 0xb1: + delta = 8 + 3 * scs; + break; + case 0xa2: + case 0xb2: + case 0xc2: + delta = 5 + 3 * scs; + break; + case 0xa3: + case 0xb3: + delta = 3 + 3 * scs; + break; + case 0xb4: + delta = 3 * scs; + break; + case 0xc0: + delta = 11 + 3 * scs; + break; + default: + AssertFatal(false, "Invalid preamble format %x\n", prach_format); + } + return delta; +} + +static int get_ra_preamble_rx_target_power(RA_config_t *ra, int scs) +{ + NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; + int delta_preamble = nr_get_delta_preamble(scs, ra->sched_ro_info.format); + int tp = ra->preambleReceivedTargetPower_config + delta_preamble + prach_resources->power_offset_2step; + tp += (prach_resources->preamble_power_ramping_cnt - 1) * prach_resources->preamble_power_ramping_step; + return tp; +} + +// 38.321 Sections 5.1.3 and .3a +static void ra_preamble_msga_transmission(RA_config_t *ra, int scs) +{ + NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; + if (prach_resources->preamble_tx_counter > 1) { + // TODO if the notification of suspending power ramping counter has not been received from lower layers (not implemented) + // this happens if the L1 does not transmit PRACH of if the spacial filter changed (UE transmitting in another beam) + // TODO if LBT failure indication was not received from lower layers (LBT not implemented) + // if SSB or CSI-RS selected is not changed from the selection in the last Random Access Preamble transmission + if (!ra->new_ssb) + prach_resources->preamble_power_ramping_cnt++; + } + + + prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(ra, scs); + + ra->ra_rnti = nr_get_ra_rnti(ra->sched_ro_info.start_symbol, ra->sched_ro_info.slot, ra->sched_ro_info.fdm, 0); + if (ra->ra_type == RA_2_STEP) + ra->MsgB_rnti = nr_get_MsgB_rnti(ra->sched_ro_info.start_symbol, ra->sched_ro_info.slot, ra->sched_ro_info.fdm, 0); +} + +// 38.321 Section 5.1.2 Random Access Resource selection +static void ra_resource_selection(NR_UE_MAC_INST_t *mac) +{ + configure_ra_preamble(mac); + const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; + const int ul_mu = mac->current_UL_BWP->scs; + const int mu = nr_get_prach_or_ul_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, current_UL_BWP->rach_ConfigCommon, ul_mu); + configure_prach_occasions(mac, mu); + ra_preamble_msga_transmission(&mac->ra, mu); +} + // Random Access procedure initialization as per 5.1.1 and initialization of variables specific // to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) bool init_RA(NR_UE_MAC_INST_t *mac, int frame) @@ -743,6 +828,11 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) prach_resources->scaling_factor_bi = 1; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreambleReceivedTargetPower_r16) + ra->preambleReceivedTargetPower_config = *twostep_generic->msgA_PreambleReceivedTargetPower_r16; + else + ra->preambleReceivedTargetPower_config = rach_ConfigGeneric->preambleReceivedTargetPower; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->preambleTransMax_r16) set_preambleTransMax(ra, *twostep_generic->preambleTransMax_r16); else @@ -769,159 +859,39 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) && current_UL_BWP->msgA_ConfigCommon_r16 && current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16 && current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16) - ra->deltaPreamble = *current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16 << 1; + ra->msg3_deltaPreamble = *current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_DeltaPreamble_r16 << 1; else - ra->deltaPreamble = mac->current_UL_BWP->msg3_DeltaPreamble ? *mac->current_UL_BWP->msg3_DeltaPreamble << 1 : 0; + ra->msg3_deltaPreamble = mac->current_UL_BWP->msg3_DeltaPreamble ? *mac->current_UL_BWP->msg3_DeltaPreamble << 1 : 0; ra->RA_RAPID_found = 0; ra->RA_backoff_cnt = 0; ra->RA_window_cnt = -1; + ra->new_ssb = false; - int ra_config_index = 0; if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PRACH_ConfigurationIndex_r16) - ra_config_index = *twostep_generic->msgA_PRACH_ConfigurationIndex_r16; + ra->ra_config_index = *twostep_generic->msgA_PRACH_ConfigurationIndex_r16; else { if (rach_ConfigGeneric->ext1 && rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610) - ra_config_index = *rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610; + ra->ra_config_index = *rach_ConfigGeneric->ext1->prach_ConfigurationIndex_v1610; else - ra_config_index = rach_ConfigGeneric->prach_ConfigurationIndex; + ra->ra_config_index = rach_ConfigGeneric->prach_ConfigurationIndex; } - int fdm = 0; + if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_RO_FDM_r16) - fdm = 1 << *twostep_generic->msgA_RO_FDM_r16; + ra->num_fd_occasions = 1 << *twostep_generic->msgA_RO_FDM_r16; else - fdm = 1 << rach_ConfigGeneric->msg1_FDM; - configure_prach_occasions(mac, ra_config_index, fdm, prach_scs); + ra->num_fd_occasions = 1 << rach_ConfigGeneric->msg1_FDM; + return true; } -/* TS 38.321 subclause 7.3 - return DELTA_PREAMBLE values in dB */ -static int8_t nr_get_DELTA_PREAMBLE(const NR_UE_MAC_INST_t *mac, uint16_t prach_format) -{ - const NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - int prach_sequence_length = nr_rach_ConfigCommon->prach_RootSequenceIndex.present - 1; - - // Preamble formats given by prach_ConfigurationIndex and tables 6.3.3.2-2 and 6.3.3.2-2 in TS 38.211 - unsigned int prachConfigIndex = nr_rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - - if (prach_sequence_length == 0) { - AssertFatal(prach_format < 4, "Illegal PRACH format %d for sequence length 839\n", prach_format); - switch (prach_format) { - - // long preamble formats - case 0: - case 3: - return 0; - - case 1: - return -3; - - case 2: - return -6; - - default: - AssertFatal(1 == 0, "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", - mac->ue_id, - prach_format, - prachConfigIndex); - } - } else { - // SCS configuration from msg1_SubcarrierSpacing and table 4.2-1 in TS 38.211 - AssertFatal(nr_rach_ConfigCommon->msg1_SubcarrierSpacing, "msg1_SubcarrierSpacing required but missing\n"); - NR_SubcarrierSpacing_t scs = *nr_rach_ConfigCommon->msg1_SubcarrierSpacing; - AssertFatal(scs >= NR_SubcarrierSpacing_kHz15 && scs <= NR_SubcarrierSpacing_spare1, "Unknown msg1_SubcarrierSpacing %lu\n", scs); - const unsigned int mu = scs; - switch (prach_format) { // short preamble formats - case 0: - case 3: - return 8 + 3 * mu; - - case 1: - case 4: - case 8: - return 5 + 3 * mu; - - case 2: - case 5: - return 3 + 3 * mu; - - case 6: - return 3 * mu; - - case 7: - return 5 + 3 * mu; - - default: - AssertFatal(false, - "[UE %d] ue_procedures.c: FATAL, Illegal preambleFormat %d, prachConfigIndex %d\n", - mac->ue_id, - prach_format, - prachConfigIndex); - } - } - return 0; -} - -// TS 38.321 subclause 5.1.3 - RA preamble transmission - ra_PREAMBLE_RECEIVED_TARGET_POWER configuration -// Measurement units: -// - preambleReceivedTargetPower dBm (-202..-60, 2 dBm granularity) -// - delta_preamble dB -// - RA_PREAMBLE_POWER_RAMPING_STEP dB -// - POWER_OFFSET_2STEP_RA dB -// returns receivedTargerPower in dBm -static int nr_get_Po_NOMINAL_PUSCH(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources) -{ - int8_t receivedTargerPower; - int8_t delta_preamble; - - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; - delta_preamble = nr_get_DELTA_PREAMBLE(mac, prach_resources->prach_format); - - receivedTargerPower = preambleReceivedTargetPower + - delta_preamble + - (prach_resources->preamble_power_ramping_cnt - 1) * prach_resources->preamble_power_ramping_step + - prach_resources->power_offset_2step; - - LOG_D(MAC, "ReceivedTargerPower is %d dBm \n", receivedTargerPower); - return receivedTargerPower; -} - -// This routine implements Section 5.1.2 (UE Random Access Resource Selection) -// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321 -// - currently the PRACH preamble is set through RRC configuration for 4-step CFRA mode -// todo: -// - determine next available PRACH occasion -// -- if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured -// -- else if SSB is selected above -// -- else if CSI-RS is selected above -// - switch initialisation cases -// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321) -// --- SSB selection, set ra_PreambleIndex -// -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 -// --- set PREAMBLE_INDEX to ra_preamble_index -// --- select the SSB signalled by PDCCH -// -- RA initiated for SI request: -// --- SSB selection, set ra_PreambleIndex -// - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321) -// - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission -// - Contention-based RA preamble selection: -// -- selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB -static void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, - NR_PRACH_RESOURCES_t *prach_resources, - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated) +static void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources) { + const int ul_mu = mac->current_UL_BWP->scs; + const int mu = nr_get_prach_or_ul_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, mac->current_UL_BWP->rach_ConfigCommon, ul_mu); if (prach_resources->preamble_tx_counter > 1) prach_resources->preamble_power_ramping_cnt++; - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources); -} - -// TbD: RA_attempt_number not used -void nr_Msg1_transmitted(NR_UE_MAC_INST_t *mac) -{ - RA_config_t *ra = &mac->ra; - ra->ra_state = nrRA_WAIT_RAR; - ra->RA_attempt_number++; + prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(&mac->ra, mu); } void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id) @@ -1028,8 +998,8 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx) { RA_config_t *ra = &mac->ra; - NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = ra->rach_ConfigDedicated; NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; + if (ra->ra_state == nrRA_UE_IDLE) { bool init_success = init_RA(mac, frame); if (!init_success) @@ -1072,7 +1042,7 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, // Fill in preamble and PRACH resources ra->RA_window_cnt--; if (ra->ra_state == nrRA_GENERATE_PREAMBLE) { - nr_get_prach_resources(mac, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mac, prach_resources); } } else if (ra->RA_backoff_cnt > 0) { @@ -1081,7 +1051,7 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, ra->RA_backoff_cnt--; if ((ra->RA_backoff_cnt > 0 && ra->ra_state == nrRA_GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) { - nr_get_prach_resources(mac, prach_resources, rach_ConfigDedicated); + nr_get_prach_resources(mac, prach_resources); } } } @@ -1288,7 +1258,7 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->preamble_backoff + 1); prach_resources->preamble_tx_counter = 1; prach_resources->preamble_power_ramping_step += 2; // 2 dB increment - prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources); + prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(ra, mac->current_UL_BWP->scs); } else { nr_get_RA_window(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 85a6cd5942..d4d4aa3a4d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2083,10 +2083,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t return; } - uint16_t format = prach_occasion_info->format; - uint16_t format0 = format & 0xff; // single PRACH format - uint16_t format1 = (format >> 8) & 0xff; // dual PRACH format - + int format = prach_occasion_info->format; fapi_nr_prach_config_t *prach_config = &mac->phy_config.config_req.prach_config; pdu->prach_config_pdu = (fapi_nr_ul_config_prach_pdu){ .phys_cell_id = mac->physCellId, @@ -2094,7 +2091,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t .prach_slot = prach_occasion_info->slot, .prach_start_symbol = prach_occasion_info->start_symbol, .num_ra = prach_occasion_info->fdm, - .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format0, ra->restricted_set_config), + .num_cs = get_NCS(ra->zeroCorrelationZoneConfig, format, ra->restricted_set_config), .root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].prach_root_sequence_index, .restricted_set = prach_config->restricted_set_config, .freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info->fdm].k1}; @@ -2106,72 +2103,46 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t pdu->prach_config_pdu.prach_start_symbol, pdu->prach_config_pdu.num_ra); - if (format1 != 0xff) { - switch (format0) { // dual PRACH format - case 0xa1: - pdu->prach_config_pdu.prach_format = 11; - break; - case 0xa2: - pdu->prach_config_pdu.prach_format = 12; - break; - case 0xa3: - pdu->prach_config_pdu.prach_format = 13; - break; - default: - AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format"); - } - } else { - switch (format0) { // single PRACH format - case 0: - pdu->prach_config_pdu.prach_format = 0; - break; - case 1: - pdu->prach_config_pdu.prach_format = 1; - break; - case 2: - pdu->prach_config_pdu.prach_format = 2; - break; - case 3: - pdu->prach_config_pdu.prach_format = 3; - break; - case 0xa1: - pdu->prach_config_pdu.prach_format = 4; - break; - case 0xa2: - pdu->prach_config_pdu.prach_format = 5; - break; - case 0xa3: - pdu->prach_config_pdu.prach_format = 6; - break; - case 0xb1: - pdu->prach_config_pdu.prach_format = 7; - break; - case 0xb4: - pdu->prach_config_pdu.prach_format = 8; - break; - case 0xc0: - pdu->prach_config_pdu.prach_format = 9; - break; - case 0xc2: - pdu->prach_config_pdu.prach_format = 10; - break; - default: - AssertFatal(1 == 0, "Invalid PRACH format"); - } - } // if format1 + switch (format) { // single PRACH format + case 0: + pdu->prach_config_pdu.prach_format = 0; + break; + case 1: + pdu->prach_config_pdu.prach_format = 1; + break; + case 2: + pdu->prach_config_pdu.prach_format = 2; + break; + case 3: + pdu->prach_config_pdu.prach_format = 3; + break; + case 0xa1: + pdu->prach_config_pdu.prach_format = 4; + break; + case 0xa2: + pdu->prach_config_pdu.prach_format = 5; + break; + case 0xa3: + pdu->prach_config_pdu.prach_format = 6; + break; + case 0xb1: + pdu->prach_config_pdu.prach_format = 7; + break; + case 0xb4: + pdu->prach_config_pdu.prach_format = 8; + break; + case 0xc0: + pdu->prach_config_pdu.prach_format = 9; + break; + case 0xc2: + pdu->prach_config_pdu.prach_format = 10; + break; + default: + AssertFatal(false, "Invalid PRACH format"); + } pdu->prach_config_pdu.ra_PreambleIndex = ra->ra_PreambleIndex; pdu->prach_config_pdu.prach_tx_power = get_prach_tx_power(mac); - unsigned int slot_RA; - // 3GPP TS 38.321 Section 5.1.3 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. - if (pdu->prach_config_pdu.prach_format < 4) { - unsigned int slots_per_sf = (1 << mac->current_UL_BWP->scs); - slot_RA = pdu->prach_config_pdu.prach_slot / slots_per_sf; - } else { - slot_RA = pdu->prach_config_pdu.prach_slot; - } - mac->ra.ra_rnti = nr_get_ra_rnti(pdu->prach_config_pdu.prach_start_symbol, slot_RA, pdu->prach_config_pdu.num_ra, 0); release_ul_config(pdu, false); nr_scheduled_response_t scheduled_response = {.ul_config = mac->ul_config_request + slotP, .mac = mac, @@ -2184,7 +2155,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t T_INT(pdu->prach_config_pdu.ra_PreambleIndex), T_INT(pdu->prach_config_pdu.prach_tx_power)); if (ra->ra_type == RA_4_STEP) { - nr_Msg1_transmitted(mac); + ra->ra_state = nrRA_WAIT_RAR; } else if (ra->ra_type == RA_2_STEP) { NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; @@ -2217,9 +2188,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t remove_ul_config_last_item(pdu); release_ul_config(pdu, false); - // Compute MsgB RNTI - ra->MsgB_rnti = - nr_get_MsgB_rnti(prach_occasion_info->start_symbol, slot_RA, prach_occasion_info->fdm, 0); LOG_D(NR_MAC, "ra->ra_state %s\n", nrra_ue_text[ra->ra_state]); ra->ra_state = nrRA_WAIT_MSGB; ra->t_crnti = 0; From cc154da549727cb2923b238176ae34e41218ab67 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Dec 2024 14:09:34 +0100 Subject: [PATCH 18/34] Procedures for Random Access Response reception --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 21 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 7 +- openair2/LAYER2/NR_MAC_UE/mac_tables.c | 24 -- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 402 ++++++++++-------- .../NR_MAC_UE/nr_ue_dci_configuration.c | 6 + .../LAYER2/NR_MAC_UE/nr_ue_power_procedures.c | 4 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 307 ++++++------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 12 +- .../tests/test_nr_ue_power_procedures.cpp | 14 +- .../tests/test_nr_ue_ra_procedures.cpp | 2 + openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 5 +- 11 files changed, 420 insertions(+), 384 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index ddb522dfb5..95df46fb72 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -283,8 +283,6 @@ typedef struct { int ra_preamble_rx_target_power; /// RA Preamble Power Ramping Step in dB uint32_t preamble_power_ramping_step; - uint8_t preamble_backoff; - uint8_t scaling_factor_bi; /// UE configured maximum output power int Pc_max; } NR_PRACH_RESOURCES_t; @@ -310,8 +308,6 @@ typedef struct { bool cfra; /// RA type nr_ra_type_t ra_type; - /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. - uint8_t RA_offset; /// MsgB SuccessRAR MAC subheader int8_t MsgB_R; int8_t MsgB_CH_ACESS_CPEXT; @@ -333,18 +329,15 @@ typedef struct { int restricted_set_config; // selected SSB for RACH (not the SSB-Index but the cumulative index, excluding not trasmitted SSBs) int ra_ssb; - /// Random-access window counter - int16_t RA_window_cnt; - /// Flag to monitor if matching RAPID was received in RAR - uint8_t RA_RAPID_found; - /// Flag to monitor if BI was received in RAR - uint8_t RA_BI_found; - /// Random-access backoff counter - int16_t RA_backoff_indicator; + /// Random-access response window timer + NR_timer_t response_window_timer; + bool start_response_window; + /// Random-access backoff timer + NR_timer_t RA_backoff_timer; + int RA_backoff_limit; + uint8_t scaling_factor_bi; /// Flag to indicate whether preambles Group A is selected bool RA_GroupA; - /// RA backoff counter - int16_t RA_backoff_cnt; /// RA max number of preamble transmissions int preambleTransMax; /// Received TPC command (in dB) from RAR diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 6d2c7a1efd..2157a6c1c8 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -212,7 +212,6 @@ void set_harq_status(NR_UE_MAC_INST_t *mac, bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); initial_pucch_resource_t get_initial_pucch_resource(const int idx); void multiplex_pucch_resource(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, int num_res); -uint32_t get_backoff_indicator(int idx); int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac, int scs, NR_PUCCH_Config_t *pucch_Config, @@ -307,10 +306,6 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); -int16_t nr_get_RA_window_2Step(const NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16); - -int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon); - void nr_get_RA_window(NR_UE_MAC_INST_t *mac); /*@mac pointer to MAC instance @@ -336,6 +331,8 @@ NR_UE_L2_STATE_t nr_ue_get_sync_state(module_id_t mod_id); int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac); void schedule_RA_after_SR_failure(NR_UE_MAC_INST_t *mac); +void nr_rar_not_successful(NR_UE_MAC_INST_t *mac); +void ra_resource_selection(NR_UE_MAC_INST_t *mac); void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id); void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order); void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_tables.c b/openair2/LAYER2/NR_MAC_UE/mac_tables.c index bd4cc6d8f3..a313600609 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_tables.c +++ b/openair2/LAYER2/NR_MAC_UE/mac_tables.c @@ -412,30 +412,6 @@ static const uint8_t table_7_3_2_3_3_4_twoCodeword[6][14] = { {2,1,1,1,1,0,0,1,1,1,1,0,0,2}, }; -// table 7.2-1 TS 38.321 -static const uint32_t table_7_2_1[16] = { - 5, // row index 0 - 10, // row index 1 - 20, // row index 2 - 30, // row index 3 - 40, // row index 4 - 60, // row index 5 - 80, // row index 6 - 120, // row index 7 - 160, // row index 8 - 240, // row index 9 - 320, // row index 10 - 480, // row index 11 - 960, // row index 12 - 1920, // row index 13 -}; - -uint32_t get_backoff_indicator(int idx) -{ - AssertFatal(idx < 16, "Backoff indicator index %d exeeding table size\n", idx); - return table_7_2_1[idx]; -} - static inline uint16_t packBits(const uint8_t *toPack, const int nb) { int res = 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 9a4caa7038..02afecec81 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -450,7 +450,7 @@ static void select_prach_occasion(RA_config_t *ra, seed = 1; } else { // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int) - seed = (unsigned int) (rdtsc_oai() & ~0); + seed = (unsigned int)(rdtsc_oai() & ~0); } int num_ros_per_ssb = 0; @@ -630,7 +630,7 @@ static void ra_preamble_msga_transmission(RA_config_t *ra, int scs) } // 38.321 Section 5.1.2 Random Access Resource selection -static void ra_resource_selection(NR_UE_MAC_INST_t *mac) +void ra_resource_selection(NR_UE_MAC_INST_t *mac) { configure_ra_preamble(mac); const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; @@ -640,6 +640,189 @@ static void ra_resource_selection(NR_UE_MAC_INST_t *mac) ra_preamble_msga_transmission(&mac->ra, mu); } +static int nr_get_RA_window_2Step_v17(long msgB_ResponseWindow) +{ + switch (msgB_ResponseWindow) { + case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl240: + return 240; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl640: + return 640; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl960: + return 960; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl1280: + return 1280; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl1920: + return 1920; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__ext1__msgB_ResponseWindow_v1700_sl2560: + return 2590; + default: + AssertFatal(false, "illegal msgB_responseWindow value %ld\n", msgB_ResponseWindow); + break; + } + return 0; +} + +static int nr_get_RA_window_2Step_v16(long msgB_ResponseWindow) +{ + switch (msgB_ResponseWindow) { + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl1: + return 1; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl2: + return 2; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl4: + return 4; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl8: + return 8; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl10: + return 10; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl20: + return 20; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl40: + return 40; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl80: + return 80; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl160: + return 160; + break; + case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl320: + return 360; + break; + default: + AssertFatal(false, "illegal msgB_responseWindow value %ld\n", msgB_ResponseWindow); + break; + } + return 0; +} + +static int nr_get_RA_window_4Step_v16(long ra_ResponseWindow) +{ + switch (ra_ResponseWindow) { + case NR_RACH_ConfigGeneric__ext1__ra_ResponseWindow_v1610_sl60: + return 60; + case NR_RACH_ConfigGeneric__ext1__ra_ResponseWindow_v1610_sl160: + return 160; + default: + AssertFatal(false, "illegal ra_ResponseWindow value %ld\n", ra_ResponseWindow); + } + return 0; +} + +static int nr_get_RA_window_4Step_v17(long ra_ResponseWindow) +{ + switch (ra_ResponseWindow) { + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl240: + return 240; + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl320: + return 320; + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl640: + return 640; + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl960: + return 960; + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl1280: + return 1280; + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl1920: + return 1920; + case NR_RACH_ConfigGeneric__ext2__ra_ResponseWindow_v1700_sl2560: + return 2590; + default: + AssertFatal(false, "illegal msgB_responseWindow value %ld\n", ra_ResponseWindow); + } + return 0; +} + +static int nr_get_RA_window_4Step(long ra_ResponseWindow) +{ + switch (ra_ResponseWindow) { + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: + return 1; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: + return 2; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: + return 4; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: + return 8; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: + return 10; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: + return 20; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: + return 40; + break; + case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: + return 80; + break; + default: + AssertFatal(false, "illegal ra_ResponseWindow value %ld\n", ra_ResponseWindow); + break; + } + return 0; +} + +static void setup_ra_response_window(RA_config_t *ra, + int slots_per_frame, + NR_NTN_Config_r17_t *ntn_Config_r17, + NR_RACH_ConfigGeneric_t *configGeneric, + NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep, + ntn_timing_advance_componets_t *ntn_ta) +{ + int respwind_value = 0; + if (ra->ra_type == RA_2_STEP) { + long *msgB_ResponseWindow = twostep->msgB_ResponseWindow_r16; + if (msgB_ResponseWindow) + respwind_value = nr_get_RA_window_2Step_v16(*msgB_ResponseWindow); + if (twostep->ext1 && twostep->ext1->msgB_ResponseWindow_v1700) { + AssertFatal(msgB_ResponseWindow == NULL, + "The network does not configure msgB-ResponseWindow-r16 simultaneously with msgB-ResponseWindow-v1700\n"); + msgB_ResponseWindow = twostep->ext1->msgB_ResponseWindow_v1700; + if (msgB_ResponseWindow) + respwind_value = nr_get_RA_window_2Step_v17(*msgB_ResponseWindow); + } + // The network configures a value lower than or equal to 40ms + int slots_40ms = 4 * slots_per_frame; + AssertFatal(respwind_value != 0 && respwind_value <= slots_40ms, "Invalid MSGB response window value\n"); + } else { + AssertFatal(ra->ra_type == RA_4_STEP, "Invalid RA type\n"); + long *response_window = NULL; + if (configGeneric->ext1 && configGeneric->ext1->ra_ResponseWindow_v1610) + respwind_value = nr_get_RA_window_4Step_v16(*configGeneric->ext1->ra_ResponseWindow_v1610); + if (configGeneric->ext2 && configGeneric->ext2->ra_ResponseWindow_v1700) { + AssertFatal(response_window == NULL, "ra_ResponseWindow_v1610 and ra_ResponseWindow_v1700 are mutually exclusive\n"); + respwind_value = nr_get_RA_window_4Step_v17(*configGeneric->ext2->ra_ResponseWindow_v1700); + } + if (!response_window) + respwind_value = nr_get_RA_window_4Step(configGeneric->ra_ResponseWindow); + // The network configures a value lower than or equal to 10ms + AssertFatal(respwind_value != 0 && respwind_value <= slots_per_frame, "Invalid RAR response window value\n"); + } + + int ta_Common_slots = 0; + if (ntn_Config_r17) { + const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(ntn_ta); + ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10); + } + + nr_timer_setup(&ra->response_window_timer, respwind_value + ta_Common_slots, 1); +} + // Random Access procedure initialization as per 5.1.1 and initialization of variables specific // to Random Access type as specified in clause 5.1.1a (3GPP TS 38.321 version 16.2.1 Release 16) bool init_RA(NR_UE_MAC_INST_t *mac, int frame) @@ -704,8 +887,6 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) prach_resources->preamble_tx_counter = 1; // set the PREAMBLE_POWER_RAMPING_COUNTER to 1 prach_resources->preamble_power_ramping_cnt = 1; - // set the PREAMBLE_BACKOFF to 0 ms TODO to be set as a timer? - prach_resources->preamble_backoff = 0; // set POWER_OFFSET_2STEP_RA to 0 dB prach_resources->power_offset_2step = 0; @@ -826,7 +1007,7 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) else prach_resources->preamble_power_ramping_step = rach_ConfigGeneric->powerRampingStep << 1; - prach_resources->scaling_factor_bi = 1; + ra->scaling_factor_bi = 1; if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreambleReceivedTargetPower_r16) ra->preambleReceivedTargetPower_config = *twostep_generic->msgA_PreambleReceivedTargetPower_r16; @@ -863,9 +1044,6 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) else ra->msg3_deltaPreamble = mac->current_UL_BWP->msg3_DeltaPreamble ? *mac->current_UL_BWP->msg3_DeltaPreamble << 1 : 0; - ra->RA_RAPID_found = 0; - ra->RA_backoff_cnt = 0; - ra->RA_window_cnt = -1; ra->new_ssb = false; if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PRACH_ConfigurationIndex_r16) @@ -882,18 +1060,16 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) else ra->num_fd_occasions = 1 << rach_ConfigGeneric->msg1_FDM; + setup_ra_response_window(ra, + mac->frame_structure.numb_slots_frame, + mac->sc_info.ntn_Config_r17, + rach_ConfigGeneric, + twostep_generic, + &mac->ntn_ta); + ra->start_response_window = false; return true; } -static void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources) -{ - const int ul_mu = mac->current_UL_BWP->scs; - const int mu = nr_get_prach_or_ul_mu(mac->current_UL_BWP->msgA_ConfigCommon_r16, mac->current_UL_BWP->rach_ConfigCommon, ul_mu); - if (prach_resources->preamble_tx_counter > 1) - prach_resources->preamble_power_ramping_cnt++; - prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(&mac->ra, mu); -} - void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, slot_t slotP, uint8_t gNB_id) { RA_config_t *ra = &mac->ra; @@ -1012,48 +1188,15 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); - if (ra->ra_state < nrRA_SUCCEEDED) { - if (ra->RA_window_cnt != -1) { // RACH is active - - LOG_D(MAC, "[%d.%d] RA is active: RA window count %d, RA backoff count %d\n", frame, nr_slot_tx, ra->RA_window_cnt, ra->RA_backoff_cnt); - - if (ra->RA_BI_found){ - prach_resources->preamble_backoff = prach_resources->scaling_factor_bi * ra->RA_backoff_indicator; - } else { - prach_resources->preamble_backoff = 0; - } - - if (ra->RA_window_cnt >= 0 && ra->RA_RAPID_found == 1) { - - if(ra->cfra) { - // Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213) - nr_ra_succeeded(mac, gNB_id, frame, nr_slot_tx); - } - - } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found && ra->ra_state != nrRA_WAIT_MSGB) { - LOG_W(MAC, "[UE %d][%d:%d] RAR reception failed \n", mac->ue_id, frame, nr_slot_tx); - - nr_ra_failed(mac, CC_id, prach_resources, frame, nr_slot_tx); - - } else if (ra->RA_window_cnt > 0) { - - LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA window count %d) \n", mac->ue_id, frame, nr_slot_tx, ra->RA_window_cnt); - - // Fill in preamble and PRACH resources - ra->RA_window_cnt--; - if (ra->ra_state == nrRA_GENERATE_PREAMBLE) { - nr_get_prach_resources(mac, prach_resources); - } - } else if (ra->RA_backoff_cnt > 0) { - - LOG_D(MAC, "[UE %d][%d.%d]: RAR not received yet (RA backoff count %d) \n", mac->ue_id, frame, nr_slot_tx, ra->RA_backoff_cnt); - - ra->RA_backoff_cnt--; - - if ((ra->RA_backoff_cnt > 0 && ra->ra_state == nrRA_GENERATE_PREAMBLE) || ra->RA_backoff_cnt == 0) { - nr_get_prach_resources(mac, prach_resources); - } - } + if (nr_timer_is_active(&ra->RA_backoff_timer)) { + // if the criteria (as defined in clause 5.1.2) to select contention-free Random Access Resources + // is met during the backoff time + // TODO verify what does this mean + if (ra->cfra) { + // perform the Random Access Resource selection procedure + nr_timer_stop(&ra->RA_backoff_timer); + mac->ra.ra_state = nrRA_GENERATE_PREAMBLE; + ra_resource_selection(mac); } } @@ -1062,102 +1205,6 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, } } -int16_t nr_get_RA_window_2Step(const NR_MsgA_ConfigCommon_r16_t *msgA_ConfigCommon_r16) -{ - int16_t ra_ResponseWindow = *msgA_ConfigCommon_r16->rach_ConfigCommonTwoStepRA_r16 - .rach_ConfigGenericTwoStepRA_r16.msgB_ResponseWindow_r16; - - switch (ra_ResponseWindow) { - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl1: - return 1; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl2: - return 2; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl4: - return 4; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl8: - return 8; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl10: - return 10; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl20: - return 20; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl40: - return 40; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl80: - return 80; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl160: - return 160; - break; - case NR_RACH_ConfigGenericTwoStepRA_r16__msgB_ResponseWindow_r16_sl320: - return 360; - break; - default: - AssertFatal(false, "illegal msgB_responseWindow value %d\n", ra_ResponseWindow); - break; - } - return 0; -} - -int16_t nr_get_RA_window_4Step(const NR_RACH_ConfigCommon_t *rach_ConfigCommon) -{ - int16_t ra_ResponseWindow = rach_ConfigCommon->rach_ConfigGeneric.ra_ResponseWindow; - - switch (ra_ResponseWindow) { - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - return 1; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - return 2; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - return 4; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - return 8; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - return 10; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - return 20; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - return 40; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - return 80; - break; - default: - AssertFatal(false, "illegal ra_ResponseWindow value %d\n", ra_ResponseWindow); - break; - } - return 0; -} - -void nr_get_RA_window(NR_UE_MAC_INST_t *mac) -{ - RA_config_t *ra = &mac->ra; - NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; - AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); - const double ta_Common_ms = GET_COMPLETE_TIME_ADVANCE_MS(&mac->ntn_ta); - int slots_per_frame = mac->frame_structure.numb_slots_frame; - const int slots_per_ms = slots_per_frame / 10; - const int ra_Offset_slots = ra->RA_offset * slots_per_frame; - const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms); - - ra->RA_window_cnt = ra_Offset_slots + ta_Common_slots; // taking into account the 2 frames gap introduced by OAI gNB - - ra->RA_window_cnt += ra->ra_type == RA_2_STEP ? nr_get_RA_window_2Step(mac->current_UL_BWP->msgA_ConfigCommon_r16) - : nr_get_RA_window_4Step(mac->current_UL_BWP->rach_ConfigCommon); -} - //////////////////////////////////////////////////////////////////////////// /////////* Random Access Contention Resolution (5.1.35 TS 38.321) *///////// //////////////////////////////////////////////////////////////////////////// @@ -1188,7 +1235,6 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame if (ra->cfra) { LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CFRA: RAR successfully received.\n", mac->ue_id, frame, slot); - ra->RA_window_cnt = -1; } else if (ra->ra_type == RA_2_STEP) { LOG_A(MAC, "[UE %d][%d.%d][RAPROC] 2-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", @@ -1210,7 +1256,6 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared contention resolution timer...\n", mac->ue_id, frame, slot); } - LOG_D(MAC, "[UE %d] clearing RA_active flag...\n", mac->ue_id); ra->RA_active = false; ra->msg3_C_RNTI = false; ra->ra_state = nrRA_SUCCEEDED; @@ -1219,6 +1264,35 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame nr_mac_rrc_ra_ind(mac->ue_id, frame, true); } +void nr_rar_not_successful(NR_UE_MAC_INST_t *mac) +{ + LOG_W(MAC, "[UE %d] RAR reception failed\n", mac->ue_id); + RA_config_t *ra = &mac->ra; + NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; + prach_resources->preamble_tx_counter++; + bool ra_completed = false; + if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { + // if the Random Access Preamble is transmitted on the SpCell + // TODO to be verified, this means SA if I'm not mistaken + if (IS_SA_MODE(get_softmodem_params())) { + // TODO indicate a Random Access problem to upper layers + } else { + // if the Random Access Preamble is transmitted on an SCell: + // consider the Random Access procedure unsuccessfully completed. + ra_completed = true; + ra->ra_state = nrRA_UE_IDLE; + } + } + if (!ra_completed) { + // select a random backoff time according to a uniform distribution + // between 0 and the PREAMBLE_BACKOFF + uint32_t seed = (unsigned int)(rdtsc_oai() & ~0); + uint32_t random_backoff = rand_r(&seed) % ra->RA_backoff_limit; // in slots + nr_timer_setup(&ra->RA_backoff_timer, random_backoff, 1); + nr_timer_start(&ra->RA_backoff_timer); + } +} + // Handling failure of RA procedure @ MAC layer // according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 // todo: @@ -1226,17 +1300,6 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot) { RA_config_t *ra = &mac->ra; - // Random seed generation - unsigned int seed; - - if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { - // Overwrite seed with non-random seed for IQ player/recorder - seed = 1; - } else { - // & to truncate the int64_t and keep only the LSB bits, up to sizeof(int) - seed = (unsigned int)(rdtsc_oai() & ~0); - } - ra->ra_PreambleIndex = -1; ra->ra_state = nrRA_UE_IDLE; @@ -1255,13 +1318,10 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr slot, ra->preambleTransMax); - ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->preamble_backoff + 1); prach_resources->preamble_tx_counter = 1; prach_resources->preamble_power_ramping_step += 2; // 2 dB increment prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(ra, mac->current_UL_BWP->scs); - } else { - nr_get_RA_window(mac); } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index b2fcab87c3..237838e4dc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -563,6 +563,12 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl if (mac->state == UE_PERFORMING_RA && mac->ra.ra_state >= nrRA_WAIT_RAR) { // if RA is ongoing use RA search space if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) { + // The RA response window starts at the first symbol of the earliest CORESET + // the UE is configured to receive PDCCH for Type1-PDCCH CSS set + if (mac->ra.start_response_window) { + nr_timer_start(&mac->ra.response_window_timer); + mac->ra.start_response_window = false; + } nr_rnti_type_t rnti_type = 0; if (mac->ra.ra_type == RA_4_STEP) { rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c index 0c024560d7..9db464f015 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_power_procedures.c @@ -492,9 +492,7 @@ int get_pusch_tx_power_ue(NR_UE_MAC_INST_t *mac, if (current_UL_BWP->msg3_DeltaPreamble) { DELTA_PREAMBLE_MSG3 = *current_UL_BWP->msg3_DeltaPreamble; } - NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = current_UL_BWP->rach_ConfigCommon; - long preambleReceivedTargetPower = nr_rach_ConfigCommon->rach_ConfigGeneric.preambleReceivedTargetPower; - int P_O_PRE = preambleReceivedTargetPower; + int P_O_PRE = mac->ra.prach_resources.ra_preamble_rx_target_power; P_O_NOMINAL_PUSCH = P_O_PRE + DELTA_PREAMBLE_MSG3; if (has_pusch_power_control_config && pusch_Config->pusch_PowerControl->msg3_Alpha) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 54f047f46d..a77067395f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -59,6 +59,25 @@ // #define DEBUG_MIB // #define ENABLE_MAC_PAYLOAD_DEBUG 1 // #define DEBUG_RAR + +// table 7.2-1 TS 38.321 +const uint16_t table_7_2_1[16] = { + 5, // row index 0 + 10, // row index 1 + 20, // row index 2 + 30, // row index 3 + 40, // row index 4 + 60, // row index 5 + 80, // row index 6 + 120, // row index 7 + 160, // row index 8 + 240, // row index 9 + 320, // row index 10 + 480, // row index 11 + 960, // row index 12 + 1920, // row index 13 +}; + /* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */ static const int sequence_cyclic_shift_1_harq_ack_bit[2] /* HARQ-ACK Value 0 1 */ @@ -701,7 +720,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, dlsch_pdu->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon + 2; } else { dlsch_pdu->SubcarrierSpacing = current_DL_BWP->scs; - if (mac->ra.RA_window_cnt >= 0 && rnti_type == TYPE_RA_RNTI_) { + if (nr_timer_is_active(&mac->ra.response_window_timer) && rnti_type == TYPE_RA_RNTI_) { dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_RA_DLSCH; } else { dl_conf_req->pdu_type = FAPI_NR_DL_CONFIG_TYPE_DLSCH; @@ -3414,11 +3433,11 @@ static bool check_ra_contention_resolution(const uint8_t *pdu, const uint8_t *co } static int nr_ue_validate_successrar(uint8_t *pduP, - int32_t pdu_len, - NR_UE_MAC_INST_t *mac, - uint8_t gNB_index, - frame_t frameP, - int slot) + int32_t pdu_len, + NR_UE_MAC_INST_t *mac, + uint8_t gNB_index, + frame_t frameP, + int slot) { // TS 38.321 - Figure 6.1.5a-1: BI MAC subheader // TS 38.321 - Figure 6.1.5a-3: SuccessRAR MAC subheader @@ -3426,6 +3445,7 @@ static int nr_ue_validate_successrar(uint8_t *pduP, uint8_t E = 1; uint8_t cont_res_id[6]; RA_config_t *ra = &mac->ra; + ra->RA_backoff_limit = 0; while (n < pdu_len && E) { E = (pduP[n] >> 7) & 0x1; @@ -3433,7 +3453,9 @@ static int nr_ue_validate_successrar(uint8_t *pduP, if (SUCESS_RAR_header_T1 == 0) { // T2 exist int SUCESS_RAR_header_T2 = (pduP[n] >> 5) & 0x1; if (SUCESS_RAR_header_T2 == 0) { // BI - ra->RA_backoff_indicator = pduP[n] & 0x0F; + int bi_ms = table_7_2_1[(pduP[n] & 0x0F)] * ra->scaling_factor_bi; + int slots_per_ms = mac->frame_structure.numb_slots_frame / 10; + ra->RA_backoff_limit = bi_ms * slots_per_ms; n++; } else { // S n++; @@ -3476,6 +3498,7 @@ static int nr_ue_validate_successrar(uint8_t *pduP, bool ra_success = check_ra_contention_resolution(cont_res_id, ra->cont_res_id); if (ra->RA_active && ra_success) { + nr_timer_stop(&ra->response_window_timer); nr_ra_succeeded(mac, gNB_index, frameP, slot); } else if (!ra_success) { // nr_ra_failed(mac, CC_id, &ra->prach_resources, frameP, slot); @@ -3841,6 +3864,115 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, return mac_ce - pdu; } +static void handle_rar_reception(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dlinfo, NR_MAC_RAR *rar, frame_t frame, int slot) +{ + RAR_grant_t rar_grant; + RA_config_t *ra = &mac->ra; +#ifdef DEBUG_RAR + // CSI + unsigned char csi_req = (unsigned char)(rar->UL_GRANT_4 & 0x01); +#endif + + // TPC + unsigned char tpc_command = (unsigned char)((rar->UL_GRANT_4 >> 1) & 0x07); + ra->Msg3_TPC = (tpc_command << 1) - 6; + + // MCS + rar_grant.mcs = (unsigned char)(rar->UL_GRANT_4 >> 4); + // time alloc + rar_grant.Msg3_t_alloc = (unsigned char)(rar->UL_GRANT_3 & 0x0f); + // frequency alloc + rar_grant.Msg3_f_alloc = (uint16_t)((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); + // frequency hopping + rar_grant.freq_hopping = (unsigned char)(rar->UL_GRANT_1 >> 2); + + // Schedule Msg3 + const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; + const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP; + const NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[current_DL_BWP->bwp_id]; + NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP, + *pdcch_config->ra_SS->controlResourceSetId, + pdcch_config->ra_SS->searchSpaceType->present, + TYPE_RA_RNTI_, + rar_grant.Msg3_t_alloc); + if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) { + LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n"); + return; + } + frame_t frame_tx = 0; + int slot_tx = 0; + const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs); + int ret = nr_ue_pusch_scheduler(mac, 1, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset); + + // TA command + // if the timeAlignmentTimer associated with this TAG is not running + if (!nr_timer_is_active(&mac->time_alignment_timer)) { + const int ta = rar->TA2 + (rar->TA1 << 5); + set_time_alignment(mac, ta, rar_ta, frame_tx, slot_tx); + LOG_W(MAC, "received TA command %d\n", 31 + ta); + } + // else ignore the received Timing Advance Command + +#ifdef DEBUG_RAR + LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E); + LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T); + LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID); + + LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R); + LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1); + + LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2); + LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1); + + LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2); + LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3); + LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4); + + LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1); + LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2); + + LOG_I(NR_MAC, + "[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n", + frame, + slot, + mac->ue_id, + rar_grant.Msg3_t_alloc, + rar_grant.Msg3_f_alloc, + ta_command, + rar_grant.mcs, + rar_grant.freq_hopping, + tpc_command); +#endif + + if (ret != -1) { + uint16_t rnti = mac->crnti; + // Upon successful reception, set the T-CRNTI to the RAR value + // if the RA preamble is selected among the contention-based RA Preambles + if (!ra->cfra) { + ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); + rnti = ra->t_crnti; + if (!ra->msg3_C_RNTI) + nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dlinfo->gNB_index); + } + fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + if (!pdu) + return; + // Config Msg3 PDU + int ret = nr_config_pusch_pdu(mac, + &tda_info, + &pdu->pusch_config_pdu, + NULL, + NULL, + &rar_grant, + rnti, + NR_SearchSpace__searchSpaceType_PR_common, + NR_DCI_NONE); + if (ret != 0) + remove_ul_config_last_item(pdu); + release_ul_config(pdu, false); + } +} + ///////////////////////////////////// // Random Access Response PDU // // TS 38.213 ch 8.2 // @@ -3885,13 +4017,10 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d } RA_config_t *ra = &mac->ra; + ra->t_crnti = 0; uint8_t n_subPDUs = 0; // number of RAR payloads uint8_t n_subheaders = 0; // number of MAC RAR subheaders uint8_t *dlsch_buffer = dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu; - uint8_t is_Msg3 = 1; - frame_t frame_tx = 0; - int slot_tx = 0; - int ret = 0; NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer; // RAR subheader pointer NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1); // RAR subPDU pointer uint8_t preamble_index = ra->ra_PreambleIndex; @@ -3900,7 +4029,8 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d T(T_NRUE_MAC_DL_RAR_PDU_WITH_DATA, T_INT(rnti), T_INT(frame), T_INT(slot), T_BUFFER(dlsch_buffer, dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.pdu_length)); - LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] invoking MAC for received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index); + ra->RA_backoff_limit = 0; + LOG_D(NR_MAC, "[%d.%d]: [UE %d][RAPROC] MAC received RAR (current preamble %d)\n", frame, slot, mac->ue_id, preamble_index); while (1) { n_subheaders++; @@ -3908,10 +4038,11 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d n_subPDUs++; LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got RAPID RAR subPDU\n", mac->ue_id, rnti); } else { - ra->RA_backoff_indicator = get_backoff_indicator(((NR_RA_HEADER_BI *)rarh)->BI); - ra->RA_BI_found = 1; - LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got BI RAR subPDU %d ms\n", mac->ue_id, ra->RA_backoff_indicator, rnti); - if ( ((NR_RA_HEADER_BI *)rarh)->E == 1) { + int bi_ms = table_7_2_1[((NR_RA_HEADER_BI *)rarh)->BI] * ra->scaling_factor_bi; + int slots_per_ms = mac->frame_structure.numb_slots_frame / 10; + ra->RA_backoff_limit = bi_ms * slots_per_ms; + LOG_I(NR_MAC, "[UE %d][RAPROC][RA-RNTI %04x] Got BI RAR subPDU %d ms\n", mac->ue_id, rnti, bi_ms); + if (((NR_RA_HEADER_BI *)rarh)->E == 1) { rarh += sizeof(NR_RA_HEADER_BI); continue; } else { @@ -3919,9 +4050,15 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d } } if (rarh->RAPID == preamble_index) { + // The MAC entity may stop ra-ResponseWindow (and hence monitoring for Random Access Response(s)) after + // successful reception of a Random Access Response containing Random Access Preamble identifiers + // that matches the transmitted PREAMBLE_INDEX. + nr_timer_stop(&ra->response_window_timer); LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mac->ue_id, frame, slot, rarh->RAPID); rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR)); - ra->RA_RAPID_found = 1; + handle_rar_reception(mac, dl_info, rar, frame, slot); + if (ra->cfra) + nr_ra_succeeded(mac, dl_info->gNB_index, frame, slot); if (get_softmodem_params()->emulate_l1) { /* When we are emulating L1 with multiple UEs, the rx_indication will have multiple RAR PDUs. The code would previously handle each of these PDUs, @@ -3971,142 +4108,6 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d rarh->RAPID, preamble_index); #endif - - if (ra->RA_RAPID_found) { - RAR_grant_t rar_grant; - -#ifdef DEBUG_RAR - // CSI - unsigned char csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); -#endif - - // TPC - unsigned char tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); - switch (tpc_command){ - case 0: - ra->Msg3_TPC = -6; - break; - case 1: - ra->Msg3_TPC = -4; - break; - case 2: - ra->Msg3_TPC = -2; - break; - case 3: - ra->Msg3_TPC = 0; - break; - case 4: - ra->Msg3_TPC = 2; - break; - case 5: - ra->Msg3_TPC = 4; - break; - case 6: - ra->Msg3_TPC = 6; - break; - case 7: - ra->Msg3_TPC = 8; - break; - default: - LOG_E(NR_PHY, "RAR impossible msg3 TPC\n"); - } - // MCS - rar_grant.mcs = (unsigned char) (rar->UL_GRANT_4 >> 4); - // time alloc - rar_grant.Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x0f); - // frequency alloc - rar_grant.Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12)); - // frequency hopping - rar_grant.freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2); - - // Schedule Msg3 - const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; - const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP; - const NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[current_DL_BWP->bwp_id]; - NR_tda_info_t tda_info = get_ul_tda_info(current_UL_BWP, - *pdcch_config->ra_SS->controlResourceSetId, - pdcch_config->ra_SS->searchSpaceType->present, - TYPE_RA_RNTI_, - rar_grant.Msg3_t_alloc); - if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) { - LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n"); - return; - } - const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs); - ret = nr_ue_pusch_scheduler(mac, is_Msg3, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset); - - // TA command - // if the timeAlignmentTimer associated with this TAG is not running - if (!nr_timer_is_active(&mac->time_alignment_timer)) { - const int ta = rar->TA2 + (rar->TA1 << 5); - set_time_alignment(mac, ta, rar_ta, frame_tx, slot_tx); - LOG_W(MAC, "received TA command %d\n", 31 + ta); - } - // else ignore the received Timing Advance Command - -#ifdef DEBUG_RAR - LOG_I(NR_MAC, "rarh->E = 0x%x\n", rarh->E); - LOG_I(NR_MAC, "rarh->T = 0x%x\n", rarh->T); - LOG_I(NR_MAC, "rarh->RAPID = 0x%x (%i)\n", rarh->RAPID, rarh->RAPID); - - LOG_I(NR_MAC, "rar->R = 0x%x\n", rar->R); - LOG_I(NR_MAC, "rar->TA1 = 0x%x\n", rar->TA1); - - LOG_I(NR_MAC, "rar->TA2 = 0x%x\n", rar->TA2); - LOG_I(NR_MAC, "rar->UL_GRANT_1 = 0x%x\n", rar->UL_GRANT_1); - - LOG_I(NR_MAC, "rar->UL_GRANT_2 = 0x%x\n", rar->UL_GRANT_2); - LOG_I(NR_MAC, "rar->UL_GRANT_3 = 0x%x\n", rar->UL_GRANT_3); - LOG_I(NR_MAC, "rar->UL_GRANT_4 = 0x%x\n", rar->UL_GRANT_4); - - LOG_I(NR_MAC, "rar->TCRNTI_1 = 0x%x\n", rar->TCRNTI_1); - LOG_I(NR_MAC, "rar->TCRNTI_2 = 0x%x\n", rar->TCRNTI_2); - - LOG_I(NR_MAC, "[%d.%d]: [UE %d] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d\n", - frame, - slot, - mac->ue_id, - rar_grant.Msg3_t_alloc, - rar_grant.Msg3_f_alloc, - ta_command, - rar_grant.mcs, - rar_grant.freq_hopping, - tpc_command); -#endif - - if (ret != -1) { - uint16_t rnti = mac->crnti; - // Upon successful reception, set the T-CRNTI to the RAR value if the RA preamble is selected among the contention-based RA Preambles - if (!ra->cfra) { - ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); - rnti = ra->t_crnti; - if (!ra->msg3_C_RNTI) - nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dl_info->gNB_index); - } - fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); - if (!pdu) - return; - // Config Msg3 PDU - int ret = nr_config_pusch_pdu(mac, - &tda_info, - &pdu->pusch_config_pdu, - NULL, - NULL, - &rar_grant, - rnti, - NR_SearchSpace__searchSpaceType_PR_common, - NR_DCI_NONE); - if (ret != 0) - remove_ul_config_last_item(pdu); - release_ul_config(pdu, false); - } - - } else { - ra->t_crnti = 0; - // TODO if the Random Access Preamble was not selected by the MAC entity - // among the contention-based Random Access Preamble - // apply the Timing Advance Command and start or restart the timeAlignmentTimer - } return; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index d4d4aa3a4d..a5f129e312 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -236,6 +236,15 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) phr_info->phr_reporting |= (1 << phr_cause_periodic_timer); } } + bool ra_window_expired = nr_timer_tick(&mac->ra.response_window_timer); + if (ra_window_expired) // consider the Random Access Response reception not successful + nr_rar_not_successful(mac); + bool ra_backoff_expired = nr_timer_tick(&mac->ra.RA_backoff_timer); + if (ra_backoff_expired) { + // perform the Random Access Resource selection procedure after the backoff time + mac->ra.ra_state = nrRA_GENERATE_PREAMBLE; + ra_resource_selection(mac); + } } void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu) @@ -2064,7 +2073,6 @@ static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP) { RA_config_t *ra = &mac->ra; - ra->RA_offset = 2; // to compensate the rx frame offset at the gNB if (ra->ra_state != nrRA_GENERATE_PREAMBLE) return; @@ -2076,7 +2084,6 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t if (is_ul_slot(slotP, &mac->frame_structure)) { if (slotP == prach_occasion_info->slot) { - nr_get_RA_window(mac); fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PRACH); if (!pdu) { LOG_E(NR_MAC, "Error in PRACH allocation\n"); @@ -2156,6 +2163,7 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t if (ra->ra_type == RA_4_STEP) { ra->ra_state = nrRA_WAIT_RAR; + ra->start_response_window = true; } else if (ra->ra_type == RA_2_STEP) { NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp index bcbec989c2..7dc0b43ec3 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_power_procedures.cpp @@ -192,8 +192,6 @@ TEST(pusch_power_control, pusch_power_control_msg3) current_UL_BWP.BWPSize = 106; current_UL_BWP.channel_bandwidth = 40; mac.current_UL_BWP = ¤t_UL_BWP; - NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; - current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon; mac.nr_band = 78; NR_PUSCH_Config_t pusch_Config = {0}; current_UL_BWP.pusch_Config = &pusch_Config; @@ -229,8 +227,8 @@ TEST(pusch_power_control, pusch_power_control_msg3) num_rb, start_prb); - long preambleReceivedTargetPower = -96; - nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower; + int preambleReceivedTargetPower = -96; + mac.ra.prach_resources.ra_preamble_rx_target_power = preambleReceivedTargetPower; int power = get_pusch_tx_power_ue(&mac, num_rb, @@ -247,7 +245,7 @@ TEST(pusch_power_control, pusch_power_control_msg3) false); EXPECT_EQ(power, -84); EXPECT_LT(power, P_CMAX); - nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower -= 2; + mac.ra.prach_resources.ra_preamble_rx_target_power -= 2; int reduced_power = get_pusch_tx_power_ue(&mac, num_rb, @@ -372,8 +370,6 @@ TEST(pusch_power_control, pusch_power_control_state_initialization) current_UL_BWP.BWPSize = 106; current_UL_BWP.channel_bandwidth = 40; mac.current_UL_BWP = ¤t_UL_BWP; - NR_RACH_ConfigCommon_t nr_rach_ConfigCommon = {0}; - current_UL_BWP.rach_ConfigCommon = &nr_rach_ConfigCommon; mac.nr_band = 78; NR_PUSCH_Config_t pusch_Config = {0}; current_UL_BWP.pusch_Config = &pusch_Config; @@ -393,8 +389,8 @@ TEST(pusch_power_control, pusch_power_control_state_initialization) uint32_t sum_bits_in_codeblocks = 56; int delta_pusch = 0; bool is_rar_tx_retx = true; - long preambleReceivedTargetPower = -96; - nr_rach_ConfigCommon.rach_ConfigGeneric.preambleReceivedTargetPower = preambleReceivedTargetPower; + int preambleReceivedTargetPower = -96; + mac.ra.prach_resources.ra_preamble_rx_target_power = preambleReceivedTargetPower; get_pusch_tx_power_ue(&mac, num_rb, diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index 6e8916f6f0..504abae957 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -101,6 +101,7 @@ TEST(test_init_ra, four_step_cbra) mac.p_Max = 23; mac.nr_band = 78; mac.frame_structure.frame_type = TDD; + mac.frame_structure.numb_slots_frame = 20; mac.frequency_range = FR1; mac.first_sync_frame = 0; int frame = 151; @@ -135,6 +136,7 @@ TEST(test_init_ra, four_step_cfra) mac.p_Max = 23; mac.nr_band = 78; mac.frame_structure.frame_type = TDD; + mac.frame_structure.numb_slots_frame = 20; mac.frequency_range = FR1; mac.first_sync_frame = 0; int frame = 151; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 9e7310cf40..d3e7a5a9aa 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -390,8 +390,7 @@ static bool is_my_dci(NR_UE_MAC_INST_t *mac, nfapi_nr_dl_dci_pdu_t *received_pdu already. Only once the RA procedure succeeds is the CRNTI value updated to the TC_RNTI. */ if (get_softmodem_params()->nsa) { - if (received_pdu->RNTI != mac->crnti && - (received_pdu->RNTI != mac->ra.ra_rnti || mac->ra.RA_RAPID_found)) + if (received_pdu->RNTI != mac->crnti && (received_pdu->RNTI != mac->ra.ra_rnti)) return false; } if (IS_SA_MODE(get_softmodem_params())) { @@ -1292,11 +1291,11 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; break; case FAPI_NR_RX_PDU_TYPE_RAR: - ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; if (!dl_info->rx_ind->rx_indication_body[i].pdsch_pdu.ack_nack) LOG_W(PHY, "Received a RAR-Msg2 but LDPC decode failed\n"); else LOG_I(PHY, "RAR-Msg2 decoded\n"); + ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; case FAPI_NR_CSIRS_IND: ret_mask |= (handle_csirs_measurements(mac, From e958822a73092efef723c774161e17fcd86a5e4d Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Dec 2024 18:21:27 +0100 Subject: [PATCH 19/34] Procedures for Contention Resolution --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 7 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 93 ++++++-------------- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 15 ++-- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 +- 4 files changed, 40 insertions(+), 79 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 2157a6c1c8..c494d477f5 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -300,12 +300,9 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c */ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, frame_t current_frame, slot_t current_slot, uint8_t Msg3_tda_id); -void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources); - -void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot); - +void nr_ra_contention_resolution_failed(RA_config_t *ra); void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); - +void nr_ra_backoff_setting(RA_config_t *ra); void nr_get_RA_window(NR_UE_MAC_INST_t *mac); /*@mac pointer to MAC instance diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 02afecec81..f198f4f17a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1174,8 +1174,6 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx) { RA_config_t *ra = &mac->ra; - NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; - if (ra->ra_state == nrRA_UE_IDLE) { bool init_success = init_RA(mac, frame); if (!init_success) @@ -1199,30 +1197,6 @@ void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, ra_resource_selection(mac); } } - - if (nr_timer_is_active(&ra->contention_resolution_timer)) { - nr_ue_contention_resolution(mac, CC_id, frame, nr_slot_tx, prach_resources); - } -} - -//////////////////////////////////////////////////////////////////////////// -/////////* Random Access Contention Resolution (5.1.35 TS 38.321) *///////// -//////////////////////////////////////////////////////////////////////////// -// Handling contention resolution timer -// WIP todo: -// - beam failure recovery -// - RA completed -void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources) -{ - RA_config_t *ra = &mac->ra; - - if (nr_timer_expired(&ra->contention_resolution_timer)) { - ra->t_crnti = 0; - nr_timer_stop(&ra->contention_resolution_timer); - // Signal PHY to quit RA procedure - LOG_E(MAC, "[UE %d] 4-Step CBRA: Contention resolution timer has expired, RA procedure has failed...\n", mac->ue_id); - nr_ra_failed(mac, cc_id, prach_resources, frame, slot); - } } // Handlig successful RA completion @ MAC layer @@ -1250,7 +1224,6 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame mac->ue_id, frame, slot); - nr_timer_stop(&ra->contention_resolution_timer); mac->crnti = ra->t_crnti; ra->t_crnti = 0; LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared contention resolution timer...\n", mac->ue_id, frame, slot); @@ -1264,6 +1237,33 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame nr_mac_rrc_ra_ind(mac->ue_id, frame, true); } +void nr_ra_backoff_setting(RA_config_t *ra) +{ + // select a random backoff time according to a uniform distribution + // between 0 and the PREAMBLE_BACKOFF + uint32_t seed = (unsigned int)(rdtsc_oai() & ~0); + uint32_t random_backoff = ra->RA_backoff_limit ? rand_r(&seed) % ra->RA_backoff_limit : 0; // in slots + nr_timer_setup(&ra->RA_backoff_timer, random_backoff, 1); + nr_timer_start(&ra->RA_backoff_timer); +} + +void nr_ra_contention_resolution_failed(RA_config_t *ra) +{ + // discard the TEMPORARY_C-RNTI + ra->t_crnti = 0; + // flush MSG3 buffer + free_and_zero(ra->Msg3_buffer); + NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; + prach_resources->preamble_tx_counter++; + if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { + // TODO indicate a Random Access problem to upper layers + } else { + // TODO handle msgA-TransMax (go back to 4-step if the threshold is reached) + // starting backoff time + nr_ra_backoff_setting(ra); + } +} + void nr_rar_not_successful(NR_UE_MAC_INST_t *mac) { LOG_W(MAC, "[UE %d] RAR reception failed\n", mac->ue_id); @@ -1284,44 +1284,7 @@ void nr_rar_not_successful(NR_UE_MAC_INST_t *mac) } } if (!ra_completed) { - // select a random backoff time according to a uniform distribution - // between 0 and the PREAMBLE_BACKOFF - uint32_t seed = (unsigned int)(rdtsc_oai() & ~0); - uint32_t random_backoff = rand_r(&seed) % ra->RA_backoff_limit; // in slots - nr_timer_setup(&ra->RA_backoff_timer, random_backoff, 1); - nr_timer_start(&ra->RA_backoff_timer); - } -} - -// Handling failure of RA procedure @ MAC layer -// according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 -// todo: -// - complete handling of received contention-based RA preamble -void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_resources, frame_t frame, int slot) -{ - RA_config_t *ra = &mac->ra; - ra->ra_PreambleIndex = -1; - ra->ra_state = nrRA_UE_IDLE; - - prach_resources->preamble_tx_counter++; - - // when the Contention Resolution is considered not successful - // stop timeAlignmentTimer - nr_timer_stop(&mac->time_alignment_timer); - - if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { - - LOG_D(NR_MAC, - "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", - mac->ue_id, - frame, - slot, - ra->preambleTransMax); - - prach_resources->preamble_tx_counter = 1; - prach_resources->preamble_power_ramping_step += 2; // 2 dB increment - prach_resources->ra_preamble_rx_target_power = get_ra_preamble_rx_target_power(ra, mac->current_UL_BWP->scs); - + nr_ra_backoff_setting(ra); } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index a77067395f..8d42075c48 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3501,9 +3501,7 @@ static int nr_ue_validate_successrar(uint8_t *pduP, nr_timer_stop(&ra->response_window_timer); nr_ra_succeeded(mac, gNB_index, frameP, slot); } else if (!ra_success) { - // nr_ra_failed(mac, CC_id, &ra->prach_resources, frameP, slot); - ra->ra_state = nrRA_UE_IDLE; - ra->RA_active = 0; + nr_ra_backoff_setting(ra); } } } else { // RAPID @@ -3706,7 +3704,8 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i mac_len = 6; if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) { - LOG_I(MAC, "[UE %d]Frame %d Contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", + LOG_D(NR_MAC, + "[UE %d]Frame %d Contention resolution identity: 0x%02x%02x%02x%02x%02x%02x Terminating RA procedure\n", mac->ue_id, frameP, pduP[1], @@ -3716,15 +3715,15 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i pduP[5], pduP[6]); + nr_timer_stop(&ra->contention_resolution_timer); bool ra_success = check_ra_contention_resolution(&pduP[1], ra->cont_res_id); if (ra->RA_active && ra_success) { nr_ra_succeeded(mac, gNB_index, frameP, slot); } else if (!ra_success) { - // TODO: Handle failure of RA procedure @ MAC layer - // nr_ra_failed(module_idP, CC_id, prach_resources, frameP, slot); // prach_resources is a PHY structure - ra->ra_state = nrRA_UE_IDLE; - ra->RA_active = false; + // consider this Contention Resolution not successful and discard the successfully decoded MAC PDU + nr_ra_contention_resolution_failed(ra); + return; } } break; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index a5f129e312..c7a6d99c33 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -192,7 +192,9 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) bool alignment_timer_expired = nr_timer_tick(&mac->time_alignment_timer); if (alignment_timer_expired) handle_time_alignment_timer_expired(mac); - nr_timer_tick(&mac->ra.contention_resolution_timer); + bool contention_resolution_expired = nr_timer_tick(&mac->ra.contention_resolution_timer); + if (contention_resolution_expired) + nr_ra_contention_resolution_failed(&mac->ra); for (int j = 0; j < NR_MAX_SR_ID; j++) nr_timer_tick(&mac->scheduling_info.sr_info[j].prohibitTimer); nr_timer_tick(&mac->scheduling_info.sr_DelayTimer); From dcc17a9d701b91e15b37a93935f4e5d757f7432a Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 4 Dec 2024 19:11:05 +0100 Subject: [PATCH 20/34] signaling RRC RA problems (leading to possible radio link failure) --- .../SIMULATION/NR_PHY/nr_dummy_functions.c | 2 +- openair2/COMMON/mac_messages_types.h | 1 - openair2/LAYER2/NR_MAC_UE/mac_proto.h | 9 +-------- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 8 ++++++-- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 13 +++++++++---- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- .../tests/test_nr_ue_ra_procedures.cpp | 2 +- openair2/RRC/NR_UE/L2_interface_ue.c | 3 +-- openair2/RRC/NR_UE/L2_interface_ue.h | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 19 ++++++++++++++----- 11 files changed, 36 insertions(+), 27 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c index d55322156b..973aa60930 100644 --- a/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c +++ b/openair1/SIMULATION/NR_PHY/nr_dummy_functions.c @@ -36,7 +36,7 @@ void nr_mac_rrc_sync_ind(const module_id_t module_id, void nr_mac_rrc_msg3_ind(const module_id_t mod_id, int rnti, int gnb_id) {} -void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) {} +void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success) {} void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) {} diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index bc9e8f6c8a..882dba7740 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -72,7 +72,6 @@ // Messages between RRC and MAC layers typedef struct NRRrcMacRaInd_s { - uint32_t frame; bool RA_succeeded; } NRRrcMacRaInd; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index c494d477f5..c3f919be5e 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -292,15 +292,8 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c uint32_t bwp_size, uint32_t bwp_start); -/* \brief This function schedules the Msg3 transmission -@param -@param -@param -@returns void -*/ -void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac, frame_t current_frame, slot_t current_slot, uint8_t Msg3_tda_id); -void nr_ra_contention_resolution_failed(RA_config_t *ra); +void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac); void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); void nr_ra_backoff_setting(RA_config_t *ra); void nr_get_RA_window(NR_UE_MAC_INST_t *mac); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 7cac155bc6..0d957ad4b5 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -180,9 +180,11 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) if (nr_mac->data_inactivity_timer) nr_timer_stop(nr_mac->data_inactivity_timer); nr_timer_stop(&nr_mac->time_alignment_timer); - nr_timer_stop(&nr_mac->ra.contention_resolution_timer); nr_timer_stop(&nr_mac->scheduling_info.sr_DelayTimer); nr_timer_stop(&nr_mac->scheduling_info.retxBSR_Timer); + nr_timer_stop(&nr_mac->ra.response_window_timer); + nr_timer_stop(&nr_mac->ra.RA_backoff_timer); + nr_timer_stop(&nr_mac->ra.contention_resolution_timer); for (int i = 0; i < NR_MAX_SR_ID; i++) nr_timer_stop(&nr_mac->scheduling_info.sr_info[i].prohibitTimer); @@ -194,8 +196,10 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) nr_mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value // stop any ongoing RACH procedure - if (nr_mac->ra.ra_state < nrRA_SUCCEEDED) + if (nr_mac->ra.RA_active) { nr_mac->ra.ra_state = nrRA_UE_IDLE; + nr_mac->ra.RA_active = false; + } // discard explicitly signalled contention-free Random Access Resources // TODO not sure what needs to be done here diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index f198f4f17a..f6da74e102 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -879,6 +879,7 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) // Random acces procedure initialization mac->state = UE_PERFORMING_RA; ra->RA_active = true; + ra->msg3_C_RNTI = false; NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; // flush MSG3 buffer @@ -1234,7 +1235,7 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame ra->ra_state = nrRA_SUCCEEDED; mac->state = UE_CONNECTED; free_and_zero(ra->Msg3_buffer); - nr_mac_rrc_ra_ind(mac->ue_id, frame, true); + nr_mac_rrc_ra_ind(mac->ue_id, true); } void nr_ra_backoff_setting(RA_config_t *ra) @@ -1247,8 +1248,10 @@ void nr_ra_backoff_setting(RA_config_t *ra) nr_timer_start(&ra->RA_backoff_timer); } -void nr_ra_contention_resolution_failed(RA_config_t *ra) +void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac) { + LOG_W(MAC, "[UE %d] Contention resolution failed\n", mac->ue_id); + RA_config_t *ra = &mac->ra; // discard the TEMPORARY_C-RNTI ra->t_crnti = 0; // flush MSG3 buffer @@ -1256,7 +1259,8 @@ void nr_ra_contention_resolution_failed(RA_config_t *ra) NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; prach_resources->preamble_tx_counter++; if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { - // TODO indicate a Random Access problem to upper layers + // indicate a Random Access problem to upper layers + nr_mac_rrc_ra_ind(mac->ue_id, false); } else { // TODO handle msgA-TransMax (go back to 4-step if the threshold is reached) // starting backoff time @@ -1275,7 +1279,8 @@ void nr_rar_not_successful(NR_UE_MAC_INST_t *mac) // if the Random Access Preamble is transmitted on the SpCell // TODO to be verified, this means SA if I'm not mistaken if (IS_SA_MODE(get_softmodem_params())) { - // TODO indicate a Random Access problem to upper layers + // indicate a Random Access problem to upper layers + nr_mac_rrc_ra_ind(mac->ue_id, false); } else { // if the Random Access Preamble is transmitted on an SCell: // consider the Random Access procedure unsuccessfully completed. diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8d42075c48..afe7438949 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3722,7 +3722,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i nr_ra_succeeded(mac, gNB_index, frameP, slot); } else if (!ra_success) { // consider this Contention Resolution not successful and discard the successfully decoded MAC PDU - nr_ra_contention_resolution_failed(ra); + nr_ra_contention_resolution_failed(mac); return; } } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index c7a6d99c33..6ae011006f 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -194,7 +194,7 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) handle_time_alignment_timer_expired(mac); bool contention_resolution_expired = nr_timer_tick(&mac->ra.contention_resolution_timer); if (contention_resolution_expired) - nr_ra_contention_resolution_failed(&mac->ra); + nr_ra_contention_resolution_failed(mac); for (int j = 0; j < NR_MAX_SR_ID; j++) nr_timer_tick(&mac->scheduling_info.sr_info[j].prohibitTimer); nr_timer_tick(&mac->scheduling_info.sr_DelayTimer); diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index 504abae957..45fc34b47c 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -29,7 +29,7 @@ softmodem_params_t *get_softmodem_params(void) { return &softmodem_params; } -void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) +void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success) { } tbs_size_t mac_rlc_data_req(const module_id_t module_idP, diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 7fd34ff91c..74f4170abb 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -177,10 +177,9 @@ void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id) itti_send_msg_to_task(TASK_RRC_NRUE, instance, message_p); } -void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success) +void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success) { MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_RA_IND); - NR_RRC_MAC_RA_IND (message_p).frame = frame; NR_RRC_MAC_RA_IND (message_p).RA_succeeded = success; itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p); } diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index 05888cbc0e..469faf2ece 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -39,7 +39,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id); void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); -void nr_mac_rrc_ra_ind(const module_id_t mod_id, int frame, bool success); +void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success); void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type); void process_msg_rcc_to_mac(MessageDef *msg); #endif diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index f61ce49494..aa9e38a3c5 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1975,6 +1975,16 @@ void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded) nr_timer_stop(&timers->T304); // TODO handle the rest of procedures as described in 5.3.5.3 for when // reconfigurationWithSync is included in spCellConfig + } else if (!ra_succeeded) { + // upon random access problem indication from MCG MAC + // while neither T300, T301, T304, T311 nor T319 are running + // consider radio link failure to be detected + if (!nr_timer_is_active(&timers->T300) + && !nr_timer_is_active(&timers->T301) + && !nr_timer_is_active(&timers->T304) + && !nr_timer_is_active(&timers->T311) + && !nr_timer_is_active(&timers->T319)) + handle_rlf_detection(rrc); } } @@ -2040,11 +2050,10 @@ void *rrc_nrue(void *notUsed) case NR_RRC_MAC_RA_IND: LOG_D(NR_RRC, - "[UE %ld] Received %s: frame %d RA %s\n", - rrc->ue_id, - ITTI_MSG_NAME(msg_p), - NR_RRC_MAC_RA_IND(msg_p).frame, - NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed"); + "[UE %ld] Received %s: RA %s\n", + rrc->ue_id, + ITTI_MSG_NAME(msg_p), + NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed"); nr_rrc_handle_ra_indication(rrc, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded); break; From 5df6153024023a036d895e631a9de8bc2e509b9b Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 5 Dec 2024 13:49:25 +0100 Subject: [PATCH 21/34] remove unnecessary nr_ue_manage_ra_procedure function --- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 9 ----- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 42 +------------------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 27 ++++++++++--- 3 files changed, 23 insertions(+), 55 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index c3f919be5e..38188d86c6 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -297,15 +297,6 @@ void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac); void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame_t frame, const int slot); void nr_ra_backoff_setting(RA_config_t *ra); void nr_get_RA_window(NR_UE_MAC_INST_t *mac); - -/*@mac pointer to MAC instance -@param CC_id Component Carrier Index -@param frame -@param gNB_id gNB index -@param nr_slot_tx slot for PRACH transmission -@returns indication to generate PRACH to phy */ -void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx); - void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index f6da74e102..3a93c88102 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1068,6 +1068,7 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) twostep_generic, &mac->ntn_ta); ra->start_response_window = false; + return true; } @@ -1159,47 +1160,6 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS memcpy(ra->Msg3_buffer, buf, sizeof(uint8_t) * TBS_max); } -/** - * Function: handles Random Access Preamble Initialization (5.1.1 TS 38.321) - * handles Random Access Response reception (5.1.4 TS 38.321) - * Note: In SA mode the Msg3 contains a CCCH SDU, therefore no C-RNTI MAC CE is transmitted. - * - * @prach_resources pointer to PRACH resources - * @prach_pdu pointer to FAPI UL PRACH PDU - * @mod_id module ID - * @CC_id CC ID - * @frame current UL TX frame - * @gNB_id gNB ID - * @nr_slot_tx current UL TX slot - */ -void nr_ue_manage_ra_procedure(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB_id, int nr_slot_tx) -{ - RA_config_t *ra = &mac->ra; - if (ra->ra_state == nrRA_UE_IDLE) { - bool init_success = init_RA(mac, frame); - if (!init_success) - return; - else { - // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a) - ra_resource_selection(mac); - } - } - - LOG_D(NR_MAC, "[UE %d][%d.%d]: ra_state %d, RA_active %d\n", mac->ue_id, frame, nr_slot_tx, ra->ra_state, ra->RA_active); - - if (nr_timer_is_active(&ra->RA_backoff_timer)) { - // if the criteria (as defined in clause 5.1.2) to select contention-free Random Access Resources - // is met during the backoff time - // TODO verify what does this mean - if (ra->cfra) { - // perform the Random Access Resource selection procedure - nr_timer_stop(&ra->RA_backoff_timer); - mac->ra.ra_state = nrRA_GENERATE_PREAMBLE; - ra_resource_selection(mac); - } - } -} - // Handlig successful RA completion @ MAC layer // according to section 5 of 3GPP TS 38.321 version 16.2.1 Release 16 // todo: diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 6ae011006f..fc69b5e517 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -246,6 +246,18 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) // perform the Random Access Resource selection procedure after the backoff time mac->ra.ra_state = nrRA_GENERATE_PREAMBLE; ra_resource_selection(mac); + } else { + if (nr_timer_is_active(&mac->ra.RA_backoff_timer)) { + // if the criteria (as defined in clause 5.1.2) to select contention-free Random Access Resources + // is met during the backoff time + // TODO verify what does this mean + if (mac->ra.cfra) { + // perform the Random Access Resource selection procedure + nr_timer_stop(&mac->ra.RA_backoff_timer); + mac->ra.ra_state = nrRA_GENERATE_PREAMBLE; + ra_resource_selection(mac); + } + } } } @@ -1315,11 +1327,18 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) uint32_t gNB_index = ul_info->gNB_index; RA_config_t *ra = &mac->ra; - if (mac->state == UE_PERFORMING_RA) { - nr_ue_manage_ra_procedure(mac, cc_id, frame_tx, gNB_index, slot_tx); - nr_ue_prach_scheduler(mac, frame_tx, slot_tx); + + if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_UE_IDLE) { + bool res = init_RA(mac, frame_tx); + if (res) { + // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a) + ra_resource_selection(mac); + } } + if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_GENERATE_PREAMBLE) + nr_ue_prach_scheduler(mac, frame_tx, slot_tx); + bool BSRsent = false; if (mac->state == UE_CONNECTED) { nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx); @@ -2075,8 +2094,6 @@ static bool is_prach_frame(frame_t frame, prach_occasion_info_t *prach_occasion_ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP) { RA_config_t *ra = &mac->ra; - if (ra->ra_state != nrRA_GENERATE_PREAMBLE) - return; // Get any valid PRACH occasion in the current slot for the selected SSB index prach_occasion_info_t *prach_occasion_info = &ra->sched_ro_info; From 65bc749ee675202a9bcb6fb005d537052a70f35d Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 5 Dec 2024 19:58:50 +0100 Subject: [PATCH 22/34] start the rar reception window in PRACH slots but take into account the additional slots difference wrt when we actually would need to start it (in first DCI occasion) --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 1 + openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 4 +--- .../NR_MAC_UE/nr_ue_dci_configuration.c | 13 ++++------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 22 +++++++++++++++++-- 5 files changed, 27 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 95df46fb72..555a7b993c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -331,7 +331,7 @@ typedef struct { int ra_ssb; /// Random-access response window timer NR_timer_t response_window_timer; - bool start_response_window; + int response_window_setup_time; /// Random-access backoff timer NR_timer_t RA_backoff_timer; int RA_backoff_limit; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 38188d86c6..530ff95240 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -302,6 +302,7 @@ void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac); void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, const fapi_nr_synch_request_t *sync_req); +bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss); /** * @brief Get UE sync state diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 3a93c88102..04285e672a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -820,7 +820,7 @@ static void setup_ra_response_window(RA_config_t *ra, ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_frame / 10); } - nr_timer_setup(&ra->response_window_timer, respwind_value + ta_Common_slots, 1); + ra->response_window_setup_time = respwind_value + ta_Common_slots; } // Random Access procedure initialization as per 5.1.1 and initialization of variables specific @@ -1067,8 +1067,6 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) rach_ConfigGeneric, twostep_generic, &mac->ntn_ta); - ra->start_response_window = false; - return true; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 237838e4dc..3817e06759 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -560,18 +560,13 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss); } } - if (mac->state == UE_PERFORMING_RA && mac->ra.ra_state >= nrRA_WAIT_RAR) { + RA_config_t *ra = &mac->ra; + if (mac->state == UE_PERFORMING_RA && ra->ra_state >= nrRA_WAIT_RAR) { // if RA is ongoing use RA search space if (is_ss_monitor_occasion(frame, slot, slots_per_frame, pdcch_config->ra_SS)) { - // The RA response window starts at the first symbol of the earliest CORESET - // the UE is configured to receive PDCCH for Type1-PDCCH CSS set - if (mac->ra.start_response_window) { - nr_timer_start(&mac->ra.response_window_timer); - mac->ra.start_response_window = false; - } nr_rnti_type_t rnti_type = 0; - if (mac->ra.ra_type == RA_4_STEP) { - rnti_type = mac->ra.ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_; + if (ra->ra_type == RA_4_STEP) { + rnti_type = ra->ra_state == nrRA_WAIT_RAR ? TYPE_RA_RNTI_ : TYPE_TC_RNTI_; } else { rnti_type = TYPE_MSGB_RNTI_; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index fc69b5e517..af7e063481 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2180,13 +2180,31 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t T(T_UE_PHY_INITIATE_RA_PROCEDURE, T_INT(frameP), T_INT(pdu->prach_config_pdu.prach_slot), T_INT(pdu->prach_config_pdu.ra_PreambleIndex), T_INT(pdu->prach_config_pdu.prach_tx_power)); + const int n_slots_frame = mac->frame_structure.numb_slots_frame; if (ra->ra_type == RA_4_STEP) { ra->ra_state = nrRA_WAIT_RAR; - ra->start_response_window = true; + // we start to monitor DCI for RAR in the first valid occasion after transmitting RACH + // the response window timer should be started at that time + // but for processing reasons it is better to start it here and to add the slot difference + // that also takes into account the rx to tx slot offset + int next_slot = (slotP + 1) % n_slots_frame; + int next_frame = (frameP + (next_slot < slotP)) % MAX_FRAME_NUMBER; + int add_slots = 1; + NR_BWP_PDCCH_t *pdcch_config = &mac->config_BWP_PDCCH[mac->current_DL_BWP->bwp_id]; + while (!is_dl_slot(next_slot, &mac->frame_structure) + || !is_ss_monitor_occasion(next_frame, next_slot, n_slots_frame, pdcch_config->ra_SS)) { + int temp_slot = (next_slot + 1) % n_slots_frame; + next_frame = (next_frame + (temp_slot < next_slot)) % MAX_FRAME_NUMBER; + next_slot = temp_slot; + add_slots++; + } + nr_timer_setup(&ra->response_window_timer, + ra->response_window_setup_time + add_slots + GET_DURATION_RX_TO_TX(&mac->ntn_ta), + 1); + nr_timer_start(&ra->response_window_timer); } else if (ra->ra_type == RA_2_STEP) { NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; - const int n_slots_frame = mac->frame_structure.numb_slots_frame; slot_t msgA_pusch_slot = (slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) % n_slots_frame; frame_t msgA_pusch_frame = (frameP + ((slotP + msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16) / n_slots_frame)) % 1024; From 3f35d462e9877e37a50e946d7356bf5ce3b30e09 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 13 Dec 2024 13:44:16 +0100 Subject: [PATCH 23/34] separate DL and UL timers at UE --- executables/nr-ue.c | 5 ++++- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 3 ++- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 18 +++++++++++------- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 7 +++++-- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h | 2 +- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index cc72eed263..7bb508cfba 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -519,7 +519,7 @@ void processSlotTX(void *arg) bool sl_tx_action = false; if (UE->if_inst) - UE->if_inst->slot_indication(UE->Mod_id); + UE->if_inst->slot_indication(UE->Mod_id, true); if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT) { if (UE->sl_mode == 2 && proc->tx_slot_type == NR_SIDELINK_SLOT) { @@ -650,6 +650,9 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, } } + if (UE->if_inst) + UE->if_inst->slot_indication(UE->Mod_id, false); + bool dl_slot = false; if (proc->rx_slot_type == NR_DOWNLINK_SLOT || proc->rx_slot_type == NR_MIXED_SLOT) { dl_slot = true; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 530ff95240..a2b2e0f777 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -49,7 +49,8 @@ NR_UE_DL_BWP_t *get_dl_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool set NR_UE_UL_BWP_t *get_ul_bwp_structure(NR_UE_MAC_INST_t *mac, int bwp_id, bool setup); void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data); -void update_mac_timers(NR_UE_MAC_INST_t *mac); +void update_mac_ul_timers(NR_UE_MAC_INST_t *mac); +void update_mac_dl_timers(NR_UE_MAC_INST_t *mac); NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid); /**\brief apply default configuration values in nr_mac instance diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index af7e063481..3eb4c4d375 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -182,16 +182,23 @@ void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) // TODO not sure what to do here } -void update_mac_timers(NR_UE_MAC_INST_t *mac) +void update_mac_dl_timers(NR_UE_MAC_INST_t *mac) +{ + bool ra_window_expired = nr_timer_tick(&mac->ra.response_window_timer); + if (ra_window_expired) // consider the Random Access Response reception not successful + nr_rar_not_successful(mac); + bool alignment_timer_expired = nr_timer_tick(&mac->time_alignment_timer); + if (alignment_timer_expired) + handle_time_alignment_timer_expired(mac); +} + +void update_mac_ul_timers(NR_UE_MAC_INST_t *mac) { if (mac->data_inactivity_timer) { bool inactivity_timer_expired = nr_timer_tick(mac->data_inactivity_timer); if (inactivity_timer_expired) nr_mac_rrc_inactivity_timer_ind(mac->ue_id); } - bool alignment_timer_expired = nr_timer_tick(&mac->time_alignment_timer); - if (alignment_timer_expired) - handle_time_alignment_timer_expired(mac); bool contention_resolution_expired = nr_timer_tick(&mac->ra.contention_resolution_timer); if (contention_resolution_expired) nr_ra_contention_resolution_failed(mac); @@ -238,9 +245,6 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) phr_info->phr_reporting |= (1 << phr_cause_periodic_timer); } } - bool ra_window_expired = nr_timer_tick(&mac->ra.response_window_timer); - if (ra_window_expired) // consider the Random Access Response reception not successful - nr_rar_not_successful(mac); bool ra_backoff_expired = nr_timer_tick(&mac->ra.RA_backoff_timer); if (ra_backoff_expired) { // perform the Random Access Resource selection procedure after the backoff time diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index d3e7a5a9aa..06eb9f8650 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1329,12 +1329,15 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info) return ret2; } -void nr_ue_slot_indication(uint8_t mod_id) +void nr_ue_slot_indication(uint8_t mod_id, bool is_tx) { NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); int ret = pthread_mutex_lock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); - update_mac_timers(mac); + if (is_tx) + update_mac_ul_timers(mac); + else + update_mac_dl_timers(mac); ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h index e6a4bfa80b..2bbd97db84 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h @@ -260,7 +260,7 @@ typedef int (nr_ue_dl_indication_f)(nr_downlink_indication_t *dl_info); */ typedef int (nr_ue_ul_indication_f)(nr_uplink_indication_t *ul_info); -typedef void (nr_ue_slot_indication_f)(uint8_t mod_id); +typedef void (nr_ue_slot_indication_f)(uint8_t mod_id, bool is_tx); /* * Generic type of an application-defined callback to return various From 96f1a2d474d7def5720784187295a302a7affbf3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 17 Dec 2024 10:17:12 +0100 Subject: [PATCH 24/34] implementation of RAR response window timer suspension (this is needed because it might expire while MSG2 is being decoded despite being received inside the window) --- common/utils/nr/nr_common.c | 11 +++++++++-- common/utils/nr/nr_common.h | 7 +++++++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 4 ++++ openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 12 ++++++++++-- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 1d1e683dce..58c18bfd36 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1380,15 +1380,22 @@ int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_su void nr_timer_start(NR_timer_t *timer) { timer->active = true; + timer->suspended = false; timer->counter = 0; } void nr_timer_stop(NR_timer_t *timer) { timer->active = false; + timer->suspended = false; timer->counter = 0; } +void nr_timer_suspension(NR_timer_t *timer) +{ + timer->suspended = !timer->suspended; +} + bool nr_timer_is_active(const NR_timer_t *timer) { return timer->active; @@ -1399,7 +1406,7 @@ bool nr_timer_tick(NR_timer_t *timer) bool expired = false; if (timer->active) { timer->counter += timer->step; - if (timer->target == UINT_MAX) // infinite target, never expires + if (timer->target == UINT_MAX || timer->suspended) // infinite target, never expires return false; expired = nr_timer_expired(timer); if (expired) @@ -1410,7 +1417,7 @@ bool nr_timer_tick(NR_timer_t *timer) bool nr_timer_expired(const NR_timer_t *timer) { - if (timer->target == UINT_MAX) // infinite target, never expires + if (timer->target == UINT_MAX || timer->suspended) // infinite target, never expires return false; return timer->counter >= timer->target; } diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index ce71500eb0..1dc6a1169d 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -156,6 +156,7 @@ typedef struct { typedef struct { bool active; + bool suspended; uint32_t counter; uint32_t target; uint32_t step; @@ -171,6 +172,12 @@ void nr_timer_start(NR_timer_t *timer); * @param timer Timer to stopped */ void nr_timer_stop(NR_timer_t *timer); +/** + * @brief To suspend/resume a timer + * @param timer Timer to be stopped/suspended + */ +void nr_timer_suspension(NR_timer_t *timer); + /** * @brief If active, it increases timer counter by an amout of units equal to step. It stops timer if expired * @param timer Timer to be handled diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index afe7438949..33ee5dd4c5 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3896,6 +3896,8 @@ static void handle_rar_reception(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t rar_grant.Msg3_t_alloc); if (!tda_info.valid_tda || tda_info.nrOfSymbols == 0) { LOG_E(MAC, "Cannot schedule Msg3. Something wrong in TDA information\n"); + // resume RAR response window timer if MSG2 decoding failed + nr_timer_suspension(&mac->ra.response_window_timer); return; } frame_t frame_tx = 0; @@ -4082,6 +4084,8 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d slot, rarh->RAPID, preamble_index); + // resume RAR response window timer if MSG2 decoding failed + nr_timer_suspension(&mac->ra.response_window_timer); break; } else { rarh += sizeof(NR_MAC_RAR) + 1; diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 06eb9f8650..96d1ee6d4d 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1124,6 +1124,11 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, if (mac->ra.msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) nr_ra_succeeded(mac, gNB_index, frame, slot); + // suspend RAR response window timer + // (in RFsim running multiple slot in parallel it might expire while decoding MSG2) + if (mac->ra.ra_state == nrRA_WAIT_RAR) + nr_timer_suspension(&mac->ra.response_window_timer); + return nr_ue_process_dci_indication_pdu(mac, frame, slot, dci); } @@ -1291,10 +1296,13 @@ static uint32_t nr_ue_dl_processing(NR_UE_MAC_INST_t *mac, nr_downlink_indicatio ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH; break; case FAPI_NR_RX_PDU_TYPE_RAR: - if (!dl_info->rx_ind->rx_indication_body[i].pdsch_pdu.ack_nack) + if (!dl_info->rx_ind->rx_indication_body[i].pdsch_pdu.ack_nack) { LOG_W(PHY, "Received a RAR-Msg2 but LDPC decode failed\n"); - else + // resume RAR response window timer if MSG2 decoding failed + nr_timer_suspension(&mac->ra.response_window_timer); + } else { LOG_I(PHY, "RAR-Msg2 decoded\n"); + } ret_mask |= (handle_dlsch(mac, dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR; break; case FAPI_NR_CSIRS_IND: From fc0d762407939eff3a59bdac92268f2e3c1946de Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 Feb 2025 14:01:24 +0100 Subject: [PATCH 25/34] move MSG3-C-RNTI flag from RA to MAC structure otherwise it would be reset by RA initialization --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 + openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 7 +++---- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 555a7b993c..0f76103fcb 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -349,7 +349,6 @@ typedef struct { // initial Random Access Preamble power int preambleRxTargetPower; int msg3_deltaPreamble; - bool msg3_C_RNTI; int preambleReceivedTargetPower_config; /// Random-access Contention Resolution Timer NR_timer_t contention_resolution_timer; @@ -637,6 +636,7 @@ typedef struct NR_UE_MAC_INST_s { int f_b_f_c; bool pusch_power_control_initialized; int delta_msg2; + bool msg3_C_RNTI; pthread_mutex_t if_mutex; ue_mac_stats_t stats; } NR_UE_MAC_INST_t; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 0d957ad4b5..c0ab5bd310 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -69,6 +69,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->p_Max = INT_MIN; mac->p_Max_alt = INT_MIN; mac->n_ta_offset = -1; + mac->msg3_C_RNTI = false; mac->ntn_ta.ntn_params_changed = false; reset_mac_inst(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 04285e672a..43114686d1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -879,7 +879,6 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) // Random acces procedure initialization mac->state = UE_PERFORMING_RA; ra->RA_active = true; - ra->msg3_C_RNTI = false; NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; fapi_nr_config_request_t *cfg = &mac->phy_config.config_req; // flush MSG3 buffer @@ -1142,7 +1141,7 @@ void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS } uint8_t *pdu = buf; - if (ra->msg3_C_RNTI) + if (mac->msg3_C_RNTI) pdu = fill_msg3_crnti_pdu(ra, pdu, mac->crnti); else pdu = fill_msg3_pdu_from_rlc(mac, pdu, TBS_max); @@ -1189,7 +1188,7 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame } ra->RA_active = false; - ra->msg3_C_RNTI = false; + mac->msg3_C_RNTI = false; ra->ra_state = nrRA_SUCCEEDED; mac->state = UE_CONNECTED; free_and_zero(ra->Msg3_buffer); @@ -1257,7 +1256,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *pdcch_order) mac->state = UE_PERFORMING_RA; reset_ra(mac, false); RA_config_t *ra = &mac->ra; - ra->msg3_C_RNTI = true; + mac->msg3_C_RNTI = true; if (pdcch_order) { ra->pdcch_order.active = true; ra->pdcch_order.preamble_index = pdcch_order->ra_preamble_index; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 33ee5dd4c5..18ee198582 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3952,7 +3952,7 @@ static void handle_rar_reception(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t if (!ra->cfra) { ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); rnti = ra->t_crnti; - if (!ra->msg3_C_RNTI) + if (!mac->msg3_C_RNTI) nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dlinfo->gNB_index); } fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 96d1ee6d4d..64de7b4560 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1121,7 +1121,7 @@ static nr_dci_format_t handle_dci(NR_UE_MAC_INST_t *mac, // if notification of a reception of a PDCCH transmission of the SpCell is received from lower layers // if the C-RNTI MAC CE was included in Msg3 // consider this Contention Resolution successful - if (mac->ra.msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) + if (mac->msg3_C_RNTI && mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) nr_ra_succeeded(mac, gNB_index, frame, slot); // suspend RAR response window timer From 4b191b7d0701bf7ba76b9dab7539469ec96a2fd5 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 20 Feb 2025 16:02:28 +0100 Subject: [PATCH 26/34] error for ra-responsewindow exceeding 10ms instead of assertion (CI test with FAPI would fail otherwise) --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 4 +++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 43114686d1..1c5be61884 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -811,7 +811,9 @@ static void setup_ra_response_window(RA_config_t *ra, if (!response_window) respwind_value = nr_get_RA_window_4Step(configGeneric->ra_ResponseWindow); // The network configures a value lower than or equal to 10ms - AssertFatal(respwind_value != 0 && respwind_value <= slots_per_frame, "Invalid RAR response window value\n"); + AssertFatal(respwind_value != 0, "Invalid RAR response window value\n"); + if (respwind_value > slots_per_frame) + LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n"); } int ta_Common_slots = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 9044927f34..a8feb18a29 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1375,6 +1375,8 @@ static bool msg2_in_response_window(int rach_frame, int current_slot) { int window_slots = get_response_window(rrc_ra_ResponseWindow); + if (window_slots > n_slots_frame) + LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n"); int abs_rach = n_slots_frame * rach_frame + rach_slot; int abs_now = n_slots_frame * current_frame + current_slot; int diff = (n_slots_frame * 1024 + abs_now - abs_rach) % (n_slots_frame * 1024); From 4f9a152f6b848a276a7fcd0fc0fa91756c177312 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 12 Mar 2025 15:17:40 +0100 Subject: [PATCH 27/34] CI: remove timeout for OC CN deployments/undeployments Default value of timeout is 5 minutes. --- ci-scripts/cls_cluster.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 7293e252a1..2ac35a610a 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -72,8 +72,8 @@ def OC_deploy_CN(cmd, ocUserName, ocPassword, ocNamespace, path): succeeded = OC_login(cmd, ocUserName, ocPassword, ocNamespace) if not succeeded: return False, CONST.OC_LOGIN_FAIL - cmd.run('helm uninstall oai5gcn --wait --timeout 60s') - ret = cmd.run(f'helm install --wait --timeout 120s oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.') + cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait') + ret = cmd.run(f'helm install --wait oai5gcn {path}/ci-scripts/charts/oai-5g-basic/.') if ret.returncode != 0: logging.error('OC OAI CN5G: Deployment failed') OC_logout(cmd) @@ -100,10 +100,10 @@ def OC_undeploy_CN(cmd, ocUserName, ocPassword, ocNamespace, path): cmd.run(f'oc logs -f {podName} {ci} &> {path}/logs/{ii}.log &') cmd.run(f'cd {path}/logs && zip -r -qq test_logs_CN.zip *.log') cmd.copyin(f'{path}/logs/test_logs_CN.zip','test_logs_CN.zip') - ret = cmd.run('helm uninstall --wait --timeout 60s oai5gcn') + ret = cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait') if ret.returncode != 0: logging.error('OC OAI CN5G: Undeployment failed') - cmd.run('helm uninstall --wait --timeout 60s oai5gcn') + cmd.run(f'helm list -aq -n {ocNamespace} | xargs -r helm uninstall -n {ocNamespace} --wait') OC_logout(cmd) return False, CONST.OC_PROJECT_FAIL report = cmd.run('oc get pods') From b9a4ebd11f71ad4c5df23ac64a5e1bb32e52d159 Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Wed, 12 Mar 2025 15:20:48 +0100 Subject: [PATCH 28/34] CI: increase timeout for OC RHEL builds --- ci-scripts/cls_cluster.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/cls_cluster.py b/ci-scripts/cls_cluster.py index 2ac35a610a..bfa315b28e 100644 --- a/ci-scripts/cls_cluster.py +++ b/ci-scripts/cls_cluster.py @@ -330,7 +330,7 @@ class Cluster: self._recreate_bc('ran-base', baseTag, 'openshift/ran-base-bc.yaml') ranbase_job = self._start_build('ran-base') attemptedImages += ['ran-base'] - status = ranbase_job is not None and self._wait_build_end([ranbase_job], 800) + status = ranbase_job is not None and self._wait_build_end([ranbase_job], 1000) if not status: logging.error('failure during build of ran-base') self.cmd.run(f'oc logs {ranbase_job} &> cmake_targets/log/ran-base.log') # cannot use cmd.run because of redirect # recover logs by mounting image @@ -392,7 +392,7 @@ class Cluster: gnb_aw2s_job = self._start_build('oai-gnb-aw2s') attemptedImages += ['oai-gnb-aw2s'] - wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 600) + wait = enb_job is not None and gnb_job is not None and gnb_aw2s_job is not None and self._wait_build_end([enb_job, gnb_job, gnb_aw2s_job], 800) if not wait: logging.error('error during build of eNB/gNB') status = status and wait # recover logs @@ -421,7 +421,7 @@ class Cluster: nrue_job = self._start_build('oai-nr-ue') attemptedImages += ['oai-nr-ue'] - wait = nr_cuup_job is not None and lteue_job is not None and nrue_job is not None and self._wait_build_end([nr_cuup_job, lteue_job, nrue_job], 600) + wait = nr_cuup_job is not None and lteue_job is not None and nrue_job is not None and self._wait_build_end([nr_cuup_job, lteue_job, nrue_job], 800) if not wait: logging.error('error during build of nr-cuup/lteUE/nrUE') status = status and wait # recover logs From 39920eb33784bebddb66eb02f4110106b7121a19 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 24 Feb 2025 15:54:23 +0100 Subject: [PATCH 29/34] L2 indication to prepare MSG3 payload in advance This is required to comply with the standard to flush MSG3 buffer in some occasions and to keep preparing MSG3 payload in advance --- openair2/COMMON/mac_messages_types.h | 1 + openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 5 +++ openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 6 +-- .../tests/test_nr_ue_ra_procedures.cpp | 3 ++ openair2/RRC/NR_UE/L2_interface_ue.c | 4 +- openair2/RRC/NR_UE/L2_interface_ue.h | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 41 +++++++++++++------ 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index 882dba7740..ebbda2fc26 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -78,6 +78,7 @@ typedef struct NRRrcMacRaInd_s { typedef struct NRRrcMacMsg3Ind_s { uint16_t rnti; int gnb_id; + bool prepare_payload; } NRRrcMacMsg3Ind; typedef struct NRRrcMacInacInd_s { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 1c5be61884..7cfc5d381a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1003,6 +1003,10 @@ bool init_RA(NR_UE_MAC_INST_t *mac, int frame) } } + // need to ask RRC to send the MSG3 data to transmit if needed (CBRA originating from upper layers) + if (!mac->msg3_C_RNTI && ra->cfra == false) + nr_mac_rrc_msg3_ind(mac->ue_id, 0, true); + NR_RACH_ConfigGenericTwoStepRA_r16_t *twostep_generic = twostep_conf ? &twostep_conf->rach_ConfigGenericTwoStepRA_r16 : NULL; if (ra->ra_type == RA_2_STEP && twostep_generic && twostep_generic->msgA_PreamblePowerRampingStep_r16) prach_resources->preamble_power_ramping_step = *twostep_generic->msgA_PreamblePowerRampingStep_r16 << 1; @@ -1215,6 +1219,7 @@ void nr_ra_contention_resolution_failed(NR_UE_MAC_INST_t *mac) ra->t_crnti = 0; // flush MSG3 buffer free_and_zero(ra->Msg3_buffer); + nr_mac_rrc_msg3_ind(mac->ue_id, 0, true); NR_PRACH_RESOURCES_t *prach_resources = &ra->prach_resources; prach_resources->preamble_tx_counter++; if (prach_resources->preamble_tx_counter == ra->preambleTransMax + 1) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 18ee198582..af2c03827c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3863,7 +3863,7 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, return mac_ce - pdu; } -static void handle_rar_reception(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dlinfo, NR_MAC_RAR *rar, frame_t frame, int slot) +static void handle_rar_reception(NR_UE_MAC_INST_t *mac, NR_MAC_RAR *rar, frame_t frame, int slot) { RAR_grant_t rar_grant; RA_config_t *ra = &mac->ra; @@ -3953,7 +3953,7 @@ static void handle_rar_reception(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t ra->t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8); rnti = ra->t_crnti; if (!mac->msg3_C_RNTI) - nr_mac_rrc_msg3_ind(mac->ue_id, rnti, dlinfo->gNB_index); + nr_mac_rrc_msg3_ind(mac->ue_id, rnti, false); } fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frame_tx, slot_tx, FAPI_NR_UL_CONFIG_TYPE_PUSCH); if (!pdu) @@ -4057,7 +4057,7 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d nr_timer_stop(&ra->response_window_timer); LOG_A(NR_MAC, "[UE %d][RAPROC][%d.%d] Found RAR with the intended RAPID %d\n", mac->ue_id, frame, slot, rarh->RAPID); rar = (NR_MAC_RAR *) (dlsch_buffer + n_subheaders + (n_subPDUs - 1) * sizeof(NR_MAC_RAR)); - handle_rar_reception(mac, dl_info, rar, frame, slot); + handle_rar_reception(mac, rar, frame, slot); if (ra->cfra) nr_ra_succeeded(mac, dl_info->gNB_index, frame, slot); if (get_softmodem_params()->emulate_l1) { diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index 45fc34b47c..1b3646c707 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -32,6 +32,9 @@ softmodem_params_t *get_softmodem_params(void) void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success) { } +void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload) +{ +} tbs_size_t mac_rlc_data_req(const module_id_t module_idP, const rnti_t rntiP, const eNB_index_t eNB_index, diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 74f4170abb..3bfe1d34e0 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -159,11 +159,11 @@ void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id) itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p); } -void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id) +void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload) { MessageDef *message_p = itti_alloc_new_message(TASK_MAC_UE, 0, NR_RRC_MAC_MSG3_IND); NR_RRC_MAC_MSG3_IND (message_p).rnti = rnti; - NR_RRC_MAC_MSG3_IND (message_p).gnb_id = gnb_id; + NR_RRC_MAC_MSG3_IND (message_p).prepare_payload = prepare_payload; itti_send_msg_to_task(TASK_RRC_NRUE, GNB_MODULE_ID_TO_INSTANCE(mod_id), message_p); } diff --git a/openair2/RRC/NR_UE/L2_interface_ue.h b/openair2/RRC/NR_UE/L2_interface_ue.h index 469faf2ece..f394e5e333 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.h +++ b/openair2/RRC/NR_UE/L2_interface_ue.h @@ -37,7 +37,7 @@ void nr_mac_rrc_data_ind_ue(const module_id_t module_id, const uint8_t* pduP, const sdu_size_t pdu_len); void nr_mac_rrc_inactivity_timer_ind(const module_id_t mod_id); -void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, int gnb_id); +void nr_mac_rrc_msg3_ind(const module_id_t mod_id, const int rnti, bool prepare_payload); void nr_ue_rrc_timer_trigger(int instance, int frame, int gnb_id); void nr_mac_rrc_ra_ind(const module_id_t mod_id, bool success); void nsa_sendmsg_to_lte_ue(const void *message, size_t msg_len, Rrc_Msg_Type_t msg_type); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index aa9e38a3c5..d0d1273776 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -335,8 +335,6 @@ static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_inf SI_info->sib1_validity = SIB_VALID; if (rrc->nrRrcState == RRC_STATE_IDLE_NR) { rrc->ra_trigger = RRC_CONNECTION_SETUP; - // preparing RRC setup request payload in advance - nr_rrc_ue_prepare_RRCSetupRequest(rrc); } NR_SIB1_v1700_IEs_t *sib1_v1700 = NULL; @@ -856,15 +854,6 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, nr_timer_stop(&timers->T311); rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT; - // preparing MSG3 for re-establishment in advance - uint8_t buffer[1024]; - int buf_size = do_RRCReestablishmentRequest(buffer, - rrc->reestablishment_cause, - rrc->phyCellID, - rrc->rnti); // old rnti - - nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size); - // apply the default MAC Cell Group configuration // (done at MAC by calling nr_ue_mac_default_configs) @@ -892,6 +881,31 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, return; } +static void nr_rrc_ue_prepare_RRCReestablishmentRequest(NR_UE_RRC_INST_t *rrc) +{ + uint8_t buffer[1024]; + int buf_size = do_RRCReestablishmentRequest(buffer, rrc->reestablishment_cause, rrc->phyCellID, rrc->rnti); // old rnti + nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size); +} + +static void nr_rrc_prepare_msg3_payload(NR_UE_RRC_INST_t *rrc) +{ + if (!IS_SA_MODE(get_softmodem_params())) + return; + switch (rrc->ra_trigger) { + case RRC_CONNECTION_SETUP: + // preparing RRC setup request payload in advance + nr_rrc_ue_prepare_RRCSetupRequest(rrc); + break; + case RRC_CONNECTION_REESTABLISHMENT: + // preparing MSG3 for re-establishment in advance + nr_rrc_ue_prepare_RRCReestablishmentRequest(rrc); + break; + default: + AssertFatal(false, "RA trigger not implemented\n"); + } +} + static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti) { NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; @@ -2045,7 +2059,10 @@ void *rrc_nrue(void *notUsed) break; case NR_RRC_MAC_MSG3_IND: - nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti); + if (NR_RRC_MAC_MSG3_IND(msg_p).prepare_payload) + nr_rrc_prepare_msg3_payload(rrc); + else + nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti); break; case NR_RRC_MAC_RA_IND: From 7ecedfced0f54bbfd5a40185e1d0f011122c4f2c Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 26 Feb 2025 17:28:03 +0100 Subject: [PATCH 30/34] UE fix when completing RA with C-RNTI in MSG3 --- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 16 ++++------------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 4 +++- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 7cfc5d381a..69f1540afc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -1173,24 +1173,16 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame if (ra->cfra) { LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CFRA: RAR successfully received.\n", mac->ue_id, frame, slot); - } else if (ra->ra_type == RA_2_STEP) { - LOG_A(MAC, - "[UE %d][%d.%d][RAPROC] 2-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", - mac->ue_id, - frame, - slot); - mac->crnti = ra->t_crnti; - ra->t_crnti = 0; - LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared response window timer...\n", mac->ue_id, frame, slot); } else { LOG_A(MAC, - "[UE %d][%d.%d][RAPROC] 4-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", + "[UE %d][%d.%d][RAPROC] %d-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", mac->ue_id, frame, - slot); + slot, + ra->ra_type == RA_2_STEP ? 2 : 4); mac->crnti = ra->t_crnti; ra->t_crnti = 0; - LOG_D(MAC, "[UE %d][%d.%d] CBRA: cleared contention resolution timer...\n", mac->ue_id, frame, slot); + nr_timer_stop(&ra->contention_resolution_timer); } ra->RA_active = false; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 3eb4c4d375..ce4b6280e7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1233,7 +1233,9 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent) NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL; - if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList) + if (!pucch_Config + || !pucch_Config->schedulingRequestResourceToAddModList + || pucch_Config->schedulingRequestResourceToAddModList->list.count == 0) return; // cannot schedule SR if there is no schedulingRequestResource configured if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID) From 44692187b89c6249c8f9c78406e5ab486b43c509 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 6 Mar 2025 16:56:43 +0100 Subject: [PATCH 31/34] use sleep to delay UE to allow the convergence of the IIR filter on PRACH noise measurements at gNB side instead of counting frames --- executables/nr-uesoftmodem.c | 4 ++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 - openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 17 ++--------------- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 3 --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 8 +++----- .../tests/test_nr_ue_ra_procedures.cpp | 2 -- 7 files changed, 9 insertions(+), 27 deletions(-) diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index d5f4a528ff..2ba05ae200 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -465,6 +465,10 @@ int main(int argc, char **argv) get_channel_model_mode(uniqCfg); } + // Delay to allow the convergence of the IIR filter on PRACH noise measurements at gNB side + if (IS_SOFTMODEM_RFSIM && !get_softmodem_params()->phy_test) + sleep(3); + if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1) start_oai_nrue_threads(); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 0f76103fcb..9cb15c0283 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -538,7 +538,6 @@ typedef struct NR_UE_MAC_INST_s { NR_UE_L2_STATE_t state; int servCellIndex; long physCellId; - int first_sync_frame; bool get_sib1; bool get_otherSI; NR_MIB_t *mib; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index c0ab5bd310..305f6d404d 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -115,7 +115,6 @@ void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac) { // reset synchornization status - mac->first_sync_frame = -1; mac->state = UE_NOT_SYNC; mac->ra.ra_state = nrRA_UE_IDLE; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 69f1540afc..01b33465e7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -830,21 +830,8 @@ static void setup_ra_response_window(RA_config_t *ra, bool init_RA(NR_UE_MAC_INST_t *mac, int frame) { RA_config_t *ra = &mac->ra; - // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side - LOG_D(NR_MAC, - "ra->ra_state %d frame %d mac->first_sync_frame %d xxx %d", - ra->ra_state, - frame, - mac->first_sync_frame, - ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 10); - if ((mac->first_sync_frame > -1 || get_softmodem_params()->do_ra || get_softmodem_params()->nsa) - && ((MAX_FRAME_NUMBER + frame - mac->first_sync_frame) % MAX_FRAME_NUMBER) > 150) { - ra->ra_state = nrRA_GENERATE_PREAMBLE; - LOG_D(NR_MAC, "PRACH Condition met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); - } else { - LOG_D(NR_MAC, "PRACH Condition not met: ra state %d, frame %d, sync_frame %d\n", ra->ra_state, frame, mac->first_sync_frame); - return false; - } + LOG_D(NR_MAC, "Initialization of RA\n"); + ra->ra_state = nrRA_GENERATE_PREAMBLE; // TODO this piece of code is required to compute MSG3_size that is used by ra_preambles_config function // Not a good implementation, it needs improvements diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index af2c03827c..83bbcadbe5 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -238,9 +238,6 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id) mac->ssb_subcarrier_offset = ssb_subcarrier_offset; mac->dmrs_TypeA_Position = mac->mib->dmrs_TypeA_Position; - if (mac->first_sync_frame == -1) - mac->first_sync_frame = frame; - if (get_softmodem_params()->phy_test) mac->state = UE_CONNECTED; else if (mac->state == UE_NOT_SYNC) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ce4b6280e7..159f6299a1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1335,11 +1335,9 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) RA_config_t *ra = &mac->ra; if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_UE_IDLE) { - bool res = init_RA(mac, frame_tx); - if (res) { - // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a) - ra_resource_selection(mac); - } + init_RA(mac, frame_tx); + // perform the Random Access Resource selection procedure (see clause 5.1.2 and .2a) + ra_resource_selection(mac); } if (mac->state == UE_PERFORMING_RA && ra->ra_state == nrRA_GENERATE_PREAMBLE) diff --git a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp index 1b3646c707..25ea5edcd0 100644 --- a/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp +++ b/openair2/LAYER2/NR_MAC_UE/tests/test_nr_ue_ra_procedures.cpp @@ -106,7 +106,6 @@ TEST(test_init_ra, four_step_cbra) mac.frame_structure.frame_type = TDD; mac.frame_structure.numb_slots_frame = 20; mac.frequency_range = FR1; - mac.first_sync_frame = 0; int frame = 151; init_RA(&mac, frame); @@ -141,7 +140,6 @@ TEST(test_init_ra, four_step_cfra) mac.frame_structure.frame_type = TDD; mac.frame_structure.numb_slots_frame = 20; mac.frequency_range = FR1; - mac.first_sync_frame = 0; int frame = 151; NR_RACH_ConfigDedicated_t rach_ConfigDedicated = {0}; From c456d6951e3e073eef306037c2602eb1c603e0a3 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 13 Mar 2025 16:34:01 +0100 Subject: [PATCH 32/34] Add telnet trigger to force C-RNTI RA on the UE --- common/utils/telnetsrv/telnetsrv_ciUE.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c index dd95f8009c..721cb0e5cd 100644 --- a/common/utils/telnetsrv/telnetsrv_ciUE.c +++ b/common/utils/telnetsrv/telnetsrv_ciUE.c @@ -94,11 +94,20 @@ int force_RRC_IDLE(char *buf, int debug, telnet_printfunc_t prnt) return 0; } +/** @brief Trigger RA with Msg3 C-RNTI */ +int force_crnti_ra(char *buf, int debug, telnet_printfunc_t prnt) +{ + NR_UE_MAC_INST_t *mac = get_mac_inst(0); + trigger_MAC_UE_RA(mac, NULL); + return 0; +} + /* Telnet shell command definitions */ static telnetshell_cmddef_t cicmds[] = { {"sync_state", "[UE_ID(int,opt)]", get_sync_state}, {"force_rlf", "", force_rlf}, {"force_RRC_IDLE", "", force_RRC_IDLE}, + {"force_crnti_ra", "", force_crnti_ra}, {"", "", NULL}, }; From 7ba0613ae85077cbfe4e826ccc1037daa7787e90 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 13 Mar 2025 16:37:13 +0100 Subject: [PATCH 33/34] Add test for C-RNTI RA trigger to 24 PRB RFSIM CI pipeline --- .../xml_files/container_5g_rfsim_24prb.xml | 17 +++++++++++++++++ .../5g_rfsimulator_24prb/docker-compose.yaml | 5 ++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml index 5c2a069122..fe80891678 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_24prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_24prb.xml @@ -34,6 +34,9 @@ 020002 030001 030002 + 040001 + 000004 + 020002 100001 222222 @@ -76,6 +79,12 @@ cacofonix + + IdleSleep + Sleep + 5 + + Ping Ping ext-dn from NR-UE @@ -118,6 +127,14 @@ 90 + + Custom_Command + Force Msg3 C-RNTI RA + cacofonix + echo ciUE force_crnti_ra | nc 192.168.71.150 8091 + yes + + Undeploy_Object true diff --git a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml index ae74649a83..2fd9a3e1fb 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_24prb/docker-compose.yaml @@ -109,7 +109,10 @@ services: - NET_ADMIN # for interface bringup - NET_RAW # for ping environment: - USE_ADDITIONAL_OPTIONS: --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + USE_ADDITIONAL_OPTIONS: --rfsim -r 24 --ssb 24 --numerology 1 -C 3604800000 --uicc0.imsi 208990100001100 + --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time + --telnetsrv --telnetsrv.shrmod ciUE --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091 + ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: - oai-gnb networks: From f0c926306be1c5adb89eee9655a057d119015152 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Tue, 18 Mar 2025 10:32:55 +0100 Subject: [PATCH 34/34] Small fix for jenkins message formatting --- ci-scripts/Jenkinsfile-GitLab-Container | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 37e6a0554b..3ad376f3da 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -65,8 +65,8 @@ pipeline { message += " - ~BUILD-ONLY (execute only build stages)\n" message += " - ~4G-LTE (perform 4G tests)\n" message += " - ~5G-NR (perform 5G tests)\n" - message += " - ~CI (perform both 4G and 5G tests)\n\n" - message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n" + message += " - ~CI (perform both 4G and 5G tests)\n" + message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n\n" message += "Not performing CI due to lack of labels" addGitLabMRComment comment: message error('Not performing CI due to lack of labels')