Commit eaff52f8 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/NR_UE_MAC_UL_improvements' into integration_2024_w12

parents 3042c70d c090b1f7
...@@ -1011,6 +1011,8 @@ bool nr_timer_tick(NR_timer_t *timer) ...@@ -1011,6 +1011,8 @@ bool nr_timer_tick(NR_timer_t *timer)
bool expired = false; bool expired = false;
if (timer->active) { if (timer->active) {
timer->counter += timer->step; timer->counter += timer->step;
if (timer->target == UINT_MAX) // infinite target, never expires
return false;
expired = nr_timer_expired(*timer); expired = nr_timer_expired(*timer);
if (expired) if (expired)
timer->active = false; timer->active = false;
...@@ -1020,9 +1022,16 @@ bool nr_timer_tick(NR_timer_t *timer) ...@@ -1020,9 +1022,16 @@ bool nr_timer_tick(NR_timer_t *timer)
bool nr_timer_expired(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); 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) void nr_timer_setup(NR_timer_t *timer, const uint32_t target, const uint32_t step)
{ {
timer->target = target; timer->target = target;
......
...@@ -158,6 +158,13 @@ bool nr_timer_expired(NR_timer_t timer); ...@@ -158,6 +158,13 @@ bool nr_timer_expired(NR_timer_t timer);
* @return Indication if the timer is active or not * @return Indication if the timer is active or not
*/ */
bool is_nr_timer_active(NR_timer_t timer); 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[]; extern const nr_bandentry_t nr_bandtable[];
......
...@@ -63,11 +63,6 @@ ...@@ -63,11 +63,6 @@
#define RAR_PAYLOAD_SIZE_MAX 128 #define RAR_PAYLOAD_SIZE_MAX 128
#define MAX_CSI_REPORTCONFIG 48 #define MAX_CSI_REPORTCONFIG 48
#define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */
#define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
// For both DL/UL-SCH // For both DL/UL-SCH
// Except: // Except:
// - UL/DL-SCH: fixed-size MAC CE(known by LCID) // - UL/DL-SCH: fixed-size MAC CE(known by LCID)
......
...@@ -657,10 +657,70 @@ static int nr_get_ms_bucketsizeduration(long bucketsizeduration) ...@@ -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) static uint32_t get_lc_bucket_size(long prioritisedBitRate, long bucketSizeDuration)
{ {
int pbr = nr_get_pbr(prioritisedBitRate); uint32_t pbr = nr_get_pbr(prioritisedBitRate);
// in infinite pbr, the bucket is saturated by pbr // if infinite pbr, the bucket is saturated by pbr
int bsd = 0; int bsd = 0;
if (prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) if (prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity)
bsd = 1; bsd = 1;
...@@ -675,8 +735,8 @@ static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SR ...@@ -675,8 +735,8 @@ static void set_default_logicalchannelconfig(nr_lcordered_info_t *lc_info, NR_SR
{ {
lc_info->lcid = srb_id; lc_info->lcid = srb_id;
lc_info->priority = srb_id == 2 ? 3 : 1; lc_info->priority = srb_id == 2 ? 3 : 1;
lc_info->prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity; lc_info->pbr = UINT_MAX;
lc_info->bucket_size = get_lc_bucket_size(lc_info->prioritisedBitRate, 0); lc_info->bucket_size = UINT_MAX;
} }
static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac,
...@@ -684,19 +744,27 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, ...@@ -684,19 +744,27 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac,
NR_LogicalChannelConfig_t *mac_lc_config, NR_LogicalChannelConfig_t *mac_lc_config,
NR_SRB_Identity_t srb_id) NR_SRB_Identity_t srb_id)
{ {
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info->lcid);
if (srb_id > 0 && !mac_lc_config->ul_SpecificParameters) { if (srb_id > 0 && !mac_lc_config->ul_SpecificParameters) {
// release configuration and reset to default // release configuration and reset to default
set_default_logicalchannelconfig(lc_info, srb_id); set_default_logicalchannelconfig(lc_info, srb_id);
mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].LCGID = 0; // invalid LCGID to signal it is absent in the configuration
lc_sched_info->LCGID = NR_INVALID_LCGID;
return; return;
} }
AssertFatal(mac_lc_config->ul_SpecificParameters, "UL parameters shouldn't be NULL for DRBs\n"); 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; struct NR_LogicalChannelConfig__ul_SpecificParameters *ul_parm = mac_lc_config->ul_SpecificParameters;
lc_info->priority = ul_parm->priority; lc_info->priority = ul_parm->priority;
lc_info->prioritisedBitRate = ul_parm->prioritisedBitRate; lc_info->sr_DelayTimerApplied = ul_parm->logicalChannelSR_DelayTimerApplied;
// TODO Verify setting to 0 is ok, 331 just says need R (release if NULL) lc_info->lc_SRMask = ul_parm->logicalChannelSR_Mask;
mac->scheduling_info.lc_sched_info[lc_info->lcid - 1].LCGID = ul_parm->logicalChannelGroup ? *ul_parm->logicalChannelGroup : 0; lc_info->pbr = nr_get_pbr(ul_parm->prioritisedBitRate);
// if logicalChannelGroup we release LCGID and set it to invalid
lc_sched_info->LCGID = ul_parm->logicalChannelGroup ? *ul_parm->logicalChannelGroup : NR_INVALID_LCGID;
lc_info->bucket_size = get_lc_bucket_size(ul_parm->prioritisedBitRate, ul_parm->bucketSizeDuration); 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 = &lc_sched_info->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, static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac,
...@@ -1492,6 +1560,137 @@ static void configure_physicalcellgroup(NR_UE_MAC_INST_t *mac, ...@@ -1492,6 +1560,137 @@ static void configure_physicalcellgroup(NR_UE_MAC_INST_t *mac,
*p_UE_FR1 : *p_NR_FR1); *p_UE_FR1 : *p_NR_FR1);
} }
static uint32_t get_sr_DelayTimer(long logicalChannelSR_DelayTimer)
{
uint32_t timer = 0;
switch (logicalChannelSR_DelayTimer) {
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf20 :
timer = 20;
break;
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf40 :
timer = 40;
break;
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf64 :
timer = 64;
break;
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf128 :
timer = 128;
break;
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf512 :
timer = 512;
break;
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf1024 :
timer = 1024;
break;
case NR_BSR_Config__logicalChannelSR_DelayTimer_sf2560 :
timer = 2560;
break;
default :
AssertFatal(false, "Invalid SR_DelayTimer %ld\n", logicalChannelSR_DelayTimer);
}
return timer;
}
static uint32_t nr_get_sf_retxBSRTimer(long retxBSR_Timer)
{
uint32_t timer = 0;
switch (retxBSR_Timer) {
case NR_BSR_Config__retxBSR_Timer_sf10:
timer = 10;
break;
case NR_BSR_Config__retxBSR_Timer_sf20:
timer = 20;
break;
case NR_BSR_Config__retxBSR_Timer_sf40:
timer = 40;
break;
case NR_BSR_Config__retxBSR_Timer_sf80:
timer = 80;
break;
case NR_BSR_Config__retxBSR_Timer_sf160:
timer = 160;
break;
case NR_BSR_Config__retxBSR_Timer_sf320:
timer = 320;
break;
case NR_BSR_Config__retxBSR_Timer_sf640:
timer = 640;
break;
case NR_BSR_Config__retxBSR_Timer_sf1280:
timer = 1280;
break;
case NR_BSR_Config__retxBSR_Timer_sf2560:
timer = 2560;
break;
case NR_BSR_Config__retxBSR_Timer_sf5120:
timer = 5120;
break;
case NR_BSR_Config__retxBSR_Timer_sf10240:
timer = 10240;
break;
default:
AssertFatal(false, "Invalid retxBSR_Timer %ld\n", retxBSR_Timer);
}
return timer;
}
static uint32_t nr_get_sf_periodicBSRTimer(long periodicBSR)
{
uint32_t timer = 0;
switch (periodicBSR) {
case NR_BSR_Config__periodicBSR_Timer_sf1:
timer = 1;
break;
case NR_BSR_Config__periodicBSR_Timer_sf5:
timer = 5;
break;
case NR_BSR_Config__periodicBSR_Timer_sf10:
timer = 10;
break;
case NR_BSR_Config__periodicBSR_Timer_sf16:
timer = 16;
break;
case NR_BSR_Config__periodicBSR_Timer_sf20:
timer = 20;
break;
case NR_BSR_Config__periodicBSR_Timer_sf32:
timer = 32;
break;
case NR_BSR_Config__periodicBSR_Timer_sf40:
timer = 40;
break;
case NR_BSR_Config__periodicBSR_Timer_sf64:
timer = 64;
break;
case NR_BSR_Config__periodicBSR_Timer_sf80:
timer = 80;
break;
case NR_BSR_Config__periodicBSR_Timer_sf128:
timer = 128;
break;
case NR_BSR_Config__periodicBSR_Timer_sf160:
timer = 160;
break;
case NR_BSR_Config__periodicBSR_Timer_sf320:
timer = 320;
break;
case NR_BSR_Config__periodicBSR_Timer_sf640:
timer = 640;
break;
case NR_BSR_Config__periodicBSR_Timer_sf1280:
timer = 1280;
break;
case NR_BSR_Config__periodicBSR_Timer_sf2560:
timer = 2560;
break;
case NR_BSR_Config__periodicBSR_Timer_infinity:
timer = UINT_MAX;
default:
AssertFatal(false, "Invalid periodicBSR_Timer %ld\n", periodicBSR);
}
return timer;
}
static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroupConfig_t *mcg) static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroupConfig_t *mcg)
{ {
NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info; NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info;
...@@ -1525,10 +1724,17 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup ...@@ -1525,10 +1724,17 @@ static void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroup
} }
} }
if (mcg->bsr_Config) { if (mcg->bsr_Config) {
si->periodicBSR_Timer = mcg->bsr_Config->periodicBSR_Timer; int subframes_per_slot = nr_slots_per_frame[mac->current_UL_BWP->scs] / 10;
si->retxBSR_Timer = mcg->bsr_Config->retxBSR_Timer; uint32_t periodic_sf = nr_get_sf_periodicBSRTimer(mcg->bsr_Config->periodicBSR_Timer);
if (mcg->bsr_Config->logicalChannelSR_DelayTimer) uint32_t target = periodic_sf < UINT_MAX ? periodic_sf * subframes_per_slot : periodic_sf;
LOG_E(NR_MAC, "Handling of logicalChannelSR_DelayTimer not implemented\n"); nr_timer_setup(&si->periodicBSR_Timer, target, 1); // 1 slot update rate
nr_timer_start(&si->periodicBSR_Timer);
uint32_t retx_sf = nr_get_sf_retxBSRTimer(mcg->bsr_Config->retxBSR_Timer);
nr_timer_setup(&si->retxBSR_Timer, retx_sf * subframes_per_slot, 1); // 1 slot update rate
if (mcg->bsr_Config->logicalChannelSR_DelayTimer) {
uint32_t dt_sf = get_sr_DelayTimer(*mcg->bsr_Config->logicalChannelSR_DelayTimer);
nr_timer_setup(&si->sr_DelayTimer, dt_sf * subframes_per_slot, 1); // 1 slot update rate
}
} }
if (mcg->tag_Config) { if (mcg->tag_Config) {
// TODO TAG not handled // TODO TAG not handled
...@@ -1988,9 +2194,6 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, ...@@ -1988,9 +2194,6 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
AssertFatal(cell_group_config, "CellGroupConfig should not be NULL\n"); AssertFatal(cell_group_config, "CellGroupConfig should not be NULL\n");
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
if (cell_group_config->mac_CellGroupConfig)
configure_maccellgroup(mac, cell_group_config->mac_CellGroupConfig);
if (cell_group_config->physicalCellGroupConfig) if (cell_group_config->physicalCellGroupConfig)
configure_physicalcellgroup(mac, cell_group_config->physicalCellGroupConfig); configure_physicalcellgroup(mac, cell_group_config->physicalCellGroupConfig);
...@@ -2008,6 +2211,9 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, ...@@ -2008,6 +2211,9 @@ 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);
configure_logicalChannelBearer(mac, configure_logicalChannelBearer(mac,
cell_group_config->rlc_BearerToAddModList, cell_group_config->rlc_BearerToAddModList,
cell_group_config->rlc_BearerToReleaseList); cell_group_config->rlc_BearerToReleaseList);
......
...@@ -68,6 +68,13 @@ ...@@ -68,6 +68,13 @@
// NR UE defs // NR UE defs
// ========== // ==========
#define NR_BSR_TRIGGER_NONE (0) /* No BSR Trigger */
#define NR_BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */
#define NR_BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */
#define NR_BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */
#define NR_INVALID_LCGID (NR_MAX_NUM_LCGID)
#define MAX_NUM_BWP_UE 5 #define MAX_NUM_BWP_UE 5
#define NUM_SLOT_FRAME 10 #define NUM_SLOT_FRAME 10
...@@ -185,6 +192,7 @@ typedef struct { ...@@ -185,6 +192,7 @@ typedef struct {
long LCGID; long LCGID;
// Bj bucket usage per lcid // Bj bucket usage per lcid
int32_t Bj; int32_t Bj;
NR_timer_t Bj_timer;
} NR_LC_SCHEDULING_INFO; } NR_LC_SCHEDULING_INFO;
typedef struct { typedef struct {
...@@ -200,18 +208,20 @@ typedef struct { ...@@ -200,18 +208,20 @@ typedef struct {
NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID]; NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID];
// lcg scheduling info // lcg scheduling info
NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID]; NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID];
/// BSR report flag management
uint8_t BSR_reporting_active;
// LCID triggering BSR
NR_LogicalChannelIdentity_t regularBSR_trigger_lcid;
/// SR pending as defined in 38.321 /// SR pending as defined in 38.321
uint8_t SR_pending; uint8_t SR_pending;
/// SR_COUNTER as defined in 38.321 /// SR_COUNTER as defined in 38.321
uint16_t SR_COUNTER; uint16_t SR_COUNTER;
/// retxBSR-Timer, default value is sf2560 // logicalChannelSR-DelayTimer
uint16_t retxBSR_Timer; NR_timer_t sr_DelayTimer;
/// retxBSR_SF, number of subframe before triggering a regular BSR /// retxBSR-Timer
uint16_t retxBSR_SF; NR_timer_t retxBSR_Timer;
/// periodicBSR-Timer, default to infinity /// periodicBSR-Timer
uint16_t periodicBSR_Timer; NR_timer_t periodicBSR_Timer;
/// periodicBSR_SF, number of subframe before triggering a periodic BSR
uint16_t periodicBSR_SF;
/// default value is 0: not configured /// default value is 0: not configured
uint16_t sr_ProhibitTimer; uint16_t sr_ProhibitTimer;
/// sr ProhibitTime running /// sr ProhibitTime running
...@@ -231,10 +241,6 @@ typedef struct { ...@@ -231,10 +241,6 @@ typedef struct {
int16_t prohibitPHR_SF; int16_t prohibitPHR_SF;
///DL Pathloss Change in db ///DL Pathloss Change in db
uint16_t PathlossChange_db; uint16_t PathlossChange_db;
/// default value is false
uint16_t extendedBSR_Sizes_r10;
/// default value is false
uint16_t extendedPHR_r10;
} NR_UE_SCHEDULING_INFO; } NR_UE_SCHEDULING_INFO;
typedef enum { typedef enum {
...@@ -441,9 +447,11 @@ typedef struct nr_lcordered_info_s { ...@@ -441,9 +447,11 @@ typedef struct nr_lcordered_info_s {
// logical channels ids ordered as per priority // logical channels ids ordered as per priority
NR_LogicalChannelIdentity_t lcid; NR_LogicalChannelIdentity_t lcid;
long priority; long priority;
long prioritisedBitRate; uint32_t pbr; // in B/s (UINT_MAX = infinite)
// Bucket size per lcid // Bucket size per lcid
uint32_t bucket_size; uint32_t bucket_size;
bool sr_DelayTimerApplied;
bool lc_SRMask;
} nr_lcordered_info_t; } nr_lcordered_info_t;
...@@ -521,9 +529,6 @@ typedef struct NR_UE_MAC_INST_s { ...@@ -521,9 +529,6 @@ typedef struct NR_UE_MAC_INST_s {
nr_phy_config_t phy_config; nr_phy_config_t phy_config;
nr_synch_request_t synch_request; nr_synch_request_t synch_request;
/// BSR report flag management
uint8_t BSR_reporting_active;
// order lc info // order lc info
A_SEQUENCE_OF(nr_lcordered_info_t) lc_ordered_list; A_SEQUENCE_OF(nr_lcordered_info_t) lc_ordered_list;
......
...@@ -47,6 +47,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac); ...@@ -47,6 +47,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac);
void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data); void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data);
void update_mac_timers(NR_UE_MAC_INST_t *mac); void update_mac_timers(NR_UE_MAC_INST_t *mac);
NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid);
/**\brief apply default configuration values in nr_mac instance /**\brief apply default configuration values in nr_mac instance
\param mac mac instance */ \param mac mac instance */
...@@ -119,46 +120,6 @@ subframe number \param[in] slotP slot number ...@@ -119,46 +120,6 @@ subframe number \param[in] slotP slot number
*/ */
int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP); int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
/*! \fn nr_update_bsr
\brief get the rlc stats and update the bsr level for each lcid
\param[in] mac pointer to UE MAC instance
\param[in] frameP Frame index
\param[in] slotP number
\param[in] gNB_index
*/
bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index);
/*! \fn nr_locate_BsrIndexByBufferSize (int *table, int size, int value)
\brief locate the BSR level in the table as defined in 38.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table.
\param[in] *table Pointer to BSR table
\param[in] size Size of the table
\param[in] value Value of the buffer
\return the index in the BSR_LEVEL table
*/
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
\return the number of subframe
*/
int nr_get_sf_periodicBSRTimer(uint8_t bucketSize);
/*! \fn int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer)
\brief get the number of subframe form the bucket size duration configured by the higher layer
\param[in] retxBSR_Timer timer for regular BSR
\return the time in sf
*/
int nr_get_sf_retxBSRTimer(uint8_t retxBSR_Timer);
int8_t nr_ue_process_dci(NR_UE_MAC_INST_t *mac, int8_t nr_ue_process_dci(NR_UE_MAC_INST_t *mac,
int cc_id, int cc_id,
frame_t frame, frame_t frame,
......
...@@ -72,6 +72,9 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) ...@@ -72,6 +72,9 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->p_Max_alt = INT_MIN; mac->p_Max_alt = INT_MIN;
reset_mac_inst(mac); reset_mac_inst(mac);
// need to inizialize because might not been setup (optional timer)
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements)); memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment)); memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
memset(mac->ssb_list, 0, sizeof(mac->ssb_list)); memset(mac->ssb_list, 0, sizeof(mac->ssb_list));
...@@ -81,8 +84,13 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) ...@@ -81,8 +84,13 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
{ {
// default values as defined in 38.331 sec 9.2.2 // default values as defined in 38.331 sec 9.2.2
mac->scheduling_info.retxBSR_Timer = NR_BSR_Config__retxBSR_Timer_sf80;
mac->scheduling_info.periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10; // sf80 default for retxBSR_Timer sf10 for periodicBSR_Timer
int mu = mac->current_UL_BWP ? mac->current_UL_BWP->scs : get_softmodem_params()->numerology;
int subframes_per_slot = nr_slots_per_frame[mu] / 10;
nr_timer_setup(&mac->scheduling_info.retxBSR_Timer, 80 * subframes_per_slot, 1); // 1 slot update rate
nr_timer_setup(&mac->scheduling_info.periodicBSR_Timer, 10 * subframes_per_slot, 1); // 1 slot update rate
mac->scheduling_info.periodicPHR_Timer = NR_PHR_Config__phr_PeriodicTimer_sf10; mac->scheduling_info.periodicPHR_Timer = NR_PHR_Config__phr_PeriodicTimer_sf10;
mac->scheduling_info.prohibitPHR_Timer = NR_PHR_Config__phr_ProhibitTimer_sf10; mac->scheduling_info.prohibitPHR_Timer = NR_PHR_Config__phr_ProhibitTimer_sf10;
} }
...@@ -144,13 +152,20 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) ...@@ -144,13 +152,20 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
// initialize Bj for each logical channel to zero // initialize Bj for each logical channel to zero
// TODO reset also other status variables of LC, is this ok? // TODO reset also other status variables of LC, is this ok?
for (int i = 0; i < NR_MAX_NUM_LCID; i++) { for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
LOG_D(NR_MAC, "Applying default logical channel config for LCID %d\n", i);
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0; nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false; nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_with_data = false;
nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0; nr_mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
} }
// TODO stop all running timers // TODO stop all running timers
for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
nr_mac->scheduling_info.lc_sched_info[i].Bj = 0;
nr_timer_stop(&nr_mac->scheduling_info.lc_sched_info[i].Bj_timer);
}
nr_timer_stop(&nr_mac->ra.contention_resolution_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);
// consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2 // consider all timeAlignmentTimers as expired and perform the corresponding actions in clause 5.2
// TODO // TODO
...@@ -177,9 +192,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac) ...@@ -177,9 +192,7 @@ void reset_mac_inst(NR_UE_MAC_INST_t *nr_mac)
nr_mac->scheduling_info.sr_id = -1; // invalid init value nr_mac->scheduling_info.sr_id = -1; // invalid init value
// cancel any triggered Buffer Status Reporting procedure // cancel any triggered Buffer Status Reporting procedure
nr_mac->scheduling_info.periodicBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING; nr_mac->scheduling_info.BSR_reporting_active = NR_BSR_TRIGGER_NONE;
nr_mac->scheduling_info.retxBSR_SF = NR_MAC_UE_BSR_TIMER_NOT_RUNNING;
nr_mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
// cancel any triggered Power Headroom Reporting procedure // cancel any triggered Power Headroom Reporting procedure
// TODO PHR not implemented yet // TODO PHR not implemented yet
......
...@@ -2511,8 +2511,7 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slot) ...@@ -2511,8 +2511,7 @@ int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slot)
// release all pucch resource // release all pucch resource
//mac->physicalConfigDedicated = NULL; // todo //mac->physicalConfigDedicated = NULL; // todo
//mac->ul_active = 0; // todo //mac->ul_active = 0; // todo
mac->BSR_reporting_active = si->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
NR_BSR_TRIGGER_NONE;
LOG_I(NR_MAC, "[UE %d] Release all SRs \n", mac->ue_id); LOG_I(NR_MAC, "[UE %d] Release all SRs \n", mac->ue_id);
} }
si->SR_pending = 0; si->SR_pending = 0;
......
...@@ -91,9 +91,74 @@ fapi_nr_ul_config_request_pdu_t *lockGet_ul_config(NR_UE_MAC_INST_t *mac, frame_ ...@@ -91,9 +91,74 @@ fapi_nr_ul_config_request_pdu_t *lockGet_ul_config(NR_UE_MAC_INST_t *mac, frame_
return pdu; return pdu;
} }
static nr_lcordered_info_t *get_lc_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid)
{
nr_lcordered_info_t *lc_info = NULL;
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
if (mac->lc_ordered_list.array[i]->lcid == lcid) {
lc_info = mac->lc_ordered_list.array[i];
break;
}
}
return lc_info;
}
static int lcid_buffer_index(NR_LogicalChannelIdentity_t lcid)
{
AssertFatal(lcid > 0 && lcid <= NR_MAX_NUM_LCID, "Invalid LCID %ld\n", lcid);
return lcid - 1;
}
NR_LC_SCHEDULING_INFO *get_scheduling_info_from_lcid(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid)
{
int idx = lcid_buffer_index(lcid);
return &mac->scheduling_info.lc_sched_info[idx];
}
static void trigger_regular_bsr(NR_UE_MAC_INST_t *mac, NR_LogicalChannelIdentity_t lcid, bool sr_DelayTimerApplied)
{
// Regular BSR trigger
mac->scheduling_info.BSR_reporting_active |= NR_BSR_TRIGGER_REGULAR;
mac->scheduling_info.regularBSR_trigger_lcid = lcid;
LOG_D(NR_MAC, "Triggering regular BSR for LCID %ld\n", lcid);
// if the BSR is triggered for a logical channel for which logicalChannelSR-DelayTimerApplied with value true
// start or restart the logicalChannelSR-DelayTimer
// else stop the logicalChannelSR-DelayTimer
if (sr_DelayTimerApplied)
nr_timer_start(&mac->scheduling_info.sr_DelayTimer);
else
nr_timer_stop(&mac->scheduling_info.sr_DelayTimer);
}
void update_mac_timers(NR_UE_MAC_INST_t *mac) void update_mac_timers(NR_UE_MAC_INST_t *mac)
{ {
nr_timer_tick(&mac->ra.contention_resolution_timer); nr_timer_tick(&mac->ra.contention_resolution_timer);
nr_timer_tick(&mac->scheduling_info.sr_DelayTimer);
bool retxBSR_expired = nr_timer_tick(&mac->scheduling_info.retxBSR_Timer);
if (retxBSR_expired) {
LOG_D(NR_MAC, "retxBSR timer expired\n");
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
NR_LogicalChannelIdentity_t lcid = lc_info->lcid;
// if at least one of the logical channels which belong to an LCG contains UL data
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
if (lc_sched_info->LCGID != NR_INVALID_LCGID && lc_sched_info->LCID_buffer_remain > 0) {
LOG_D(NR_MAC, "Triggering regular BSR after retxBSR timer expired\n");
trigger_regular_bsr(mac, lcid, lc_info->sr_DelayTimerApplied);
break;
}
}
}
bool periodicBSR_expired = nr_timer_tick(&mac->scheduling_info.periodicBSR_Timer);
if (periodicBSR_expired) {
// periodicBSR-Timer expires, trigger BSR
mac->scheduling_info.BSR_reporting_active |= NR_BSR_TRIGGER_PERIODIC;
LOG_D(NR_MAC, "[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry\n", mac->ue_id);
}
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) void remove_ul_config_last_item(fapi_nr_ul_config_request_pdu_t *pdu)
...@@ -545,7 +610,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, ...@@ -545,7 +610,7 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
//Optional Data only included if indicated in pduBitmap //Optional Data only included if indicated in pduBitmap
pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213 pusch_config_pdu->pusch_data.rv_index = 0; // 8.3 in 38.213
pusch_config_pdu->pusch_data.harq_process_id = 0; pusch_config_pdu->pusch_data.harq_process_id = 0;
pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data pusch_config_pdu->pusch_data.new_data_indicator = true; // new data
pusch_config_pdu->pusch_data.num_cb = 0; pusch_config_pdu->pusch_data.num_cb = 0;
pusch_config_pdu->tbslbrm = 0; pusch_config_pdu->tbslbrm = 0;
...@@ -796,6 +861,10 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, ...@@ -796,6 +861,10 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate); pusch_config_pdu->ldpcBaseGraph = get_BG(pusch_config_pdu->pusch_data.tb_size << 3, pusch_config_pdu->target_code_rate);
//The MAC entity shall restart retxBSR-Timer upon reception of a grant for transmission of new data on any UL-SCH
if (pusch_config_pdu->pusch_data.new_data_indicator && dci && dci->ulsch_indicator)
nr_timer_start(&mac->scheduling_info.retxBSR_Timer);
if (pusch_config_pdu->pusch_data.tb_size == 0) { if (pusch_config_pdu->pusch_data.tb_size == 0) {
LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n"); LOG_E(MAC, "Invalid TBS = 0. Probably caused by missed detection of DCI\n");
return -1; return -1;
...@@ -1037,6 +1106,97 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info ...@@ -1037,6 +1106,97 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info
LOG_E(NR_MAC, "Internal error, no scheduled_response function\n"); LOG_E(NR_MAC, "Internal error, no scheduled_response function\n");
} }
static void nr_trigger_sr(NR_UE_MAC_INST_t *mac)
{
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
// if a Regular BSR has been triggered and logicalChannelSR-DelayTimer is not running
if (((sched_info->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0)
|| is_nr_timer_active(sched_info->sr_DelayTimer))
return;
nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, sched_info->regularBSR_trigger_lcid);
AssertFatal(lc_info, "Couldn't find logical channel with LCID %ld\n", sched_info->regularBSR_trigger_lcid);
// if there is no UL-SCH resource available for a new transmission (ie we are at this point)
// if the MAC entity is configured with configured uplink grant(s) and the Regular BSR was triggered for a
// logical channel for which logicalChannelSR-Mask is set to false or
if (mac->current_UL_BWP->configuredGrantConfig && lc_info->lc_SRMask)
return;
// if the UL-SCH resources available for a new transmission do not meet the LCP mapping restrictions
// TODO not implemented
// trigger SR
sched_info->SR_pending = 1;
}
static void nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index)
{
// Reset All BSR Infos
for (int id = 0; id < NR_MAX_NUM_LCID; id++) {
// Reset transmission status
mac->scheduling_info.lc_sched_info[id].LCID_buffer_with_data = false;
}
for (int lcgid = 0; lcgid < NR_MAX_NUM_LCGID; lcgid++) {
// Reset Buffer Info
mac->scheduling_info.lcg_sched_info[lcgid].BSR = 0;
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes = 0;
}
bool bsr_regular_triggered = mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_REGULAR;
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
int lcid = lc_info->lcid;
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
int lcgid = lc_sched_info->LCGID;
// check if UL data for a logical channel which belongs to a LCG becomes available for transmission
if (lcgid != NR_INVALID_LCGID) {
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mac->ue_id,
mac->ue_id,
gNB_index,
frameP,
slotP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
0,
0);
lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer;
if (rlc_status.bytes_in_buffer > 0) {
LOG_D(NR_MAC,
"[UE %d] LCID %d LCGID %d has %d bytes to transmit at frame %d slot %d\n",
mac->ue_id,
lcid,
lcgid,
rlc_status.bytes_in_buffer,
frameP,
slotP);
lc_sched_info->LCID_buffer_with_data = true;
//Update BSR_bytes
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer;
if (!bsr_regular_triggered) {
bsr_regular_triggered = true;
trigger_regular_bsr(mac, lcid, lc_info->sr_DelayTimerApplied);
LOG_D(NR_MAC,
"[UE %d] MAC BSR Triggered LCID %d LCGID %d data become available at %d.%d\n",
mac->ue_id,
lcid,
lcgid,
frameP,
slotP);
}
}
}
}
}
void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
{ {
int cc_id = ul_info->cc_id; int cc_id = ul_info->cc_id;
...@@ -1054,6 +1214,11 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) ...@@ -1054,6 +1214,11 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
if(mac->state == UE_CONNECTED) if(mac->state == UE_CONNECTED)
nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx); nr_ue_periodic_srs_scheduling(mac, frame_tx, slot_tx);
// Call BSR procedure as described in Section 5.4.5 in 38.321
// Check whether BSR is triggered before scheduling ULSCH
if(mac->state == UE_CONNECTED)
nr_update_bsr(mac, frame_tx, slot_tx, gNB_index);
// Schedule ULSCH only if the current frame and slot match those in ul_config_req // Schedule ULSCH only if the current frame and slot match those in ul_config_req
// AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus) // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus)
uint8_t ulsch_input_buffer_array[NFAPI_MAX_NUM_UL_PDU][MAX_ULSCH_PAYLOAD_BYTES]; uint8_t ulsch_input_buffer_array[NFAPI_MAX_NUM_UL_PDU][MAX_ULSCH_PAYLOAD_BYTES];
...@@ -1120,199 +1285,43 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info) ...@@ -1120,199 +1285,43 @@ void nr_ue_ul_scheduler(NR_UE_MAC_INST_t *mac, nr_uplink_indication_t *ul_info)
mac->if_module->scheduled_response(&scheduled_response); mac->if_module->scheduled_response(&scheduled_response);
} }
if(mac->state == UE_CONNECTED)
nr_trigger_sr(mac);
// update Bj for all active lcids before LCP procedure // update Bj for all active lcids before LCP procedure
LOG_D(NR_MAC, "====================[Frame %d][Slot %d]Logical Channel Prioritization===========\n", frame_tx, slot_tx); LOG_D(NR_MAC, "====================[Frame %d][Slot %d]Logical Channel Prioritization===========\n", frame_tx, slot_tx);
for (int i = 0; i < mac->lc_ordered_list.count; i++) { for (int i = 0; i < mac->lc_ordered_list.count; i++) {
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
int lcid = lc_info->lcid; int lcid = lc_info->lcid;
// max amount of data that can be buffered/accumulated in a logical channel buffer // max amount of data that can be buffered/accumulated in a logical channel buffer
int32_t bucketSize_max = lc_info->bucket_size; uint32_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);
/* /*
measure Bj measure Bj
increment the value of Bj by product PBR * T increment the value of Bj by product PBR * T
*/ */
int T = 1; // time elapsed since Bj was last incremented NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
int32_t bj = mac->scheduling_info.lc_sched_info[lcid - 1].Bj; int32_t bj = sched_info->Bj;
bj += nr_get_pbr(lc_info->prioritisedBitRate) * T; if (lc_info->pbr < UINT_MAX) {
if (lc_info->prioritisedBitRate == NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) uint32_t slots_elapsed = nr_timer_elapsed_time(sched_info->Bj_timer); // slots elapsed since Bj was last incremented
bj = nr_get_pbr(lc_info->prioritisedBitRate); // 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 // bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization
mac->scheduling_info.lc_sched_info[lcid - 1].Bj = min(bj, bucketSize_max); 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
// First check ReTxBSR Timer because it is always configured
// Decrement ReTxBSR Timer if it is running and not null
if ((mac->scheduling_info.retxBSR_SF != NR_MAC_UE_BSR_TIMER_NOT_RUNNING) && (mac->scheduling_info.retxBSR_SF != 0)) {
mac->scheduling_info.retxBSR_SF--;
}
// Decrement Periodic Timer if it is running and not null
if ((mac->scheduling_info.periodicBSR_SF != NR_MAC_UE_BSR_TIMER_NOT_RUNNING) && (mac->scheduling_info.periodicBSR_SF != 0)) {
mac->scheduling_info.periodicBSR_SF--;
}
//Check whether Regular BSR is triggered
if (nr_update_bsr(mac, frame_tx, slot_tx, gNB_index) == true) {
// call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures
// outlined in Sections 5.4.4 an 5.4.5 of 38.321
mac->scheduling_info.SR_pending = 1;
// Regular BSR trigger
mac->BSR_reporting_active |= NR_BSR_TRIGGER_REGULAR;
LOG_D(NR_MAC, "[UE %d][BSR] Regular BSR Triggered Frame %d slot %d SR for PUSCH is pending\n", mac->ue_id, frame_tx, slot_tx);
} }
if(mac->state >= UE_PERFORMING_RA) if(mac->state >= UE_PERFORMING_RA)
nr_ue_pucch_scheduler(mac, frame_tx, slot_tx, ul_info->phy_data); nr_ue_pucch_scheduler(mac, frame_tx, slot_tx, ul_info->phy_data);
} }
bool nr_update_bsr(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP, uint8_t gNB_index) static uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value)
{
bool bsr_regular_triggered = false;
uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined
uint32_t lcgid_buffer_remain[NR_MAX_NUM_LCGID] = {0,0,0,0,0,0,0,0};
int32_t lcid_bytes_in_buffer[NR_MAX_NUM_LCID];
/* Array for ordering LCID with data per decreasing priority order */
uint8_t lcid_reordered_array[NR_MAX_NUM_LCID] = {
NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID,
NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID,
NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID,
NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID,
NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID, NR_MAX_NUM_LCID,
};
uint8_t pos_next = 0;
//uint8_t highest_priority = 16;
uint8_t array_index = 0;
// Reset All BSR Infos
lcid_bytes_in_buffer[0] = 0;
// TO BE NOTED LCID = 0 is excluded from buffers
// so they need to be addressed with lcid - 1
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
// Reset transmission status
lcid_bytes_in_buffer[lcid - 1] = 0;
mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_with_data = false;
}
for (int lcgid = 0; lcgid < NR_MAX_NUM_LCGID; lcgid++) {
// Reset Buffer Info
mac->scheduling_info.lcg_sched_info[lcgid].BSR = 0;
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes = 0;
}
//Get Buffer Occupancy and fill lcid_reordered_array
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
int lcid = mac->lc_ordered_list.array[i]->lcid;
int lcgid = mac->scheduling_info.lc_sched_info[lcid - 1].LCGID;
// Store already available data to transmit per Group
if (lcgid < NR_MAX_NUM_LCGID) {
lcgid_buffer_remain[lcgid] += mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_remain;
}
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mac->ue_id,
mac->ue_id,
gNB_index,
frameP,
slotP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
0,
0);
lcid_bytes_in_buffer[lcid - 1] = rlc_status.bytes_in_buffer;
if (rlc_status.bytes_in_buffer > 0) {
LOG_D(NR_MAC,
"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d slot %d\n",
mac->ue_id,
lcid,
lcgid,
rlc_status.bytes_in_buffer,
frameP,
slotP);
mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_with_data = true;
//Update BSR_bytes and position in lcid_reordered_array only if Group is defined
if (lcgid < NR_MAX_NUM_LCGID) {
num_lcid_with_data ++;
// sum lcid buffer which has same lcgid
mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer;
//Fill in the array
array_index = 0;
do {
//if (mac->logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority) {
if (1) { // todo
//Insert if priority is higher or equal (lower or equal in value)
for (pos_next = num_lcid_with_data - 1; pos_next > array_index; pos_next--) {
lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1];
}
lcid_reordered_array[array_index] = lcid;
break;
}
array_index ++;
} while ((array_index < num_lcid_with_data) && (array_index <= NR_MAX_NUM_LCID));
}
}
}
// Check whether a regular BSR can be triggered according to the first cases in 38.321
if (num_lcid_with_data) {
LOG_D(NR_MAC, "[UE %d] PDCCH Tick at frame %d slot %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n",
mac->ue_id,
frameP,
slotP,
num_lcid_with_data,
lcid_reordered_array[0],
lcid_reordered_array[1],
lcid_reordered_array[2]);
for (array_index = 0; array_index < num_lcid_with_data; array_index++) {
int lcid = lcid_reordered_array[array_index];
/* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity
either the data belongs to a logical channel with higher priority than the priorities of the logical channels
which belong to any LCG and for which data is already available for transmission
*/
{
bsr_regular_triggered = true;
LOG_D(NR_MAC,
"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%ld data become available at frame %d slot %d\n",
mac->ue_id,
lcid,
mac->scheduling_info.lc_sched_info[lcid - 1].LCGID,
frameP,
slotP);
break;
}
}
// Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission
if (mac->scheduling_info.retxBSR_SF == 0) {
bsr_regular_triggered = true;
if ((mac->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0) {
LOG_I(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d slot %d\n", mac->ue_id, frameP, slotP);
}
}
}
//Store Buffer Occupancy in remain buffers for next TTI
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_remain = lcid_bytes_in_buffer[lcid - 1];
}
return bsr_regular_triggered;
}
uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int value)
{ {
uint8_t ju, jm, jl; uint8_t ju, jm, jl;
int ascend; int ascend;
...@@ -1347,127 +1356,6 @@ uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int valu ...@@ -1347,127 +1356,6 @@ uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, int valu
} }
} }
int nr_get_sf_periodicBSRTimer(uint8_t sf_offset) {
switch (sf_offset) {
case NR_BSR_Config__periodicBSR_Timer_sf1:
return 1;
break;
case NR_BSR_Config__periodicBSR_Timer_sf5:
return 5;
break;
case NR_BSR_Config__periodicBSR_Timer_sf10:
return 10;
break;
case NR_BSR_Config__periodicBSR_Timer_sf16:
return 16;
break;
case NR_BSR_Config__periodicBSR_Timer_sf20:
return 20;
break;
case NR_BSR_Config__periodicBSR_Timer_sf32:
return 32;
break;
case NR_BSR_Config__periodicBSR_Timer_sf40:
return 40;
break;
case NR_BSR_Config__periodicBSR_Timer_sf64:
return 64;
break;
case NR_BSR_Config__periodicBSR_Timer_sf80:
return 80;
break;
case NR_BSR_Config__periodicBSR_Timer_sf128:
return 128;
break;
case NR_BSR_Config__periodicBSR_Timer_sf160:
return 160;
break;
case NR_BSR_Config__periodicBSR_Timer_sf320:
return 320;
break;
case NR_BSR_Config__periodicBSR_Timer_sf640:
return 640;
break;
case NR_BSR_Config__periodicBSR_Timer_sf1280:
return 1280;
break;
case NR_BSR_Config__periodicBSR_Timer_sf2560:
return 2560;
break;
case NR_BSR_Config__periodicBSR_Timer_infinity:
default:
return 0xFFFF;
break;
}
}
int nr_get_sf_retxBSRTimer(uint8_t sf_offset) {
switch (sf_offset) {
case NR_BSR_Config__retxBSR_Timer_sf10:
return 10;
break;
case NR_BSR_Config__retxBSR_Timer_sf20:
return 20;
break;
case NR_BSR_Config__retxBSR_Timer_sf40:
return 40;
break;
case NR_BSR_Config__retxBSR_Timer_sf80:
return 80;
break;
case NR_BSR_Config__retxBSR_Timer_sf160:
return 160;
break;
case NR_BSR_Config__retxBSR_Timer_sf320:
return 320;
break;
case NR_BSR_Config__retxBSR_Timer_sf640:
return 640;
break;
case NR_BSR_Config__retxBSR_Timer_sf1280:
return 1280;
break;
case NR_BSR_Config__retxBSR_Timer_sf2560:
return 2560;
break;
case NR_BSR_Config__retxBSR_Timer_sf5120:
return 5120;
break;
case NR_BSR_Config__retxBSR_Timer_sf10240:
return 10240;
break;
default:
return -1;
break;
}
}
// PUSCH scheduler: // PUSCH scheduler:
// - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2, // - Calculate the slot in which ULSCH should be scheduled. This is current slot + K2,
// - where K2 is the offset between the slot in which UL DCI is received and the slot // - where K2 is the offset between the slot in which UL DCI is received and the slot
...@@ -2592,47 +2480,30 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac, ...@@ -2592,47 +2480,30 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
mac_ce_p->bsr_header_len = 0; mac_ce_p->bsr_header_len = 0;
mac_ce_p->phr_header_len = 0; //sizeof(SCH_SUBHEADER_FIXED); mac_ce_p->phr_header_len = 0; //sizeof(SCH_SUBHEADER_FIXED);
int lcg_id = 0; int lcg_id = 0;
while (lcg_id < NR_MAX_NUM_LCGID) { while (lcg_id != NR_INVALID_LCGID) {
if (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes) { if (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes) {
num_lcg_id_with_data++; num_lcg_id_with_data++;
} }
lcg_id++; lcg_id++;
} }
//Restart ReTxBSR Timer at new grant indication (38.321) // Compute BSR Length if Regular or Periodic BSR is triggered
if (mac->scheduling_info.retxBSR_SF != NR_MAC_UE_BSR_TIMER_NOT_RUNNING) { // WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing
mac->scheduling_info.retxBSR_SF = nr_get_sf_retxBSRTimer(mac->scheduling_info.retxBSR_Timer); // if there remains less than 1 LCGROUP with data after Tx
} if (mac->scheduling_info.BSR_reporting_active) {
AssertFatal((mac->scheduling_info.BSR_reporting_active & NR_BSR_TRIGGER_PADDING) == 0,
// periodicBSR-Timer expires, trigger BSR
if ((mac->scheduling_info.periodicBSR_Timer != NR_BSR_Config__periodicBSR_Timer_infinity)
&& (mac->scheduling_info.periodicBSR_SF == 0)) {
// Trigger BSR Periodic
mac->BSR_reporting_active |= NR_BSR_TRIGGER_PERIODIC;
LOG_D(NR_MAC,
"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
mac->ue_id,
frameP,
subframe,
buflen);
}
//Compute BSR Length if Regular or Periodic BSR is triggered
//WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx
if (mac->BSR_reporting_active) {
AssertFatal((mac->BSR_reporting_active & NR_BSR_TRIGGER_PADDING) == 0,
"Inconsistent BSR Trigger=%d !\n", "Inconsistent BSR Trigger=%d !\n",
mac->BSR_reporting_active); mac->scheduling_info.BSR_reporting_active);
//A Regular or Periodic BSR can only be sent if TBS is sufficient as transmitting only a BSR is not allowed if UE has data to transmit // A Regular or Periodic BSR can only be sent if TBS is sufficient
// as transmitting only a BSR is not allowed if UE has data to transmit
if (num_lcg_id_with_data <= 1) { if (num_lcg_id_with_data <= 1) {
if (buflen >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED)+1)) { if (buflen >= (sizeof(NR_BSR_SHORT) + sizeof(NR_MAC_SUBHEADER_FIXED) + 1)) {
mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); // 1 byte mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); // 1 byte
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); // 1 byte mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); // 1 byte
} }
} else { } else {
if (buflen >= (num_lcg_id_with_data+1+sizeof(NR_MAC_SUBHEADER_SHORT)+1)) { if (buflen >= (num_lcg_id_with_data + 1 + sizeof(NR_MAC_SUBHEADER_SHORT) + 1)) {
mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; // variable size mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; // variable size
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); // 2 bytes mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); // 2 bytes
} }
...@@ -2662,8 +2533,8 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac, ...@@ -2662,8 +2533,8 @@ static int nr_ue_get_sdu_mac_ce_pre(NR_UE_MAC_INST_t *mac,
*/ */
static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
int CC_id, int CC_id,
frame_t frameP, frame_t frame,
sub_frame_t subframe, slot_t slot,
uint8_t gNB_index, uint8_t gNB_index,
uint8_t *ulsch_buffer, uint8_t *ulsch_buffer,
uint16_t buflen, uint16_t buflen,
...@@ -2671,22 +2542,22 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, ...@@ -2671,22 +2542,22 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
{ {
// Compute BSR Values and update Nb LCGID with data after multiplexing // Compute BSR Values and update Nb LCGID with data after multiplexing
unsigned short padding_len = 0; unsigned short padding_len = 0;
int lcg_id = 0;
int num_lcg_id_with_data = 0; int num_lcg_id_with_data = 0;
int lcg_id_bsr_trunc = 0; int lcg_id_bsr_trunc = 0;
for (lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) { NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
for (int lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) {
if (mac_ce_p->bsr_ce_len == sizeof(NR_BSR_SHORT)) { if (mac_ce_p->bsr_ce_len == sizeof(NR_BSR_SHORT)) {
mac->scheduling_info.lcg_sched_info[lcg_id].BSR = sched_info->lcg_sched_info[lcg_id].BSR =
nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE,
NR_SHORT_BSR_TABLE_SIZE, NR_SHORT_BSR_TABLE_SIZE,
mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes); sched_info->lcg_sched_info[lcg_id].BSR_bytes);
} else { } else {
mac->scheduling_info.lcg_sched_info[lcg_id].BSR = sched_info->lcg_sched_info[lcg_id].BSR =
nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE,
NR_LONG_BSR_TABLE_SIZE, NR_LONG_BSR_TABLE_SIZE,
mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes); sched_info->lcg_sched_info[lcg_id].BSR_bytes);
} }
if (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes) { if (sched_info->lcg_sched_info[lcg_id].BSR_bytes) {
num_lcg_id_with_data++; num_lcg_id_with_data++;
lcg_id_bsr_trunc = lcg_id; lcg_id_bsr_trunc = lcg_id;
} }
...@@ -2709,11 +2580,11 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, ...@@ -2709,11 +2580,11 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
if ((padding_len) && (mac_ce_p->bsr_len == 0)) { if ((padding_len) && (mac_ce_p->bsr_len == 0)) {
/* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR */ /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR */
if (padding_len >= (num_lcg_id_with_data+1+sizeof(NR_MAC_SUBHEADER_SHORT))) { if (padding_len >= (num_lcg_id_with_data + 1 + sizeof(NR_MAC_SUBHEADER_SHORT))) {
mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size mac_ce_p->bsr_ce_len = num_lcg_id_with_data + 1; //variable size
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_SHORT); //2 bytes
// Trigger BSR Padding // Trigger BSR Padding
mac->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING; sched_info->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING;
} else if (padding_len >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED))) { } else if (padding_len >= (sizeof(NR_BSR_SHORT)+sizeof(NR_MAC_SUBHEADER_FIXED))) {
mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte mac_ce_p->bsr_ce_len = sizeof(NR_BSR_SHORT); //1 byte
mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte mac_ce_p->bsr_header_len = sizeof(NR_MAC_SUBHEADER_FIXED); //1 byte
...@@ -2722,9 +2593,9 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, ...@@ -2722,9 +2593,9 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
// REPORT SHORT TRUNCATED BSR // REPORT SHORT TRUNCATED BSR
// Get LCGID of highest priority LCID with data (todo) // Get LCGID of highest priority LCID with data (todo)
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) { for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
lcg_id = mac->scheduling_info.lc_sched_info[lcid - 1].LCGID; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
if ((lcg_id < NR_MAX_NUM_LCGID) && (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes)) { if ((sched_info->LCGID != NR_INVALID_LCGID) && (mac->scheduling_info.lcg_sched_info[sched_info->LCGID].BSR_bytes)) {
lcg_id_bsr_trunc = lcg_id; lcg_id_bsr_trunc = sched_info->LCGID;
} }
} }
} else { } else {
...@@ -2733,7 +2604,7 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, ...@@ -2733,7 +2604,7 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
} }
// Trigger BSR Padding // Trigger BSR Padding
mac->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING; sched_info->BSR_reporting_active |= NR_BSR_TRIGGER_PADDING;
} }
mac_ce_p->bsr_len = mac_ce_p->bsr_header_len + mac_ce_p->bsr_ce_len; mac_ce_p->bsr_len = mac_ce_p->bsr_header_len + mac_ce_p->bsr_ce_len;
...@@ -2749,63 +2620,63 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, ...@@ -2749,63 +2620,63 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
} else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_SHORT)) { } else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_SHORT)) {
mac_ce_p->bsr_s = NULL; mac_ce_p->bsr_s = NULL;
mac_ce_p->bsr_t = NULL; mac_ce_p->bsr_t = NULL;
mac_ce_p->bsr_l->Buffer_size0 = mac->scheduling_info.lcg_sched_info[0].BSR; mac_ce_p->bsr_l->Buffer_size0 = sched_info->lcg_sched_info[0].BSR;
mac_ce_p->bsr_l->Buffer_size1 = mac->scheduling_info.lcg_sched_info[1].BSR; mac_ce_p->bsr_l->Buffer_size1 = sched_info->lcg_sched_info[1].BSR;
mac_ce_p->bsr_l->Buffer_size2 = mac->scheduling_info.lcg_sched_info[2].BSR; mac_ce_p->bsr_l->Buffer_size2 = sched_info->lcg_sched_info[2].BSR;
mac_ce_p->bsr_l->Buffer_size3 = mac->scheduling_info.lcg_sched_info[3].BSR; mac_ce_p->bsr_l->Buffer_size3 = sched_info->lcg_sched_info[3].BSR;
mac_ce_p->bsr_l->Buffer_size4 = mac->scheduling_info.lcg_sched_info[4].BSR; mac_ce_p->bsr_l->Buffer_size4 = sched_info->lcg_sched_info[4].BSR;
mac_ce_p->bsr_l->Buffer_size5 = mac->scheduling_info.lcg_sched_info[5].BSR; mac_ce_p->bsr_l->Buffer_size5 = sched_info->lcg_sched_info[5].BSR;
mac_ce_p->bsr_l->Buffer_size6 = mac->scheduling_info.lcg_sched_info[6].BSR; mac_ce_p->bsr_l->Buffer_size6 = sched_info->lcg_sched_info[6].BSR;
mac_ce_p->bsr_l->Buffer_size7 = mac->scheduling_info.lcg_sched_info[7].BSR; mac_ce_p->bsr_l->Buffer_size7 = sched_info->lcg_sched_info[7].BSR;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] Frame %d subframe %d BSR Trig=%d report LONG BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 " "[UE %d] Frame %d subframe %d BSR Trig=%d report LONG BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 "
"%d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n", "%d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
mac->BSR_reporting_active, sched_info->BSR_reporting_active,
mac->scheduling_info.lcg_sched_info[0].BSR, sched_info->lcg_sched_info[0].BSR,
mac->scheduling_info.lcg_sched_info[1].BSR, sched_info->lcg_sched_info[1].BSR,
mac->scheduling_info.lcg_sched_info[2].BSR, sched_info->lcg_sched_info[2].BSR,
mac->scheduling_info.lcg_sched_info[3].BSR, sched_info->lcg_sched_info[3].BSR,
mac->scheduling_info.lcg_sched_info[4].BSR, sched_info->lcg_sched_info[4].BSR,
mac->scheduling_info.lcg_sched_info[5].BSR, sched_info->lcg_sched_info[5].BSR,
mac->scheduling_info.lcg_sched_info[6].BSR, sched_info->lcg_sched_info[6].BSR,
mac->scheduling_info.lcg_sched_info[7].BSR); sched_info->lcg_sched_info[7].BSR);
} else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_FIXED)) { } else if (mac_ce_p->bsr_header_len == sizeof(NR_MAC_SUBHEADER_FIXED)) {
mac_ce_p->bsr_l = NULL; mac_ce_p->bsr_l = NULL;
if ((mac_ce_p->bsr_t != NULL) && (mac->BSR_reporting_active & NR_BSR_TRIGGER_PADDING)) { if ((mac_ce_p->bsr_t != NULL) && (sched_info->BSR_reporting_active & NR_BSR_TRIGGER_PADDING)) {
//Truncated BSR //Truncated BSR
mac_ce_p->bsr_s = NULL; mac_ce_p->bsr_s = NULL;
mac_ce_p->bsr_t->LcgID = lcg_id_bsr_trunc; mac_ce_p->bsr_t->LcgID = lcg_id_bsr_trunc;
mac_ce_p->bsr_t->Buffer_size = mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR; mac_ce_p->bsr_t->Buffer_size = sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", "[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
mac->BSR_reporting_active, sched_info->BSR_reporting_active,
mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR, sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR,
lcg_id_bsr_trunc); lcg_id_bsr_trunc);
} else { } else {
mac_ce_p->bsr_t = NULL; mac_ce_p->bsr_t = NULL;
mac_ce_p->bsr_s->LcgID = lcg_id_bsr_trunc; mac_ce_p->bsr_s->LcgID = lcg_id_bsr_trunc;
mac_ce_p->bsr_s->Buffer_size = mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR; mac_ce_p->bsr_s->Buffer_size = sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", "[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
mac->BSR_reporting_active, sched_info->BSR_reporting_active,
mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR, sched_info->lcg_sched_info[lcg_id_bsr_trunc].BSR,
lcg_id_bsr_trunc); lcg_id_bsr_trunc);
} }
} }
LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", mac->ue_id); LOG_D(NR_MAC, "[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", mac->ue_id);
mac->scheduling_info.SR_pending = 0; sched_info->SR_pending = 0;
mac->scheduling_info.SR_COUNTER = 0; sched_info->SR_COUNTER = 0;
/* Actions when a BSR is sent */ /* Actions when a BSR is sent */
if (mac_ce_p->bsr_ce_len) { if (mac_ce_p->bsr_ce_len) {
...@@ -2816,17 +2687,15 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac, ...@@ -2816,17 +2687,15 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
mac_ce_p->bsr_header_len, mac_ce_p->bsr_header_len,
buflen); buflen);
// Reset ReTx BSR Timer // Reset ReTx BSR Timer
mac->scheduling_info.retxBSR_SF = nr_get_sf_retxBSRTimer(mac->scheduling_info.retxBSR_Timer); nr_timer_start(&sched_info->retxBSR_Timer);
LOG_D(NR_MAC, "[UE %d] MAC ReTx BSR Timer Reset =%d\n", mac->ue_id, mac->scheduling_info.retxBSR_SF);
// Reset Periodic Timer except when BSR is truncated // Reset Periodic Timer except when BSR is truncated
if ((mac_ce_p->bsr_t == NULL) && (mac->scheduling_info.periodicBSR_Timer != NR_BSR_Config__periodicBSR_Timer_infinity)) { if (mac_ce_p->bsr_t == NULL) {
mac->scheduling_info.periodicBSR_SF = nr_get_sf_periodicBSRTimer(mac->scheduling_info.periodicBSR_Timer); nr_timer_start(&sched_info->periodicBSR_Timer);
LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset =%d\n", mac->ue_id, mac->scheduling_info.periodicBSR_SF); LOG_D(NR_MAC, "[UE %d] MAC Periodic BSR Timer Reset\n", mac->ue_id);
} }
// Reset BSR Trigger flags // Reset BSR Trigger flags
mac->BSR_reporting_active = NR_BSR_TRIGGER_NONE; sched_info->BSR_reporting_active = NR_BSR_TRIGGER_NONE;
} }
} }
...@@ -2854,16 +2723,11 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac, ...@@ -2854,16 +2723,11 @@ long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
long *target) long *target)
{ {
/* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/ /* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/
long found_pbr = -1; nr_lcordered_info_t *lc_info = get_lc_info_from_lcid(mac, lc_num);
for (int i = 0; i < mac->lc_ordered_list.count; i++) { AssertFatal(lc_info, "Couldn't find logical channel with LCID %d\n", lc_num);
if (mac->lc_ordered_list.array[i]->lcid == lc_num) { uint32_t pbr = lc_info->pbr;
found_pbr = mac->lc_ordered_list.array[i]->prioritisedBitRate; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lc_num);
break; int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain;
}
}
AssertFatal(found_pbr >= 0, "Couldn't find LC config for ID %d\n", lc_num);
uint32_t pbr = nr_get_pbr(found_pbr);
int32_t lcid_remain_buffer = mac->scheduling_info.lc_sched_info[lc_num - 1].LCID_buffer_remain;
*target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr; *target = (same_priority_count > 1) ? min(buflen_remain_ep, pbr) : pbr;
long num_remaining_bytes = 0; long num_remaining_bytes = 0;
...@@ -2893,7 +2757,7 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_ ...@@ -2893,7 +2757,7 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_
// check whether there is any data in the rlc buffer corresponding to active lcs // check whether there is any data in the rlc buffer corresponding to active lcs
for (uint8_t id = 0; id < total_active_lcids; id++) { for (uint8_t id = 0; id < total_active_lcids; id++) {
int lcid = lcid_ordered_array[id].lcid; int lcid = lcid_ordered_array[id].lcid;
if (data_status_lcbuffers[lcid - 1]) { if (data_status_lcbuffers[lcid_buffer_index(lcid)]) {
return true; return true;
} }
} }
...@@ -2908,7 +2772,8 @@ static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids ...@@ -2908,7 +2772,8 @@ static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids
// selection of logical channels with Bj > 0 // selection of logical channels with Bj > 0
for (int i = 0; i < mac->lc_ordered_list.count; i++) { for (int i = 0; i < mac->lc_ordered_list.count; i++) {
int lcid = mac->lc_ordered_list.array[i]->lcid; int lcid = mac->lc_ordered_list.array[i]->lcid;
if (mac->scheduling_info.lc_sched_info[lcid - 1].Bj > 0) { NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
if (sched_info->Bj > 0) {
active_lcids[*num_active_lcids] = *mac->lc_ordered_list.array[i]; active_lcids[*num_active_lcids] = *mac->lc_ordered_list.array[i];
(*num_active_lcids)++; (*num_active_lcids)++;
LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, *num_active_lcids); LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, *num_active_lcids);
...@@ -2917,8 +2782,8 @@ static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids ...@@ -2917,8 +2782,8 @@ static void select_logical_channels(NR_UE_MAC_INST_t *mac, int *num_active_lcids
} }
static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
frame_t frameP, frame_t frame,
sub_frame_t subframe, slot_t slot,
uint8_t gNB_index, uint8_t gNB_index,
uint16_t buflen, uint16_t buflen,
int16_t *buflen_remain, int16_t *buflen_remain,
...@@ -2933,16 +2798,16 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, ...@@ -2933,16 +2798,16 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
bool *lcids_data_status, bool *lcids_data_status,
uint8_t *num_lcids_same_priority) uint8_t *num_lcids_same_priority)
{ {
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG); const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
/* prepare the MAC sdu */ /* prepare the MAC sdu */
int32_t lcid_remain_buffer = sched_info->lc_sched_info[lcid - 1].LCID_buffer_remain; NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
int32_t lcid_remain_buffer = sched_info->LCID_buffer_remain;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n", "[UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
*counter, *counter,
*buflen_remain, *buflen_remain,
lcid_remain_buffer, lcid_remain_buffer,
...@@ -2961,7 +2826,7 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, ...@@ -2961,7 +2826,7 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
uint16_t sdu_length = mac_rlc_data_req(mac->ue_id, uint16_t sdu_length = mac_rlc_data_req(mac->ue_id,
mac->ue_id, mac->ue_id,
gNB_index, gNB_index,
frameP, frame,
ENB_FLAG_NO, ENB_FLAG_NO,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -2980,21 +2845,22 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, ...@@ -2980,21 +2845,22 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
// currently the Bj is drecremented by size of MAC SDus everytime it is served to logical channel, so by this approach there // currently the Bj is drecremented by size of MAC SDus everytime it is served to logical channel, so by this approach there
// will be more chance for lower priority logical channels to be served in the next TTI // will be more chance for lower priority logical channels to be served in the next TTI
// second approach can also be followed where Bj is decremented only in the first round but not in the subsequent rounds // second approach can also be followed where Bj is decremented only in the first round but not in the subsequent rounds
sched_info->lc_sched_info[lcid - 1].Bj -= sdu_length; // TODO avoid Bj to go below 0 sched_info->Bj -= sdu_length; // TODO avoid Bj to go below 0
LOG_D(NR_MAC, LOG_D(NR_MAC,
"decrement Bj of the lcid %d by size of sdu length = %d and new Bj for lcid %d is %d\n", "decrement Bj of the lcid %d by size of sdu length = %d and new Bj for lcid %d is %d\n",
lcid, lcid,
sdu_length, sdu_length,
lcid, lcid,
sched_info->lc_sched_info[lcid - 1].Bj); sched_info->Bj);
int lc_idx = lcid_buffer_index(lcid);
if (sdu_length > 0) { if (sdu_length > 0) {
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID " "[UE %d] [%d.%d] UL-DXCH -> ULSCH, Generating UL MAC sub-PDU for SDU %d, length %d bytes, RB with LCID "
"0x%02x (buflen (TBS) %d bytes)\n", "0x%02x (buflen (TBS) %d bytes)\n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
(*num_sdus) + 1, (*num_sdus) + 1,
sdu_length, sdu_length,
lcid, lcid,
...@@ -3019,7 +2885,7 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3019,7 +2885,7 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
(*num_sdus)++; (*num_sdus)++;
} else { } else {
*pdu -= sh_size; *pdu -= sh_size;
lcids_data_status[lcid - 1] = false; lcids_data_status[lc_idx] = false;
(*num_lcids_same_priority)--; (*num_lcids_same_priority)--;
LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x\n and hence set to false", lcid); LOG_D(NR_MAC, "No data to transmit for RB with LCID 0x%02x\n and hence set to false", lcid);
return 0; return 0;
...@@ -3028,31 +2894,30 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3028,31 +2894,30 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
*buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size); *buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
// Update Buffer remain and BSR bytes after transmission // Update Buffer remain and BSR bytes after transmission
NR_LC_SCHEDULING_INFO *lc_info = &sched_info->lc_sched_info[0] + lcid - 1; NR_LCG_SCHEDULING_INFO *lcg_info = &mac->scheduling_info.lcg_sched_info[0];
NR_LCG_SCHEDULING_INFO *lcg_info = &sched_info->lcg_sched_info[0]; sched_info->LCID_buffer_remain -= sdu_length;
lc_info->LCID_buffer_remain -= sdu_length; (lcg_info + sched_info->LCGID)->BSR_bytes -= sdu_length;
(lcg_info + lc_info->LCGID)->BSR_bytes -= sdu_length;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%ld = %d\n", "[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%ld = %d\n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
lc_info->LCGID, sched_info->LCGID,
(lcg_info + lc_info->LCGID)->BSR_bytes); (lcg_info + sched_info->LCGID)->BSR_bytes);
if ((lcg_info + lc_info->LCGID)->BSR_bytes < 0) if ((lcg_info + sched_info->LCGID)->BSR_bytes < 0)
(lcg_info + lc_info->LCGID)->BSR_bytes = 0; (lcg_info + sched_info->LCGID)->BSR_bytes = 0;
// update number of bytes served from the current lcid // update number of bytes served from the current lcid
lcids_bytes_tot[lcid - 1] += (sdu_length + (count_same_priority_lcids > 1 ? 1 : 0) * sh_size); lcids_bytes_tot[lc_idx] += (sdu_length + (count_same_priority_lcids > 1 ? 1 : 0) * sh_size);
if ((*counter == 0 && lcids_bytes_tot[lcid - 1] >= target) if ((*counter == 0 && lcids_bytes_tot[lc_idx] >= target)
|| (count_same_priority_lcids > 1 || (count_same_priority_lcids > 1
&& lcids_bytes_tot[lcid - 1] >= buflen_ep)) { // only prioritized bit rate should be taken from logical channel in && lcids_bytes_tot[lc_idx] >= buflen_ep)) { // only prioritized bit rate should be taken from logical channel in
// the first lcp run except when infinity // the first lcp run except when infinity
LOG_D(NR_MAC, LOG_D(NR_MAC,
"Total number bytes read from rlc buffer for lcid %d are %d\n", "Total number bytes read from rlc buffer for lcid %d are %d\n",
lcid, lcid,
lcids_bytes_tot[lcid - 1]); lcids_bytes_tot[lc_idx]);
(*num_lcids_same_priority)--; (*num_lcids_same_priority)--;
return 0; return 0;
} }
...@@ -3065,16 +2930,16 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3065,16 +2930,16 @@ static bool fill_mac_sdu(NR_UE_MAC_INST_t *mac,
the selected sub-header for the payload sub-PDUs is NR_MAC_SUBHEADER_LONG the selected sub-header for the payload sub-PDUs is NR_MAC_SUBHEADER_LONG
* @module_idP Module ID * @module_idP Module ID
* @CC_id Component Carrier index * @CC_id Component Carrier index
* @frameP current UL frame * @frame current UL frame
* @subframe current UL slot * @slot current UL slot
* @gNB_index gNB index * @gNB_index gNB index
* @ulsch_buffer Pointer to ULSCH PDU * @ulsch_buffer Pointer to ULSCH PDU
* @buflen TBS * @buflen TBS
*/ */
uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
int CC_id, int CC_id,
frame_t frameP, frame_t frame,
sub_frame_t subframe, slot_t slot,
uint8_t gNB_index, uint8_t gNB_index,
uint8_t *ulsch_buffer, uint8_t *ulsch_buffer,
uint16_t buflen) uint16_t buflen)
...@@ -3099,7 +2964,6 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3099,7 +2964,6 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
//NR_POWER_HEADROOM_CMD phr; //NR_POWER_HEADROOM_CMD phr;
//mac_ce_p->phr_p = &phr; //mac_ce_p->phr_p = &phr;
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
//int highest_priority = 16; //int highest_priority = 16;
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG); const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
...@@ -3110,17 +2974,17 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3110,17 +2974,17 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
bool lcids_data_status[NR_MAX_NUM_LCID] = {0}; bool lcids_data_status[NR_MAX_NUM_LCID] = {0};
memset(lcids_data_status, 1, NR_MAX_NUM_LCID); memset(lcids_data_status, 1, NR_MAX_NUM_LCID);
uint32_t lcp_allocation_counter = // in the first run all the lc are allocated as per bj and prioritized bit rate but in subsequent runs, no need to consider
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 uint32_t lcp_allocation_counter = 0;
// bj and prioritized bit rate but just consider priority // 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 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 // because as per standard(TS38.321), all equal priority channels should be served equally
// nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length // nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length
mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p); mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(mac, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, mac_ce_p);
mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len; mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len;
LOG_D(NR_MAC, "[UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", mac->ue_id, frameP, subframe, buflen); LOG_D(NR_MAC, "[UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", mac->ue_id, frame, slot, buflen);
// selection of logical channels // selection of logical channels
int avail_lcids_count = 0; int avail_lcids_count = 0;
...@@ -3147,11 +3011,12 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3147,11 +3011,12 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
is placed in the MAC PDU before going on to next high priority logical channel is placed in the MAC PDU before going on to next high priority logical channel
*/ */
int lcid = lcids_bj_pos[id].lcid; int lcid = lcids_bj_pos[id].lcid;
NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid);
int idx = lcid_buffer_index(lcid);
// skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to // skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to
// MAC PDU // MAC PDU
if (!sched_info->lc_sched_info[lcid - 1].LCID_buffer_with_data || !lcids_data_status[lcid - 1]) { if (!lc_sched_info->LCID_buffer_with_data || !lcids_data_status[idx]) {
lcids_data_status[lcid - 1] = false; lcids_data_status[idx] = false;
continue; continue;
} }
...@@ -3168,8 +3033,8 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3168,8 +3033,8 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
"len %d bytes," "len %d bytes,"
"buflen_remain %d bytes)\n", "buflen_remain %d bytes)\n",
mac->ue_id, mac->ue_id,
frameP, frame,
subframe, slot,
lcid, lcid,
buflen, buflen,
mac_ce_p->sdu_length_total, mac_ce_p->sdu_length_total,
...@@ -3188,8 +3053,8 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3188,8 +3053,8 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
the target number of bytes to request from RLC via 'mac_rlc_data_req' the target number of bytes to request from RLC via 'mac_rlc_data_req'
*/ */
if (!fill_mac_sdu(mac, if (!fill_mac_sdu(mac,
frameP, frame,
subframe, slot,
gNB_index, gNB_index,
buflen, buflen,
&buflen_remain, &buflen_remain,
...@@ -3213,7 +3078,7 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, ...@@ -3213,7 +3078,7 @@ uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
//nr_ue_get_sdu_mac_ce_post recalculates all mac_ce related header fields since buffer has been changed after mac_rlc_data_req. //nr_ue_get_sdu_mac_ce_post recalculates all mac_ce related header fields since buffer has been changed after mac_rlc_data_req.
//Also, BSR padding is handled here after knowing mac_ce_p->sdu_length_total. //Also, BSR padding is handled here after knowing mac_ce_p->sdu_length_total.
nr_ue_get_sdu_mac_ce_post(mac, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p); nr_ue_get_sdu_mac_ce_post(mac, CC_id, frame, slot, gNB_index, ulsch_buffer, buflen, mac_ce_p);
if (mac_ce_p->tot_mac_ce_len > 0) { if (mac_ce_p->tot_mac_ce_len > 0) {
...@@ -3277,80 +3142,3 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TI ...@@ -3277,80 +3142,3 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TI
dl_config->number_pdus += 1; dl_config->number_pdus += 1;
ul_time_alignment->ta_apply = no_ta; 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;
}
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