Implementation of RA 2-Step MsgB procedures at gNB

This commit is contained in:
ndomingues
2024-10-09 09:11:16 +01:00
parent 19e0df13a9
commit 9d786bdee7
6 changed files with 140 additions and 49 deletions
+125 -36
View File
@@ -553,6 +553,76 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
} }
} }
int nr_fill_successrar(const NR_UE_sched_ctrl_t *ue_sched_ctl,
rnti_t crnti,
const unsigned char *ue_cont_res_id,
uint8_t resource_indicator,
uint8_t timing_indicator,
unsigned char *mac_pdu,
int mac_pdu_length)
{
LOG_D(NR_MAC, "mac_pdu_length = %d\n", mac_pdu_length);
int timing_advance_cmd = ue_sched_ctl->ta_update;
// TS 38.321 - Figure 6.1.5a-1: BI MAC subheader
NR_RA_HEADER_BI_MSGB *bi = (NR_RA_HEADER_BI_MSGB *)&mac_pdu[mac_pdu_length];
mac_pdu_length += sizeof(NR_RA_HEADER_BI_MSGB);
bi->E = 1;
bi->T1 = 0;
bi->T2 = 0;
bi->R = 0;
bi->BI = 0; // BI = 0, 5ms
// TS 38.321 - Figure 6.1.5a-3: SuccessRAR MAC subheader
NR_RA_HEADER_SUCCESS_RAR_MSGB *SUCESS_RAR_header = (NR_RA_HEADER_SUCCESS_RAR_MSGB *)&mac_pdu[mac_pdu_length];
mac_pdu_length += sizeof(NR_RA_HEADER_SUCCESS_RAR_MSGB);
SUCESS_RAR_header->E = 0;
SUCESS_RAR_header->T1 = 0;
SUCESS_RAR_header->T2 = 1;
SUCESS_RAR_header->S = 0;
SUCESS_RAR_header->R = 0;
// TS 38.321 - Figure 6.2.3a-2: successRAR
NR_MAC_SUCCESS_RAR *successRAR = (NR_MAC_SUCCESS_RAR *)&mac_pdu[mac_pdu_length];
mac_pdu_length += sizeof(NR_MAC_SUCCESS_RAR);
successRAR->CONT_RES_1 = ue_cont_res_id[0];
successRAR->CONT_RES_2 = ue_cont_res_id[1];
successRAR->CONT_RES_3 = ue_cont_res_id[2];
successRAR->CONT_RES_4 = ue_cont_res_id[3];
successRAR->CONT_RES_5 = ue_cont_res_id[4];
successRAR->CONT_RES_6 = ue_cont_res_id[5];
successRAR->R = 0;
successRAR->CH_ACESS_CPEXT = 1;
successRAR->TPC = ue_sched_ctl->tpc0;
successRAR->HARQ_FTI = timing_indicator;
successRAR->PUCCH_RI = resource_indicator;
successRAR->TA1 = (uint8_t)(timing_advance_cmd >> 8); // 4 MSBs of timing advance;
successRAR->TA2 = (uint8_t)(timing_advance_cmd & 0xff); // 8 LSBs of timing advance;
successRAR->CRNTI_1 = (uint8_t)(crnti >> 8); // 8 MSBs of rnti
successRAR->CRNTI_2 = (uint8_t)(crnti & 0xff); // 8 LSBs of rnti
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",
successRAR->CONT_RES_1,
successRAR->CONT_RES_2,
successRAR->CONT_RES_3,
successRAR->CONT_RES_4,
successRAR->CONT_RES_5,
successRAR->CONT_RES_6,
successRAR->R,
successRAR->CH_ACESS_CPEXT,
successRAR->TPC,
successRAR->HARQ_FTI,
successRAR->PUCCH_RI,
timing_advance_cmd,
crnti);
LOG_D(NR_MAC, "mac_pdu_length = %d\n", mac_pdu_length);
return mac_pdu_length;
}
static bool ra_contains_preamble(const NR_RA_t *ra, uint16_t preamble_index) static bool ra_contains_preamble(const NR_RA_t *ra, uint16_t preamble_index)
{ {
for (int j = 0; j < ra->preambles.num_preambles; j++) { for (int j = 0; j < ra->preambles.num_preambles; j++) {
@@ -1854,33 +1924,32 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac,
LOG_D(NR_MAC, "numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); LOG_D(NR_MAC, "numDlDci: %i\n", pdcch_pdu_rel15->numDlDci);
} }
static void nr_generate_Msg4(module_id_t module_idP, static void nr_generate_Msg4_MsgB(module_id_t module_idP,
int CC_id, int CC_id,
frame_t frameP, frame_t frameP,
sub_frame_t slotP, sub_frame_t slotP,
NR_RA_t *ra, NR_RA_t *ra,
nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_dl_tti_request_t *DL_req,
nfapi_nr_tx_data_request_t *TX_req) nfapi_nr_tx_data_request_t *TX_req)
{ {
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP;
// if it is a DL slot, if the RA is in MSG4 state // if it is a DL slot, if the RA is in MSG4 state
if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) {
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_SearchSpace_t *ss = ra->ra_ss;
const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4";
NR_ControlResourceSet_t *coreset = ra->coreset;
AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str);
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; uint16_t mac_sdu_length = 0;
NR_SearchSpace_t *ss = ra->ra_ss;
NR_ControlResourceSet_t *coreset = ra->coreset; NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti);
AssertFatal(coreset!=NULL,"Coreset cannot be null for RA-Msg4\n"); if (!UE) {
LOG_E(NR_MAC, "want to generate %s, but rnti %04x not in the table\n", ra_type_str, ra->rnti);
uint16_t mac_sdu_length = 0; return;
NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti);
if (!UE) {
LOG_E(NR_MAC, "want to generate Msg4, but rnti %04x not in the table\n", ra->rnti);
return;
} }
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
@@ -1975,7 +2044,8 @@ static void nr_generate_Msg4(module_id_t module_idP,
} }
else { else {
uint8_t subheader_len = (mac_sdu_length < 256) ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG); uint8_t subheader_len = (mac_sdu_length < 256) ? sizeof(NR_MAC_SUBHEADER_SHORT) : sizeof(NR_MAC_SUBHEADER_LONG);
pdu_length = mac_sdu_length + subheader_len + 7; //7 is contetion resolution length pdu_length = mac_sdu_length + subheader_len + 13; // 13 is contention resolution length of msgB. It is divided into 3 parts:
// BI MAC subheader (1 Oct) + SuccessRAR MAC subheader (1 Oct) + SuccessRAR (11 Oct)
} }
// increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size // increase PRBs until we get to BWPSize or TBS is bigger than MAC PDU size
@@ -1990,7 +2060,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
rbSize, msg4_tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3; rbSize, msg4_tda.nrOfSymbols, dmrs_info.N_PRB_DMRS * dmrs_info.N_DMRS_SLOT, 0, tb_scaling,1) >> 3;
} while (tb_size < pdu_length && mcsIndex<=28); } while (tb_size < pdu_length && mcsIndex<=28);
AssertFatal(tb_size >= pdu_length,"Cannot allocate Msg4\n"); AssertFatal(tb_size >= pdu_length, "Cannot allocate %s\n", ra_type_str);
int i = 0; int i = 0;
uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx]; uint16_t *vrb_map = cc[CC_id].vrb_map[beam.idx];
@@ -2053,9 +2123,22 @@ static void nr_generate_Msg4(module_id_t module_idP,
uint8_t *buf = (uint8_t *) harq->transportBlock; uint8_t *buf = (uint8_t *) harq->transportBlock;
// Bytes to be transmitted // Bytes to be transmitted
if (harq->round == 0) { if (harq->round == 0) {
// UE Contention Resolution Identity MAC CE uint16_t mac_pdu_length = 0;
uint16_t mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); if (ra->ra_type == RA_4_STEP) {
LOG_D(NR_MAC,"Encoded contention resolution mac_pdu_length %d\n",mac_pdu_length); // UE Contention Resolution Identity MAC CE
mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id);
} else if (ra->ra_type == RA_2_STEP) {
mac_pdu_length = nr_fill_successrar(nr_mac->sched_ctrlCommon,
ra->rnti,
ra->cont_res_id,
pucch->resource_indicator,
pucch->timing_indicator,
buf,
mac_pdu_length);
} else {
AssertFatal(false, "RA type %d not implemented!\n", ra->ra_type);
}
uint8_t buffer[CCCH_SDU_SIZE]; uint8_t buffer[CCCH_SDU_SIZE];
uint8_t mac_subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT); uint8_t mac_subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT);
// Get RLC data on the SRB (RRCSetup, RRCReestablishment) // Get RLC data on the SRB (RRCSetup, RRCReestablishment)
@@ -2140,7 +2223,7 @@ static void nr_generate_Msg4(module_id_t module_idP,
if (pucch == NULL) { if (pucch == NULL) {
LOG_A(NR_MAC, "(UE RNTI 0x%04x) Skipping Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti); LOG_A(NR_MAC, "(UE RNTI 0x%04x) Skipping Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti);
UE->Msg4_ACKed = true; UE->Msg4_MsgB_ACKed = true;
// Pause scheduling according to: // Pause scheduling according to:
// 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs
@@ -2151,17 +2234,18 @@ static void nr_generate_Msg4(module_id_t module_idP,
nr_clear_ra_proc(ra); nr_clear_ra_proc(ra);
} else { } else {
ra->ra_state = nrRA_WAIT_Msg4_ACK; ra->ra_state = nrRA_WAIT_Msg4_MsgB_ACK;
LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size); LOG_I(NR_MAC,"UE %04x Generate msg4: feedback at %4d.%2d, payload %d bytes, next state WAIT_Msg4_ACK\n", ra->rnti, pucch->frame, pucch->ul_slot, harq->tb_size);
} }
} }
} }
static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) static void nr_check_Msg4_MsgB_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra)
{ {
const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4";
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti); NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti);
if (!UE) { if (!UE) {
LOG_E(NR_MAC, "Cannot check Msg4 ACK/NACK, rnti %04x not in the table\n", ra->rnti); LOG_E(NR_MAC, "Cannot check %s ACK/NACK, rnti %04x not in the table\n", ra_type_str, ra->rnti);
return; return;
} }
const int current_harq_pid = ra->harq_pid; const int current_harq_pid = ra->harq_pid;
@@ -2173,10 +2257,14 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s
if (harq->is_waiting == 0) { if (harq->is_waiting == 0) {
if (harq->round == 0) { if (harq->round == 0) {
if (UE->Msg4_ACKed) { if (UE->Msg4_MsgB_ACKed) {
LOG_A(NR_MAC, "(UE RNTI 0x%04x) Received Ack of RA-Msg4. CBRA procedure succeeded!\n", ra->rnti); LOG_A(NR_MAC,
"%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n",
frame, slot, ra->rnti, ra_type_str);
} else { } else {
LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at Msg4!\n", frame, slot, ra->rnti); LOG_I(NR_MAC,
"%4d.%2d UE %04x: RA Procedure failed at %s!\n",
frame, slot, ra->rnti, ra_type_str);
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
} }
@@ -2192,8 +2280,8 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s
remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid);
} }
} else { } else {
LOG_I(NR_MAC, "(UE %04x) Received Nack of RA-Msg4. Preparing retransmission!\n", ra->rnti); LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", ra->rnti, nrra_text[ra->ra_state]);
ra->ra_state = nrRA_Msg4; ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB;
} }
} }
} }
@@ -2365,10 +2453,11 @@ void nr_schedule_RA(module_id_t module_idP,
nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req);
break; break;
case nrRA_Msg4: case nrRA_Msg4:
nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); case nrRA_MsgB:
nr_generate_Msg4_MsgB(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req);
break; break;
case nrRA_WAIT_Msg4_ACK: case nrRA_WAIT_Msg4_MsgB_ACK:
nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); nr_check_Msg4_MsgB_Ack(module_idP, CC_id, frameP, slotP, ra);
break; break;
default: default:
break; break;
@@ -627,7 +627,7 @@ static void pf_dl(module_id_t module_id,
/* Loop UE_info->list to check retransmission */ /* Loop UE_info->list to check retransmission */
UE_iterator(UE_list, UE) { UE_iterator(UE_list, UE) {
if (UE->Msg4_ACKed != true) if (!UE->Msg4_MsgB_ACKed)
continue; continue;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
@@ -2476,10 +2476,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator); UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator);
UE->CellGroup = CellGroup; UE->CellGroup = CellGroup;
if (CellGroup) UE->Msg4_MsgB_ACKed = CellGroup != NULL;
UE->Msg4_ACKed = true;
else
UE->Msg4_ACKed = false;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
memset(sched_ctrl, 0, sizeof(*sched_ctrl)); memset(sched_ctrl, 0, sizeof(*sched_ctrl));
@@ -1041,8 +1041,8 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
remove_front_nr_list(&sched_ctrl->feedback_dl_harq); remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value); LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value);
handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max); handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max);
if (!UE->Msg4_ACKed && harq_value == 0 && harq_confidence == 0) if (!UE->Msg4_MsgB_ACKed && harq_value == 0 && harq_confidence == 0)
UE->Msg4_ACKed = true; UE->Msg4_MsgB_ACKed = true;
if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++;
} }
@@ -921,7 +921,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// The UE identified by C-RNTI still exists at the gNB // The UE identified by C-RNTI still exists at the gNB
// Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration // Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration
UE->Msg4_ACKed = false; UE->Msg4_MsgB_ACKed = false;
nr_mac_reset_ul_failure(&UE->UE_sched_ctrl); nr_mac_reset_ul_failure(&UE->UE_sched_ctrl);
// Reset HARQ processes // Reset HARQ processes
reset_dl_harq_list(&UE->UE_sched_ctrl); reset_dl_harq_list(&UE->UE_sched_ctrl);
@@ -956,8 +956,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// the function is only called to decode the contention resolution sub-header // the function is only called to decode the contention resolution sub-header
nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1); nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1);
LOG_I(NR_MAC, "Activating scheduling RA-Msg4 for TC_RNTI 0x%04x (state %s)\n", ra->rnti, nrra_text[ra->ra_state]); LOG_I(NR_MAC,
ra->ra_state = nrRA_Msg4; "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n",
ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4",
ra->rnti,
nrra_text[ra->ra_state]);
ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4;
LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", ra->rnti, nrra_text[ra->ra_state]);
return; return;
} }
} }
@@ -1794,7 +1799,7 @@ static void pf_ul(module_id_t module_id,
UE_iterator(UE_list, UE) { UE_iterator(UE_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (UE->Msg4_ACKed != true || sched_ctrl->ul_failure) if (!UE->Msg4_MsgB_ACKed || sched_ctrl->ul_failure)
continue; continue;
LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti);
+2 -2
View File
@@ -121,7 +121,7 @@ typedef enum {
nrRA_Msg3_retransmission, nrRA_Msg3_retransmission,
nrRA_Msg4, nrRA_Msg4,
nrRA_MsgB, nrRA_MsgB,
nrRA_WAIT_Msg4_ACK, nrRA_WAIT_Msg4_MsgB_ACK,
} RA_gNB_state_t; } RA_gNB_state_t;
static const char *const nrra_text[] = static const char *const nrra_text[] =
@@ -758,7 +758,7 @@ typedef struct {
NR_UE_NR_Capability_t *capability; NR_UE_NR_Capability_t *capability;
// UE selected beam index // UE selected beam index
uint8_t UE_beam_index; uint8_t UE_beam_index;
bool Msg4_ACKed; bool Msg4_MsgB_ACKed;
float ul_thr_ue; float ul_thr_ue;
float dl_thr_ue; float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook; long pdsch_HARQ_ACK_Codebook;