From acd776fe289037691548b05a0b5695acb3c90f50 Mon Sep 17 00:00:00 2001 From: ndomingues Date: Tue, 14 May 2024 11:35:34 +0100 Subject: [PATCH] Implementation of RA 2-Step MsgB procedures at UE --- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 15 ++- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 125 ++++++++++++++++--- 2 files changed, 122 insertions(+), 18 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 9006c84be2..ffa09ccb25 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -312,10 +312,17 @@ 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 - rnti_t ra_rnti; - /// MsgB-RNTI - rnti_t MsgB_rnti; + /// MsgB SuccessRAR MAC subheader + int8_t MsgB_R; + int8_t MsgB_CH_ACESS_CPEXT; + uint8_t MsgB_TPC; + int8_t MsgB_HARQ_FTI; + uint16_t timing_advance_command; + int8_t PUCCH_RI; + /// RA-rnti + uint16_t ra_rnti; + /// MsgB RNTI + uint16_t MsgB_rnti; /// Temporary CRNTI uint16_t t_crnti; /// number of attempt for rach diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index cdec17bce6..6ba441bad1 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3437,6 +3437,101 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in nr_timer_start(&mac->time_alignment_timer); } +static bool check_ra_contention_resolution(const uint8_t *pdu, const uint8_t *cont_res) +{ + if (IS_SOFTMODEM_IQPLAYER) // Control is bypassed when replaying IQs (BMC) + return true; + for (int i = 0; i < 6; i++) { + if (pdu[i] != cont_res[i]) { + return false; + } + } + return true; +} + +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) +{ + // TS 38.321 - Figure 6.1.5a-1: BI MAC subheader + // TS 38.321 - Figure 6.1.5a-3: SuccessRAR MAC subheader + int n = 0; + uint8_t E = 1; + uint8_t cont_res_id[6]; + RA_config_t *ra = &mac->ra; + + while (n < pdu_len && E) { + E = (pduP[n] >> 7) & 0x1; + uint8_t SUCESS_RAR_header_T1 = (pduP[n] >> 6) & 0x1; + 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; + n++; + } else { // S + n++; + // TS 38.321 - Figure 6.2.3a-2: successRAR + for (int i = 0; i < 6; ++i) + cont_res_id[i] = pduP[n + i]; + n += 6; + // Oct 7 + ra->MsgB_R = 0; + ra->MsgB_CH_ACESS_CPEXT = (pduP[n] >> 5) & 0x3; + ra->MsgB_TPC = (pduP[n] >> 3) & 3; + ra->MsgB_HARQ_FTI = (int8_t)pduP[n] & 0x7; + // Oct 8 + n++; + ra->PUCCH_RI = ((int8_t)pduP[n] >> 4) & 0x0F; + // Oct 8 and Oct 9 + ra->timing_advance_command = ((uint16_t)(pduP[n] & 0xf) << 8) | pduP[n + 1]; + n += 2; + // Oct 10 and Oct 11 + ra->t_crnti = ((uint16_t)pduP[n] << 8) | pduP[n + 1]; + n += 2; + + LOG_D(NR_MAC, + "successRAR: Contention Resolution ID 0x%02x%02x%02x%02x%02x%02x R 0x%01x CH_ACESS_CPEXT 0x%02x TPC 0x%02x " + "HARQ_FTI 0x%03x PUCCH_RI 0x%04x TA 0x%012x CRNTI 0x%04x\n", + cont_res_id[0], + cont_res_id[1], + cont_res_id[2], + cont_res_id[3], + cont_res_id[4], + cont_res_id[5], + ra->MsgB_R, + ra->MsgB_CH_ACESS_CPEXT, + ra->MsgB_TPC, + ra->MsgB_HARQ_FTI, + ra->PUCCH_RI, + ra->timing_advance_command, + ra->t_crnti); + + bool ra_success = check_ra_contention_resolution(cont_res_id, ra->cont_res_id); + + if (ra->RA_active && ra_success) { + 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; + } + } + } else { // RAPID + int RAPID = pduP[n] & 0x3F; + n++; + LOG_D(MAC, "RAPID %d\n", RAPID); + AssertFatal(false, "FallbackRAR not implemented yet!\n"); + } + } + const int ta = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + + set_time_alignment(mac, ta, adjustment_ta, frameP, slot); + return n; +} + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3460,9 +3555,12 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in // // |0|1|2|3|4|5|6|7| bit-wise // |R|R| LCID | -// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described -// in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; -// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders +// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the +// corresponding MAC CE or padding as described +// in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID +// field size is 6 bits; +// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field +// per MAC subheader except for subheaders // corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; // F: lenght of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. @@ -3478,17 +3576,24 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i uint8_t done = 0; RA_config_t *ra = &mac->ra; - if (!pduP){ + if (!pduP) { return; } - LOG_D(MAC, "[%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", + LOG_D(MAC, + "[%d.%d]: processing PDU %d (with length %d) of %d total number of PDUs...\n", frameP, slot, pdu_id, pdu_len, dl_info->rx_ind->number_pdus); + if (ra->ra_type == RA_2_STEP && ra->ra_state == nrRA_WAIT_MSGB) { + int n = nr_ue_validate_successrar(pduP, pdu_len, mac, gNB_index, frameP, slot); + pduP += n; + pdu_len -= n; + } + while (!done && pdu_len > 0){ uint16_t mac_len = 0x0000; uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct @@ -3621,15 +3726,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i pduP[5], pduP[6]); - bool ra_success = true; - if (!IS_SOFTMODEM_IQPLAYER) { // Control is bypassed when replaying IQs (BMC) - for(int i = 0; i < mac_len; i++) { - if(ra->cont_res_id[i] != pduP[i + 1]) { - ra_success = false; - break; - } - } - } + 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);