diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index f7ea7304e43d90913e99bf206bedfee563b94503..fbff9bf94be1ac58b8e9c616c4792d27eb523f21 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1011,6 +1011,8 @@ bool nr_timer_tick(NR_timer_t *timer) bool expired = false; if (timer->active) { timer->counter += timer->step; + if (timer->target == UINT_MAX) // infinite target, never expires + return false; expired = nr_timer_expired(*timer); if (expired) timer->active = false; @@ -1020,9 +1022,16 @@ bool nr_timer_tick(NR_timer_t *timer) bool nr_timer_expired(NR_timer_t timer) { + if (timer.target == UINT_MAX) // infinite target, never expires + return false; return (timer.counter >= timer.target); } +uint32_t nr_timer_elapsed_time(NR_timer_t timer) +{ + return 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 c76969a8e89e83904b027fe20dbfc0e582bf9a35..4a90d79578d4944cd6bbbed0b80d3374853b7c2e 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -158,6 +158,13 @@ bool nr_timer_expired(NR_timer_t timer); * @return Indication if the timer is active or not */ bool is_nr_timer_active(NR_timer_t timer); +/** + * @brief To return how much time has passed since start of timer + * @param timer Timer to be checked + * @return Time passed since start of timer + */ +uint32_t nr_timer_elapsed_time(NR_timer_t timer); + extern const nr_bandentry_t nr_bandtable[]; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index ef5df5beb9ef690286dbc517b0e23c681eff405d..c86aad9ab26898342e4df321cb3e87f810ee105c 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -657,10 +657,70 @@ static int nr_get_ms_bucketsizeduration(long bucketsizeduration) } } +static uint32_t nr_get_pbr(long prioritizedbitrate) // returns Bps +{ + uint32_t pbr = 0; + switch (prioritizedbitrate) { + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps0: + pbr = 0; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8: + pbr = 8; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16: + pbr = 16; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32: + pbr = 32; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps64: + pbr = 64; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps128: + pbr = 128; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps256: + pbr = 256; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps512: + pbr = 512; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps1024: + pbr = 1024; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps2048: + pbr = 2048; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps4096: + pbr = 4096; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8192: + pbr = 8192; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16384: + pbr = 16384; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32768: + pbr = 32768; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps65536: + pbr = 65536; + break; + case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity: + pbr = UINT_MAX; + break; + default: + AssertFatal(false, "The proritized bit rate value is not one of the enum values\n"); + } + uint32_t pbr_bytes = + (prioritizedbitrate < NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) ? pbr * 1000 : pbr; + return pbr_bytes; +} + static uint32_t get_lc_bucket_size(long prioritisedBitRate, long bucketSizeDuration) { - int pbr = nr_get_pbr(prioritisedBitRate); - // in infinite pbr, the bucket is saturated by pbr + uint32_t pbr = nr_get_pbr(prioritisedBitRate); + // if infinite pbr, the bucket is saturated by pbr int bsd = 0; if (prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) bsd = 1; @@ -675,8 +735,8 @@ static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SR { lc_info->lcid = srb_id; lc_info->priority = srb_id == 2 ? 3 : 1; - lc_info->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; - lc_info->bucket_size = get_lc_bucket_size(lc_info->prioritisedBitRate, 0); + lc_info->pbr = UINT_MAX; + lc_info->bucket_size = UINT_MAX; } static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, @@ -693,10 +753,14 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, AssertFatal(mac_lc_config->ul_SpecificParameters, "UL parameters shouldn't be NULL for DRBs\n"); struct NR_LogicalChannelConfig__ul_SpecificParameters *ul_parm = mac_lc_config->ul_SpecificParameters; lc_info->priority = ul_parm->priority; - lc_info->prioritisedBitRate = ul_parm->prioritisedBitRate; + lc_info->pbr = nr_get_pbr(ul_parm->prioritisedBitRate); // TODO Verify setting to 0 is ok, 331 just says need R (release if NULL) mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].LCGID = ul_parm->logicalChannelGroup ? *ul_parm->logicalChannelGroup : 0; lc_info->bucket_size = get_lc_bucket_size(ul_parm->prioritisedBitRate, ul_parm->bucketSizeDuration); + // setup and start Bj timer for this LC + NR_timer_t *bjt = &mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].Bj_timer; + nr_timer_setup(bjt, UINT_MAX, 1); // this timer never expires in principle, counter incremented by number of slots + nr_timer_start(bjt); } static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 0c112ac66d34551baf8205efea0f7b8775a30c63..97c1860d1b2fefef632a9bb46f2dc4ecfe157689 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -185,6 +185,7 @@ typedef struct { long LCGID; // Bj bucket usage per lcid int32_t Bj; + NR_timer_t Bj_timer; } NR_LC_SCHEDULING_INFO; typedef struct { @@ -441,7 +442,7 @@ typedef struct nr_lcordered_info_s { // logical channels ids ordered as per priority NR_LogicalChannelIdentity_t lcid; long priority; - long prioritisedBitRate; + uint32_t pbr; // in B/s (UINT_MAX = infinite) // Bucket size per lcid uint32_t bucket_size; } nr_lcordered_info_t; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 7322024e7b5fc378d9f2263f8d7973f76c62a512..e3d887f2a35ef51c324998c915ec99134edb3872 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -138,13 +138,6 @@ bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value); -/*! \fn int nr_get_pbr(long prioritizedbitrate) - \brief get the rate in kbps from the rate configured by the higher layer -\param[in] prioritizedbitrate -\return the rate in kbps -*/ -uint32_t nr_get_pbr(long prioritizedbitrate); - /*! \fn int nr_get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer) \brief get the number of subframe from the periodic BSR timer configured by the higher layers \param[in] periodicBSR_Timer timer for periodic BSR diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 4bd1e29ca9da9af7d4056a2b88c825a9a7808d30..bfded89c1565a7989721bd2631cabf0f3728b69c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -118,6 +118,10 @@ static NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *ma void update_mac_timers(NR_UE_MAC_INST_t *mac) { nr_timer_tick(&mac->ra.contention_resolution_timer); + for (int i = 0; i < NR_MAX_NUM_LCID; i++) + AssertFatal(!nr_timer_tick(&mac->scheduling_info.lc_sched_info[i].Bj_timer), + "Bj timer for LCID %d expired! That should never happen\n", + i); } void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu) @@ -1150,22 +1154,27 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; int lcid = lc_info->lcid; // max amount of data that can be buffered/accumulated in a logical channel buffer - int32_t bucketSize_max = lc_info->bucket_size; - AssertFatal(bucketSize_max >= 0, "negative bucketSize_max %d, will never schedule UE: lcid %d\n",bucketSize_max, lcid); + uint32_t bucketSize_max = lc_info->bucket_size; /* measure Bj increment the value of Bj by product PBR * T */ NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid); - int T = 1; // time elapsed since Bj was last incremented int32_t bj = sched_info->Bj; - bj += nr_get_pbr(lc_info->prioritisedBitRate) * T; - if (lc_info->prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) - bj = nr_get_pbr(lc_info->prioritisedBitRate); + if (lc_info->pbr < UINT_MAX) { + uint32_t slots_elapsed = nr_timer_elapsed_time(sched_info->Bj_timer); // slots elapsed since Bj was last incremented + // it is safe to divide by 1k since pbr in lc_info is computed multiplying by 1000 the RRC value to convert kB/s to B/s + uint32_t pbr_ms = lc_info->pbr / 1000; + bj += ((pbr_ms * slots_elapsed) >> mac->current_UL_BWP->scs); // each slot length is 1/scs ms + } + else + bj = INT_MAX; // bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization sched_info->Bj = min(bj, bucketSize_max); + // reset bj timer + nr_timer_start(&sched_info->Bj_timer); } // Call BSR procedure as described in Section 5.4.5 in 38.321 @@ -2883,7 +2892,7 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, /* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/ nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, lc_num); AssertFatal(lc_info, "Couldn't find logical channel with LCID %d\n", lc_num); - uint32_t pbr = nr_get_pbr(lc_info->prioritisedBitRate); + uint32_t pbr = lc_info->pbr; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lc_num); int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain; *target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr; @@ -3132,8 +3141,8 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, bool lcids_data_status[NR_MAX_NUM_LCID] = {0}; memset(lcids_data_status, 1, NR_MAX_NUM_LCID); - uint32_t lcp_allocation_counter = - 0; // in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider + // in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider + uint32_t lcp_allocation_counter = 0; // bj and prioritized bit rate but just consider priority uint16_t buflen_ep = 0; // this variable holds the length in bytes in mac pdu when multiple equal priority channels are present // because as per standard(TS38.321), all equal priority channels should be served equally @@ -3300,80 +3309,3 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TI dl_config->number_pdus += 1; ul_time_alignment->ta_apply = no_ta; } - -uint32_t nr_get_pbr(long prioritizedbitrate) -{ - int32_t pbr = -1; - switch (prioritizedbitrate) { - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps0: - pbr = 0; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8: - pbr = 8; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16: - pbr = 16; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32: - pbr = 32; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps64: - pbr = 64; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps128: - pbr = 128; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps256: - pbr = 256; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps512: - pbr = 512; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps1024: - pbr = 1024; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps2048: - pbr = 2048; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps4096: - pbr = 4096; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8192: - pbr = 8192; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps16384: - pbr = 16384; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps32768: - pbr = 32768; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps65536: - pbr = 65536; - break; - - case NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity: - pbr = INT32_MAX; - break; - - default: - pbr = -1; - } - AssertFatal(pbr >= 0, "The proritized bit rate value is not one of the enum values\n"); - uint32_t pbr_bytes = - (prioritizedbitrate < NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) ? pbr * 1000 : pbr; - return pbr_bytes; -}