From 939ce850a55e506b3c9bcb88980d62087cd54376 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 16 Oct 2024 10:12:57 +0200 Subject: [PATCH 01/24] 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 02/24] 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 03/24] 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 04/24] 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 05/24] 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 06/24] 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 07/24] 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 08/24] 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 09/24] 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 10/24] 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 11/24] 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 12/24] 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 13/24] 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 14/24] 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 15/24] 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 16/24] 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 17/24] 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 18/24] 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 19/24] 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 20/24] 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 21/24] 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 39920eb33784bebddb66eb02f4110106b7121a19 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 24 Feb 2025 15:54:23 +0100 Subject: [PATCH 22/24] 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 23/24] 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 24/24] 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};