From e4a6d60dc2a4501fdc4b175d4d94690bad948a38 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 2 May 2024 18:47:05 +0200 Subject: [PATCH] implementation of time alignment timer at MAC UE --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 45 +++++++ openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 + openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 3 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 9 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 116 ++++++++++--------- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 27 +++++ 7 files changed, 142 insertions(+), 61 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 4652cb0d18..6f5cdef338 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1545,6 +1545,42 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up } } +static void configure_timeAlignmentTimer(NR_timer_t *time_alignment_timer, NR_TimeAlignmentTimer_t timer_config, int scs) +{ + uint32_t timer_ms = 0; + switch (timer_config) { + case NR_TimeAlignmentTimer_ms500 : + timer_ms = 500; + break; + case NR_TimeAlignmentTimer_ms750 : + timer_ms = 750; + break; + case NR_TimeAlignmentTimer_ms1280 : + timer_ms = 1280; + break; + case NR_TimeAlignmentTimer_ms1920 : + timer_ms = 1920; + break; + case NR_TimeAlignmentTimer_ms2560 : + timer_ms = 2560; + break; + case NR_TimeAlignmentTimer_ms5120 : + timer_ms = 5120; + break; + case NR_TimeAlignmentTimer_ms10240 : + timer_ms = 10240; + break; + case NR_TimeAlignmentTimer_infinity : + timer_ms = UINT_MAX; + break; + default : + AssertFatal(false, "Invalid timeAlignmentTimer\n"); + } + // length of slot is (1/2^scs)ms + uint32_t n_slots = timer_ms != UINT_MAX ? (timer_ms << scs) : UINT_MAX; + nr_timer_setup(time_alignment_timer, n_slots, 1); // 1 slot update rate +} + void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause) { @@ -1577,6 +1613,8 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, nr_ue_mac_default_configs(mac); nr_ue_reset_sync_state(mac); release_mac_configuration(mac, cause); + // apply the timeAlignmentTimerCommon included in SIB1 + configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); // new sync with old cell ID (re-establishment on the same cell) sync_req.target_Nid_cell = mac->physCellId; sync_req.ssb_bw_scan = false; @@ -1636,6 +1674,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, AssertFatal(mac->current_DL_BWP, "Couldn't find DL-BWP0\n"); mac->current_UL_BWP = get_ul_bwp_structure(mac, 0, false); AssertFatal(mac->current_UL_BWP, "Couldn't find DL-BWP0\n"); + configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->timeAlignmentTimerCommon, mac->current_UL_BWP->scs); } // Setup the SSB to Rach Occasions mapping according to the config @@ -2476,6 +2515,12 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, if (cell_group_config->mac_CellGroupConfig) configure_maccellgroup(mac, cell_group_config->mac_CellGroupConfig); + for (int j = 0; j < mac->TAG_list.count; j++) { + // apply the Timing Advance Command for the indicated TAG + if (mac->TAG_list.array[j]->tag_Id == mac->tag_Id) + configure_timeAlignmentTimer(&mac->time_alignment_timer, mac->TAG_list.array[j]->timeAlignmentTimer, mac->current_UL_BWP->scs); + } + configure_logicalChannelBearer(mac, cell_group_config->rlc_BearerToAddModList, cell_group_config->rlc_BearerToReleaseList); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2eb6415980..d9c5fa2345 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -596,6 +596,7 @@ typedef struct NR_UE_MAC_INST_s { NR_TAG_Id_t tag_Id; A_SEQUENCE_OF(NR_TAG_t) TAG_list; NR_TimeAlignmentTimer_t timeAlignmentTimerCommon; + NR_timer_t time_alignment_timer; nr_emulated_l1_t nr_ue_emul_l1; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index bb42701ec3..dcd6a62f5d 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -350,7 +350,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 nr_get_msg3_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, NR_PDSCH_Config_t *pdsch_Config, diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 4de5024b8f..a60d8d2c43 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -202,6 +202,7 @@ 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); @@ -209,7 +210,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) nr_timer_stop(&nr_mac->scheduling_info.sr_info[i].prohibitTimer); // consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2 - // TODO + handle_time_alignment_timer_expired(nr_mac); // set the NDIs for all uplink HARQ processes to the value 0 for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index c52a67c5a2..66fbf20630 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -912,9 +912,14 @@ void nr_ra_failed(NR_UE_MAC_INST_t *mac, uint8_t CC_id, NR_PRACH_RESOURCES_t *pr prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER++; - if (prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER == ra->preambleTransMax + 1){ + // when the Contention Resolution is considered not successful + // stop timeAlignmentTimer + nr_timer_stop(&mac->time_alignment_timer); - LOG_D(MAC, "[UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", + if (prach_resources->RA_PREAMBLE_TRANSMISSION_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, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index d007878203..f9d23177eb 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2953,8 +2953,11 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN); - LOG_D(MAC, "In [%d.%d] Handling DLSCH PDU type %d\n", - dl_info->frame, dl_info->slot, dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type); + LOG_D(NR_MAC, + "In [%d.%d] Handling DLSCH PDU type %d\n", + dl_info->frame, + dl_info->slot, + dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type); // Processing MAC PDU // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs @@ -2969,10 +2972,9 @@ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, in case FAPI_NR_RX_PDU_TYPE_RAR : nr_ue_process_rar(mac, dl_info, pdu_id); break; - default: - AssertFatal(false, "Invalid PDU type\n"); + default : + AssertFatal(false, "Invalid DLSCH PDU type\n"); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); } @@ -3412,6 +3414,21 @@ static nr_dci_format_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac, return format; } +static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, int frame, int slot) +{ + NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; + ul_time_alignment->ta_command = ta; + ul_time_alignment->ta_apply = type; + + const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); + const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs]; + ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; + ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame; + + // start or restart the timeAlignmentTimer associated with the indicated TAG + nr_timer_start(&mac->time_alignment_timer); +} + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3572,20 +3589,7 @@ void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_i break; } - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; - ul_time_alignment->ta_command = ta; - ul_time_alignment->ta_apply = adjustment_ta; - - const int ntn_ue_koffset = get_NTN_UE_Koffset(mac->sc_info.ntn_Config_r17, mac->current_UL_BWP->scs); - const int n_slots_frame = nr_slots_per_frame[mac->current_UL_BWP->scs]; - ul_time_alignment->frame = (frameP + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; - ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame; - - /* - #ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]); - #endif - */ + set_time_alignment(mac, ta, adjustment_ta, frameP, slot); if (ta == 31) LOG_D(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d \n", frameP, slot, ta, tag, CC_id); @@ -3934,13 +3938,15 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d } } - #ifdef DEBUG_RAR - LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", +#ifdef DEBUG_RAR + LOG_D(NR_MAC, + "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs); - LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", + LOG_D(NR_MAC, + "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], @@ -3950,30 +3956,18 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d rar[5], rarh->RAPID, preamble_index); - #endif +#endif if (ra->RA_RAPID_found) { RAR_grant_t rar_grant; - unsigned char tpc_command; -#ifdef DEBUG_RAR - unsigned char csi_req; -#endif - - // TA command - NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment; - const int ta = rar->TA2 + (rar->TA1 << 5); - ul_time_alignment->ta_command = ta; - ul_time_alignment->ta_apply = rar_ta; - - LOG_W(MAC, "received TA command %d\n", 31 + ta); #ifdef DEBUG_RAR // CSI - csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); + unsigned char csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01); #endif // TPC - tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); + unsigned char tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07); switch (tpc_command){ case 0: ra->Msg3_TPC = -6; @@ -4011,6 +4005,31 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d // 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_Koffset(mac->sc_info.ntn_Config_r17, 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); @@ -4041,26 +4060,6 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d tpc_command); #endif - // 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_Koffset(mac->sc_info.ntn_Config_r17, 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); - - const int n_slots_frame = nr_slots_per_frame[current_UL_BWP->scs]; - ul_time_alignment->frame = (frame_tx + (slot_tx + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER; - ul_time_alignment->slot = (slot_tx + ntn_ue_koffset) % n_slots_frame; - 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 @@ -4090,6 +4089,9 @@ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *d } 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 baf728e192..d742f7cc9a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -152,6 +152,30 @@ static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity nr_timer_stop(&mac->scheduling_info.sr_DelayTimer); } +void handle_time_alignment_timer_expired(NR_UE_MAC_INST_t *mac) +{ + // flush all HARQ buffers for all Serving Cells + for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) { + memset(&mac->dl_harq_info[k], 0, sizeof(NR_UE_HARQ_STATUS_t)); + memset(&mac->ul_harq_info[k], 0, sizeof(NR_UL_HARQ_INFO_t)); + mac->dl_harq_info[k].last_ndi = -1; // initialize to invalid value + mac->ul_harq_info[k].last_ndi = -1; // initialize to invalid value + } + // release PUCCH for all Serving Cells; + // release SRS for all Serving Cells; + release_PUCCH_SRS(mac); + // clear any configured downlink assignments and uplink grants; + int scs = mac->current_UL_BWP ? mac->current_UL_BWP->scs : get_softmodem_params()->numerology; + if (mac->dl_config_request) + memset(mac->dl_config_request, 0, sizeof(*mac->dl_config_request)); + if (mac->ul_config_request) + clear_ul_config_request(mac, scs); + // clear any PUSCH resources for semi-persistent CSI reporting + // TODO we don't have semi-persistent CSI reporting + // maintain N_TA + // TODO not sure what to do here +} + void update_mac_timers(NR_UE_MAC_INST_t *mac) { if (mac->data_inactivity_timer) { @@ -159,6 +183,9 @@ void update_mac_timers(NR_UE_MAC_INST_t *mac) 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); nr_timer_tick(&mac->ra.contention_resolution_timer); for (int j = 0; j < NR_MAX_SR_ID; j++) nr_timer_tick(&mac->scheduling_info.sr_info[j].prohibitTimer);