From 160210ebae4525df5c871c0b222dc903cbd95f56 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:31:40 +0100 Subject: [PATCH] Baseline implementation of RA 2-Step MsgA procedures at UE --- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 4 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 21 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 10 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 197 ++++++++++++++----- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 125 +++++++++++- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 2 +- 6 files changed, 288 insertions(+), 71 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 471b2aee38..e2928b2df4 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -225,7 +225,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t k += kbar; k *= 2; - LOG_I(PHY, "PRACH [UE %d] in frame.slot %d.%d, placing PRACH in position %d, msg1 frequency start %d (k1 %d), preamble_offset %d, first_nonzero_root_idx %d\n", + LOG_I(PHY, + "PRACH [UE %d] in frame.slot %d.%d, placing PRACH in position %d, Msg1/MsgA-Preamble frequency start %d (k1 %d), " + "preamble_offset %d, first_nonzero_root_idx %d\n", Mod_id, frame, slot, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 8eb6b194dc..9006c84be2 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -263,16 +263,17 @@ typedef struct { } NR_UE_SCHEDULING_INFO; typedef enum { - nrRA_UE_IDLE = 0, - nrRA_GENERATE_PREAMBLE = 1, - nrRA_WAIT_RAR = 2, - nrRA_WAIT_CONTENTION_RESOLUTION = 3, - nrRA_SUCCEEDED = 4, - nrRA_FAILED = 5 + nrRA_UE_IDLE, + nrRA_GENERATE_PREAMBLE, + nrRA_WAIT_RAR, + nrRA_WAIT_MSGB, + nrRA_WAIT_CONTENTION_RESOLUTION, + nrRA_SUCCEEDED, + nrRA_FAILED, } nrRA_UE_state_t; static const char *const nrra_ue_text[] = - {"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"}; + {"UE_IDLE", "GENERATE_PREAMBLE", "WAIT_RAR", "WAIT_MSGB", "WAIT_CONTENTION_RESOLUTION", "RA_SUCCEEDED", "RA_FAILED"}; typedef struct { /// PRACH format retrieved from prach_ConfigIndex @@ -311,8 +312,10 @@ typedef struct { nr_ra_type_t ra_type; /// RA rx frame offset: compensate RA rx offset introduced by OAI gNB. uint8_t RA_offset; - /// RA-rnti - uint16_t ra_rnti; + /// RA-RNTI + rnti_t ra_rnti; + /// MsgB-RNTI + rnti_t MsgB_rnti; /// Temporary CRNTI uint16_t t_crnti; /// number of attempt for rach diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 1f53812dec..6feca8756e 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -304,6 +304,10 @@ 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); /* \brief Function called by PHY to retrieve information to be transmitted using the RA procedure. @@ -331,7 +335,7 @@ void nr_get_prach_resources(NR_UE_MAC_INST_t *mac, NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigDedicated_t * rach_ConfigDedicated); -void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); +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); void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac); @@ -356,7 +360,7 @@ 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 nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max); +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, fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config_pdu, @@ -410,7 +414,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci, csi_payload_t *csi_report, RAR_grant_t *rar_grant, - uint16_t rnti, + rnti_t rnti, int ss_type, const nr_dci_format_t dci_format); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index eadc1677f4..da183b3b14 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -191,10 +191,28 @@ void init_RA(NR_UE_MAC_INST_t *mac, break; } - if (nr_rach_ConfigCommon->ext1) { - if (nr_rach_ConfigCommon->ext1->ra_PrioritizationForAccessIdentity_r16){ + 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; + } 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; + } } } @@ -637,7 +655,7 @@ static uint8_t *fill_msg3_crnti_pdu(RA_config_t *ra, uint8_t *pdu, uint16_t crnt static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int TBS_max) { RA_config_t *ra = &mac->ra; - // regular MSG3 with PDU coming from higher layers + // regular Msg3/MsgA_PUSCH with PDU coming from higher layers *(NR_MAC_SUBHEADER_FIXED *)pdu = (NR_MAC_SUBHEADER_FIXED){.LCID = UL_SCH_LCID_CCCH}; pdu += sizeof(NR_MAC_SUBHEADER_FIXED); tbs_size_t len = mac_rlc_data_req(mac->ue_id, @@ -651,7 +669,7 @@ static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int (char *)pdu, 0, 0); - AssertFatal(len > 0, "no data for Msg.3\n"); + AssertFatal(len > 0, "no data for Msg3/MsgA_PUSCH\n"); // UE Contention Resolution Identity // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to determine whether or not the // Random Access Procedure has been successful after reception of Msg4 @@ -661,7 +679,7 @@ static uint8_t *fill_msg3_pdu_from_rlc(NR_UE_MAC_INST_t *mac, uint8_t *pdu, int return pdu; } -void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) +void nr_get_Msg3_MsgA_PUSCH_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) { RA_config_t *ra = &mac->ra; @@ -674,10 +692,10 @@ void nr_get_msg3_payload(NR_UE_MAC_INST_t *mac, uint8_t *buf, int TBS_max) uint8_t *pdu = buf; if (ra->msg3_C_RNTI) pdu = fill_msg3_crnti_pdu(ra, pdu, mac->crnti); - else + else pdu = fill_msg3_pdu_from_rlc(mac, pdu, TBS_max); - AssertFatal(TBS_max >= pdu - buf, "Allocated resources are not enough for Msg3!\n"); + AssertFatal(TBS_max >= pdu - buf, "Allocated resources are not enough for Msg3/MsgA_PUSCH!\n"); // Padding: fill remainder with 0 LOG_D(NR_MAC, "Remaining %ld bytes, filling with padding\n", pdu - buf); while (pdu < buf + TBS_max - sizeof(NR_MAC_SUBHEADER_FIXED)) { @@ -709,13 +727,24 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB // Delay init RA procedure to allow the convergence of the IIR filter on PRACH noise measurements at gNB side if (ra->ra_state == nrRA_UE_IDLE) { - 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; - } 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; - } + 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; + } } 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); @@ -776,8 +805,7 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB nr_ra_succeeded(mac, gNB_id, frame, nr_slot_tx); } - } else if (ra->RA_window_cnt == 0 && !ra->RA_RAPID_found) { - + } 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); @@ -809,49 +837,102 @@ void nr_ue_get_rach(NR_UE_MAC_INST_t *mac, int CC_id, frame_t frame, uint8_t gNB } } +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__); - NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17); const int mu = mac->current_DL_BWP->scs; const int slots_per_ms = nr_slots_per_frame[mu] / 10; - + const int ra_Offset_slots = ra->RA_offset * nr_slots_per_frame[mu]; 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 - int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; - - switch (ra_ResponseWindow) { - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: - ra->RA_window_cnt += 1; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2: - ra->RA_window_cnt += 2; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4: - ra->RA_window_cnt += 4; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8: - ra->RA_window_cnt += 8; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10: - ra->RA_window_cnt += 10; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20: - ra->RA_window_cnt += 20; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40: - ra->RA_window_cnt += 40; - break; - case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80: - ra->RA_window_cnt += 80; - break; - } + 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); } //////////////////////////////////////////////////////////////////////////// @@ -869,7 +950,7 @@ void nr_ue_contention_resolution(NR_UE_MAC_INST_t *mac, int cc_id, frame_t frame ra->t_crnti = 0; nr_timer_stop(&ra->contention_resolution_timer); // Signal PHY to quit RA procedure - LOG_E(MAC, "[UE %d] CB-RA: Contention resolution timer has expired, RA procedure has failed...\n", mac->ue_id); + 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); } } @@ -883,14 +964,27 @@ void nr_ra_succeeded(NR_UE_MAC_INST_t *mac, const uint8_t gNB_index, const frame RA_config_t *ra = &mac->ra; if (ra->cfra) { - LOG_I(MAC, "[UE %d][%d.%d][RAPROC] RA procedure succeeded. CF-RA: RAR successfully received.\n", mac->ue_id, frame, slot); + 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", + 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] RA procedure succeeded. CB-RA: Contention Resolution is successful.\n", mac->ue_id, frame, slot); + LOG_A(MAC, + "[UE %d][%d.%d][RAPROC] 4-Step RA procedure succeeded. CBRA: Contention Resolution is successful.\n", + 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] CB-RA: cleared contention resolution timer...\n", mac->ue_id, frame, slot); + 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); @@ -945,7 +1039,6 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(mac, prach_resources, CC_id); } else { - // Resetting RA window nr_get_RA_window(mac); } } @@ -958,7 +1051,7 @@ void trigger_MAC_UE_RA(NR_UE_MAC_INST_t *mac) mac->ra.msg3_C_RNTI = true; } -void prepare_msg4_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) +void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack) { NR_UE_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[pid]; int sched_slot = current_harq->ul_slot; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index a076829a8a..b07e90e614 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -574,7 +574,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, dci_pdu_rel15_t *dci, csi_payload_t *csi_report, RAR_grant_t *rar_grant, - uint16_t rnti, + rnti_t rnti, int ss_type, const nr_dci_format_t dci_format) { @@ -584,6 +584,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int rnti_type = get_rnti_type(mac, rnti); NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; NR_UE_ServingCell_Info_t *sc_info = &mac->sc_info; + int scs = current_UL_BWP->scs; // Common configuration pusch_config_pdu->dmrs_config_type = pusch_dmrs_type1; @@ -596,8 +597,69 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, int dmrslength = 1; NR_PUSCH_Config_t *pusch_Config = current_UL_BWP->pusch_Config; - if (rar_grant) { + AssertFatal(!((mac->ra.ra_state < nrRA_SUCCEEDED && mac->ra.ra_type == RA_2_STEP) && rar_grant), "logic error: Is not possible to have both msgA_pusch_resource and rar_grant\n"); + if (mac->ra.ra_state < nrRA_SUCCEEDED && mac->ra.ra_type == RA_2_STEP) { + NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource = + current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_PUSCH_ResourceGroupA_r16; + int S = 0; + int L = 0; + SLIV2SL(*msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16, &S, &L); + tda_info->k2 = msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16; + tda_info->startSymbolIndex = S; + tda_info->nrOfSymbols = L; + l_prime_mask = get_l_prime(tda_info->nrOfSymbols, + tda_info->mapping_type, + add_pos, + dmrslength, + tda_info->startSymbolIndex, + mac->dmrs_TypeA_Position); + LOG_I(NR_MAC, + "MSGA PUSCH start_sym:%d NR Symb:%d mappingtype:%d, DMRS_MASK:%x\n", + pusch_config_pdu->start_symbol_index, + pusch_config_pdu->nr_of_symbols, + tda_info->mapping_type, + l_prime_mask); + + LOG_D(NR_MAC, + "sc_info->initial_ul_BWPStart = %d sc_info->initial_ul_BWPSize = %d\n", + sc_info->initial_ul_BWPStart, + sc_info->initial_ul_BWPSize); + pusch_config_pdu->handle = 0; + pusch_config_pdu->rb_size = msgA_PUSCH_Resource->nrofPRBs_PerMsgA_PO_r16; + pusch_config_pdu->mcs_table = 0; + pusch_config_pdu->frequency_hopping = msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 ? *msgA_PUSCH_Resource->msgA_IntraSlotFrequencyHopping_r16 : 0; + pusch_config_pdu->dmrs_ports = 1; // is in SIB1 nrofDMRS_Sequences_r16? + pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data + pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + pusch_config_pdu->ul_dmrs_symb_pos = get_l_prime(3, 0, pusch_dmrs_pos2, pusch_len1, 10, mac->dmrs_TypeA_Position); + pusch_config_pdu->transform_precoding = + *mac->current_UL_BWP->msgA_ConfigCommon_r16->msgA_PUSCH_Config_r16->msgA_TransformPrecoder_r16; + pusch_config_pdu->rb_bitmap[0] = 0; + pusch_config_pdu->rb_start = msgA_PUSCH_Resource->frequencyStartMsgA_PUSCH_r16; // rb_start depends on the RO + pusch_config_pdu->bwp_size = sc_info->initial_ul_BWPSize; + pusch_config_pdu->bwp_start = sc_info->initial_ul_BWPStart; + pusch_config_pdu->subcarrier_spacing = scs; + pusch_config_pdu->cyclic_prefix = 0; + pusch_config_pdu->uplink_frequency_shift_7p5khz = 0; + pusch_config_pdu->vrb_to_prb_mapping = 0; + pusch_config_pdu->dmrs_config_type = 0; + pusch_config_pdu->data_scrambling_id = mac->physCellId; + pusch_config_pdu->ul_dmrs_scrambling_id = mac->physCellId; + pusch_config_pdu->scid = 0; + pusch_config_pdu->resource_alloc = 1; + pusch_config_pdu->tx_direct_current_location = 0; + pusch_config_pdu->mcs_index = msgA_PUSCH_Resource->msgA_MCS_r16; + pusch_config_pdu->qam_mod_order = nr_get_Qm_dl(pusch_config_pdu->mcs_index, 0); + pusch_config_pdu->start_symbol_index = S; + pusch_config_pdu->nr_of_symbols = L; + pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 + pusch_config_pdu->pusch_data.harq_process_id = 0; + pusch_config_pdu->pusch_data.num_cb = 0; + pusch_config_pdu->tbslbrm = 0; + pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, 0); + + } else if (rar_grant) { // Note: for Msg3 or MsgA PUSCH transmission the N_PRB_oh is always set to 0 int ibwp_start = sc_info->initial_ul_BWPStart; int ibwp_size = sc_info->initial_ul_BWPSize; @@ -1501,8 +1563,8 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) TBS_bytes, ra->ra_state); ulcfg_pdu->pusch_config_pdu.tx_request_body.fapiTxPdu = NULL; - if (ra->ra_state == nrRA_WAIT_RAR && !ra->cfra) { - nr_get_msg3_payload(mac, ulsch_input_buffer, TBS_bytes); + if ((ra->ra_state == nrRA_WAIT_RAR || ra->ra_state == nrRA_WAIT_MSGB) && !ra->cfra) { + nr_get_Msg3_MsgA_PUSCH_payload(mac, ulsch_input_buffer, TBS_bytes); for (int k = 0; k < TBS_bytes; k++) { LOG_D(NR_MAC, "(%i): 0x%x\n", k, ulsch_input_buffer[k]); } @@ -1553,6 +1615,9 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-Msg3 transmitted\n", frame_tx, slot_tx); nr_Msg3_transmitted(mac, cc_id, frame_tx, slot_tx, gNB_index); } + if (ra->ra_state == nrRA_WAIT_MSGB && !ra->cfra) { + LOG_A(NR_MAC, "[RAPROC][%d.%d] RA-MsgA-PUSCH transmitted\n", frame_tx, slot_tx); + } } ulcfg_pdu++; } @@ -2867,7 +2932,57 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, sub_fra if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL) mac->if_module->scheduled_response(&scheduled_response); - nr_Msg1_transmitted(mac); + if (ra->ra_type == RA_4_STEP) { + nr_Msg1_transmitted(mac); + } else if (ra->ra_type == RA_2_STEP) { + const NR_MsgA_ConfigCommon_r16_t *msgacc = mac->current_UL_BWP->msgA_ConfigCommon_r16; + int mu = (int)*msgacc->rach_ConfigCommonTwoStepRA_r16.msgA_SubcarrierSpacing_r16; + + 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 = nr_slots_per_frame[mu]; + 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; + + fapi_nr_ul_config_request_pdu_t *pdu = + lockGet_ul_config(mac, msgA_pusch_frame, msgA_pusch_slot, FAPI_NR_UL_CONFIG_TYPE_PUSCH); + if (!pdu) + return; + + // Config Msg3/MsgA-PUSCH PDU + NR_tda_info_t tda_info = {0}; + AssertFatal(msgA_PUSCH_Resource->startSymbolAndLengthMsgA_PO_r16, + "Only SLIV based on startSymbolAndLengthMsgA_PO_r16 implemented\n"); + + int ret = nr_config_pusch_pdu(mac, + &tda_info, + &pdu->pusch_config_pdu, + NULL, + NULL, + NULL, + mac->ra.ra_rnti, + NR_SearchSpace__searchSpaceType_PR_common, + NR_DCI_NONE); + + if (ret != 0) + remove_ul_config_last_item(pdu); + release_ul_config(pdu, false); + + // Compute MsgB RNTI + ra->MsgB_rnti = + nr_get_MsgB_rnti(prach_occasion_info_p->start_symbol, prach_occasion_info_p->slot, prach_occasion_info_p->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; + mac->crnti = 0; + ra->ra_rnti = 0; + } 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 } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 2da11f109c..c4faefa0fa 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1127,7 +1127,7 @@ void update_harq_status(NR_UE_MAC_INST_t *mac, uint8_t harq_pid, uint8_t ack_nac LOG_D(PHY,"Updating harq_status for harq_id %d, ack/nak %d\n", harq_pid, current_harq->ack); // we can prepare feedback for MSG4 in advance if (mac->ra.ra_state == nrRA_WAIT_CONTENTION_RESOLUTION) - prepare_msg4_feedback(mac, harq_pid, ack_nack); + prepare_msg4_msgb_feedback(mac, harq_pid, ack_nack); else { current_harq->ack = ack_nack; current_harq->ack_received = true;