From 932b17766782c6f9bf7820a5986fb16e15f45be4 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Thu, 10 Jul 2025 08:38:52 +0200 Subject: [PATCH] Add logic for measgap scheduling --- common/utils/nr/nr_common.c | 5 +++ common/utils/nr/nr_common.h | 6 +++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 1 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 38 ++++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 + 6 files changed, 51 insertions(+), 2 deletions(-) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 5d98a99bb4..7875fe546a 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1415,6 +1415,11 @@ uint32_t nr_timer_elapsed_time(const NR_timer_t *timer) return timer->counter; } +uint32_t nr_timer_remaining_time(const NR_timer_t *timer) +{ + return timer->target - timer->counter; +} + void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step) { timer->target = target; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index f98ce510a2..05ee80c18a 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -222,6 +222,12 @@ bool nr_timer_is_active(const NR_timer_t *timer); * @return Time passed since start of timer */ uint32_t nr_timer_elapsed_time(const NR_timer_t *timer); +/** + * @brief To return how much time is left until the timer expires + * @param timer Timer to be checked + * @return Time left until the timer expires + */ +uint32_t nr_timer_remaining_time(const NR_timer_t *timer); int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_subframe); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 39d75907be..faaa00ea3f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -201,6 +201,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo LOG_I(NR_MAC, "Frame.Slot %d.%d\n%s\n", frame, slot, stats_output); } + nr_measgap_scheduling(gNB, frame, slot); nr_mac_update_timers(module_idP, frame, slot); if (wait_prach_completed || get_softmodem_params()->phy_test) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 9c5a00e12c..dad58f52f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -628,6 +628,7 @@ static void pf_dl(module_id_t module_id, NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head; + /* Calculate Throughput */ const float a = 0.01f; const uint32_t b = UE->mac_stats.dl.current_bytes; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 13dc711b77..b40329cd69 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3158,6 +3158,37 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt } } +void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot) +{ + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + + NR_UEs_t *UE_info = &nr_mac->UE_info; + UE_iterator(UE_info->connected_ue_list, UE) { + measgap_config_t *mgc = &UE->measgap_config; + if (!mgc->enable) + continue; + + const int slots_frame = nr_mac->frame_structure.numb_slots_frame; + const frame_t f = (frame + (slot + mgc->n_slots_advance) / slots_frame) % 1024; + const slot_t s = (slot + mgc->n_slots_advance) % slots_frame; + + // TS 38 331 - Section 5.5.2.9 Measurement gap configuration + if (!(((f % (mgc->mgrp_ms / 10)) == (mgc->gapOffset / 10)) && (s == mgc->gapOffset % 10))) + continue; + + NR_timer_t *t = &UE->UE_sched_ctrl.transm_interrupt; + interrupt_followup_action_t a = nr_timer_is_active(t) ? UE->interrupt_action : FOLLOW_INSYNC; + // start a timer to stop scheduling UE during MeasGap, or extend timer for + // duration of measGap with existing follow-up action + // TODO: if the timer is running, it might be to stop scheduling of the UE afterwards, but then it does not make sense to stop + // scheduling the UE now, we should maybe just skip it? + if (!nr_timer_is_active(t) || nr_timer_remaining_time(t) < mgc->mgl_slots) { + nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_DL_BWP.scs); /* set the UE to "not active" */ + nr_mac_interrupt_ue_transmission(nr_mac, UE, a, mgc->mgl_slots); + } + } +} + void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) { DevAssert(cell_group != NULL); @@ -3281,9 +3312,12 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) if (nr_timer_tick(&sched_ctrl->transm_interrupt)) { /* expired */ nr_timer_stop(&sched_ctrl->transm_interrupt); - if (UE->interrupt_action == FOLLOW_OUTOFSYNC) + if (UE->interrupt_action == FOLLOW_OUTOFSYNC) { nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - /* else: default FOLLOW_INSYNC: nothing to do (UE is now active again) */ + } else { + DevAssert(UE->interrupt_action == FOLLOW_INSYNC); + nr_mac_reset_ul_failure(sched_ctrl); + } } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c6f9a2f6f9..ea07fbeea4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -203,6 +203,8 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt void nr_csi_meas_reporting(int Mod_idP, frame_t frameP, slot_t slotP); +void nr_measgap_scheduling(gNB_MAC_INST *nr_mac, frame_t frame, sub_frame_t slot); + int nr_acknack_scheduling(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frameP,