Commit 8ea95a0e authored by Robert Schmidt's avatar Robert Schmidt

CFRA: mark RA complete when sending Msg2

The current contention-free random access forces a "Msg3" (which does
not exist in CFRA) to be received by a UE. Sometimes, this "Msg3" is not
received (for whatever reason), and the MAC declare that RA failed.

This is problematic, as the spec says that RA is complete once Msg2 is
received by the UE. To avoid this, inconditionally mark RA as complete
as soon as we receive an indication of Msg3 (DTX or not).

Note that after this change, we still send a UL grant in Msg2. This is
because 38.321 §5.1.4 is not clear to me whether we should send UL grant
(it does not explicitly exclude it), and it says

> 3> if the Random Access Response includes a MAC subPDU with RAPID only:
> [...]
>   4> indicate the reception of an acknowledgement for SI request to
>      upper layers.

which is NOT the case (but then I don't know/think we can have CFRA for
SI request?).  Since it also works with COTS UE, I leave Msg3 for the
moment.

The reason to not directly mark RA as complete when sending Msg2 is
because of possible retransmissions in do-ra mode. In fact, in do-ra,
there might already be data awaiting. In that case, the DLSCH scheduler
schedules data _in the same slot as Msg2_, which the UE does not decode,
leading to retransmissions.
parent f0151c21
...@@ -785,6 +785,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ...@@ -785,6 +785,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
{ {
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
NR_RA_t *ra = UE->ra; NR_RA_t *ra = UE->ra;
DevAssert(!ra->cfra);
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
...@@ -1451,6 +1452,11 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1451,6 +1452,11 @@ static void nr_generate_Msg2(module_id_t module_idP,
return; return;
const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
// check the feasibility of Msg3, the actual Msg3 allocation
// is further below. In the case of CFRA, we don't need Msg3, but 38.321
// §5.1.4 does not clearly exclude Msg3, and UL TA might still be useful.
// Before the change in this commit, we used CFRA but required Msg3, which
// COTS UE would often (but not always) send.
bool ret = get_feasible_msg3_tda(scc, bool ret = get_feasible_msg3_tda(scc,
get_delta_for_k2(ul_bwp->scs), get_delta_for_k2(ul_bwp->scs),
ul_bwp->tdaList_Common, ul_bwp->tdaList_Common,
...@@ -1523,6 +1529,7 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1523,6 +1529,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
return; return;
} }
// get an actual Msg3 allocation in CBRA
bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, UE); bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, UE);
if (!msg3_ret) { if (!msg3_ret) {
reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam);
...@@ -1609,9 +1616,22 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1609,9 +1616,22 @@ static void nr_generate_Msg2(module_id_t module_idP,
// DL TX request // DL TX request
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs];
// Program UL processing for Msg3 // If CFRA: 38.321 §5.1.4 does not clearly say (to me) if UL grant should be
// dropped or not, and COTS UE would often send Msg3 if we configured CFRA
// but required Msg3. Also, "if RAR includes a MAC subPDU with RAPID: [...]
// indicate the reception of an acknowledgement for SI request to upper
// layers." which is not the case here.
nr_add_msg3(module_idP, CC_id, frameP, slotP, UE, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); nr_add_msg3(module_idP, CC_id, frameP, slotP, UE, (uint8_t *)&tx_req->TLVs[0].value.direct[0]);
if (!ra->cfra) {
LOG_D(NR_MAC,
"UE %04x: %d.%d: Setting RA-Msg3 reception for SFN.Slot %d.%d\n",
UE->rnti,
frameP,
slotP,
ra->Msg3_frame,
ra->Msg3_slot);
// Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2)
// 3GPP TS 38.321 Section 5.1.5 Contention Resolution // 3GPP TS 38.321 Section 5.1.5 Contention Resolution
start_ra_contention_resolution_timer( start_ra_contention_resolution_timer(
...@@ -1620,14 +1640,7 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1620,14 +1640,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
*ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), *ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc),
ul_bwp->scs); ul_bwp->scs);
LOG_D(NR_MAC, }
"UE %04x: %d.%d: Setting RA-Msg3 reception (%s) for SFN.Slot %d.%d\n",
UE->rnti,
frameP,
slotP,
ra->cfra ? "CFRA" : "CBRA",
ra->Msg3_frame,
ra->Msg3_slot);
tx_req->PDU_index = pduindex; tx_req->PDU_index = pduindex;
tx_req->num_TLV = 1; tx_req->num_TLV = 1;
...@@ -1652,6 +1665,7 @@ static void nr_generate_Msg2(module_id_t module_idP, ...@@ -1652,6 +1665,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
vrb_map[bwp_info.bwpStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); vrb_map[bwp_info.bwpStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
} }
// In CFRA: in Msg3 handling, will unconditionally mark succeeded
ra->ra_state = nrRA_WAIT_Msg3; ra->ra_state = nrRA_WAIT_Msg3;
} }
...@@ -1673,6 +1687,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, ...@@ -1673,6 +1687,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP,
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_SearchSpace_t *ss = sched_ctrl->search_space; NR_SearchSpace_t *ss = sched_ctrl->search_space;
NR_RA_t *ra = UE->ra; NR_RA_t *ra = UE->ra;
DevAssert(!ra->cfra);
const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4";
NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; NR_ControlResourceSet_t *coreset = sched_ctrl->coreset;
AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str); AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str);
......
...@@ -725,13 +725,6 @@ static void handle_nr_ul_harq(gNB_MAC_INST *nrmac, ...@@ -725,13 +725,6 @@ static void handle_nr_ul_harq(gNB_MAC_INST *nrmac,
static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max) static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max)
{ {
// for CFRA (NSA) do not schedule retransmission of msg3
if (ra->cfra) {
LOG_W(NR_MAC, "UE %04x RA failed at state %s (NSA msg3 reception failed)\n", rnti, nrra_text[ra->ra_state]);
nr_release_ra_UE(mac, rnti);
return;
}
if (ra->msg3_round >= harq_round_max - 1) { if (ra->msg3_round >= harq_round_max - 1) {
LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]); LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]);
nr_release_ra_UE(mac, rnti); nr_release_ra_UE(mac, rnti);
...@@ -756,6 +749,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, ...@@ -756,6 +749,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
const uint16_t rssi) const uint16_t rssi)
{ {
gNB_MAC_INST *mac = RC.nrmac[mod_id]; gNB_MAC_INST *mac = RC.nrmac[mod_id];
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
NR_UE_info_t *UE = find_ra_UE(&mac->UE_info, rnti); NR_UE_info_t *UE = find_ra_UE(&mac->UE_info, rnti);
if (!UE) { if (!UE) {
LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", rnti); LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", rnti);
...@@ -768,6 +762,31 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, ...@@ -768,6 +762,31 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
return; return;
} }
// CFRA: we scheduled Msg3 (which does not exist in CFRA, see also
// nr_generate_Msg2()). We did not mark RA as complete right away, as the
// DLSCH scheduler might schedule in the same slot as Msg2 if RLC has data
// (which can only happen in do-ra), so we mark it as complete now.
if (ra->cfra) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
nr_mac_reset_ul_failure(sched_ctrl);
reset_dl_harq_list(sched_ctrl);
reset_ul_harq_list(sched_ctrl);
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA
// in NSA (or do-ra) there is no reconfiguration in NR
int ss_type = IS_SA_MODE(get_softmodem_params()) ? NR_SearchSpace__searchSpaceType_PR_common
: NR_SearchSpace__searchSpaceType_PR_ue_Specific;
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
// initialize ta_frame in case there is no Msg3 received
UE->UE_sched_ctrl.ta_frame = (frame + 100) % MAX_FRAME_NUMBER;
if (!transition_ra_connected_nr_ue(mac, UE)) {
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator);
} else {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
}
return; // TODO: handle Msg3 in case it has been received?
}
const int target_snrx10 = mac->pusch_target_snrx10; const int target_snrx10 = mac->pusch_target_snrx10;
if (!sdu) { // NACK if (!sdu) { // NACK
if (ra->ra_state != nrRA_WAIT_Msg3) if (ra->ra_state != nrRA_WAIT_Msg3)
...@@ -826,27 +845,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, ...@@ -826,27 +845,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->ta_update = timing_advance;
UE_scheduling_control->raw_rssi = rssi; UE_scheduling_control->raw_rssi = rssi;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList);
int ss_type;
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA
// in NSA (or do-ra) there is no reconfiguration in NR
if (IS_SA_MODE(get_softmodem_params()))
ss_type = NR_SearchSpace__searchSpaceType_PR_common;
else
ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
if (!transition_ra_connected_nr_ue(mac, UE)) {
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator);
return;
}
} else {
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
for (uint32_t k = 0; k < sdu_len; k++) { for (uint32_t k = 0; k < sdu_len; k++) {
LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]); LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]);
...@@ -913,7 +912,6 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, ...@@ -913,7 +912,6 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; 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", UE->rnti, nrra_text[ra->ra_state]); LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]);
return; return;
}
} }
static void _nr_rx_sdu(const module_id_t gnb_mod_idP, static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment