Commit 3e9d3100 authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch...

Merge remote-tracking branch 'origin/implement_logical_channel_prioritization_ue' into integration_2023_w47
parents 67b0c006 31a63bc9
...@@ -305,6 +305,7 @@ Furthermore, the gNB and UE support ...@@ -305,6 +305,7 @@ Furthermore, the gNB and UE support
- HARQ procedures - HARQ procedures
* ULSCH scheduler * ULSCH scheduler
- Configuration of fapi PDU according to DCI - Configuration of fapi PDU according to DCI
- Logical channel prioritization of 'data from any logical channel'
* NR-CSIRS scheduler * NR-CSIRS scheduler
- Scheduling of NR-CSIRS reception - Scheduling of NR-CSIRS reception
- Fill UCI for CSI measurement reporting - Fill UCI for CSI measurement reporting
......
...@@ -975,7 +975,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf ...@@ -975,7 +975,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
nr_rrc_mac_config_req_ue_logicalChannelBearer(0, &rlc_toadd_list, NULL); nr_rrc_mac_config_req_ue_logicalChannelBearer(0, &rlc_toadd_list, NULL);
// free memory // free memory
free_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig); free_nr_noS1_bearer_config(&rbconfig, NULL);
} }
} }
} }
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
* \warning * \warning
*/ */
#define _GNU_SOURCE
//#include "mac_defs.h" //#include "mac_defs.h"
#include <NR_MAC_gNB/mac_proto.h> #include <NR_MAC_gNB/mac_proto.h>
#include "NR_MAC_UE/mac_proto.h" #include "NR_MAC_UE/mac_proto.h"
...@@ -39,6 +41,32 @@ ...@@ -39,6 +41,32 @@
#include "executables/softmodem-common.h" #include "executables/softmodem-common.h"
#include "SCHED_NR/phy_frame_config_nr.h" #include "SCHED_NR/phy_frame_config_nr.h"
const long logicalChannelGroup0_NR = 0;
typedef struct NR_LogicalChannelConfig__ul_SpecificParameters LcConfig_UlParamas_t;
const LcConfig_UlParamas_t NR_LCSRB1 = {
.priority = 1,
.prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity,
.logicalChannelGroup = (long *)&logicalChannelGroup0_NR};
const LcConfig_UlParamas_t NR_LCSRB2 = {
.priority = 3,
.prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity,
.logicalChannelGroup = (long *)&logicalChannelGroup0_NR};
const LcConfig_UlParamas_t NR_LCSRB3 = {
.priority = 1,
.prioritisedBitRate = NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity,
.logicalChannelGroup = (long *)&logicalChannelGroup0_NR};
// these are the default values for SRB configurations(SRB1 and SRB2) as mentioned in 36.331 pg 258-259
const NR_LogicalChannelConfig_t NR_SRB1_logicalChannelConfig_defaultValue = {.ul_SpecificParameters =
(LcConfig_UlParamas_t *)&NR_LCSRB1};
const NR_LogicalChannelConfig_t NR_SRB2_logicalChannelConfig_defaultValue = {.ul_SpecificParameters =
(LcConfig_UlParamas_t *)&NR_LCSRB2};
const NR_LogicalChannelConfig_t NR_SRB3_logicalChannelConfig_defaultValue = {.ul_SpecificParameters =
(LcConfig_UlParamas_t *)&NR_LCSRB3};
void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table,
int mu, int mu,
NR_TDD_UL_DL_Pattern_t *pattern) NR_TDD_UL_DL_Pattern_t *pattern)
...@@ -511,25 +539,144 @@ void configure_ss_coreset(NR_UE_MAC_INST_t *mac, ...@@ -511,25 +539,144 @@ void configure_ss_coreset(NR_UE_MAC_INST_t *mac,
mac->BWP_coresets[i] = NULL; mac->BWP_coresets[i] = NULL;
} }
static int lcid_cmp(const void *lc1, const void *lc2, void *mac_inst)
{
uint8_t id1 = ((nr_lcordered_info_t *)lc1)->lcids_ordered;
uint8_t id2 = ((nr_lcordered_info_t *)lc2)->lcids_ordered;
NR_UE_MAC_INST_t *mac = (NR_UE_MAC_INST_t *)mac_inst;
NR_LogicalChannelConfig_t **lc_config = &mac->logicalChannelConfig[0];
AssertFatal(id1 > 0 && id2 > 0, "undefined logical channel identity\n");
AssertFatal(lc_config[id1 - 1] != NULL || lc_config[id2 - 1] != NULL, "logical channel configuration should be available\n");
return (lc_config[id1 - 1]->ul_SpecificParameters->priority - lc_config[id2 - 1]->ul_SpecificParameters->priority);
}
void nr_release_mac_config_logicalChannelBearer(module_id_t module_id, long channel_identity)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
if (mac->logicalChannelConfig[channel_identity - 1] != NULL) {
mac->logicalChannelConfig[channel_identity - 1] = NULL;
memset(&mac->scheduling_info.lc_sched_info[channel_identity - 1], 0, sizeof(NR_LC_SCHEDULING_INFO));
} else {
LOG_E(NR_MAC, "Trying to release a non configured logical channel bearer %li\n", channel_identity);
}
}
static uint16_t nr_get_ms_bucketsizeduration(uint8_t bucketsizeduration)
{
switch (bucketsizeduration) {
case NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50:
return 50;
case NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100:
return 100;
case NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms150:
return 150;
case NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms300:
return 300;
case NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms500:
return 500;
case NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000:
return 1000;
default:
return 0;
}
}
void nr_configure_mac_config_logicalChannelBearer(module_id_t module_id,
long channel_identity,
NR_LogicalChannelConfig_t *lc_config)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
LOG_I(NR_MAC, "[MACLogicalChannelConfig]Applying RRC Logical Channel Config %d to lcid %li\n", module_id, channel_identity);
mac->logicalChannelConfig[channel_identity - 1] = lc_config;
// initialize the variable Bj for every LCID
mac->scheduling_info.lc_sched_info[channel_identity - 1].Bj = 0;
// store the bucket size
int pbr = nr_get_pbr(lc_config->ul_SpecificParameters->prioritisedBitRate);
int bsd = nr_get_ms_bucketsizeduration(lc_config->ul_SpecificParameters->bucketSizeDuration);
// in infinite pbr, the bucket is saturated by pbr
if (lc_config->ul_SpecificParameters->prioritisedBitRate
== NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) {
bsd = 1;
}
mac->scheduling_info.lc_sched_info[channel_identity - 1].bucket_size = pbr * bsd;
if (lc_config->ul_SpecificParameters->logicalChannelGroup != NULL)
mac->scheduling_info.lc_sched_info[channel_identity - 1].LCGID = *lc_config->ul_SpecificParameters->logicalChannelGroup;
else
mac->scheduling_info.lc_sched_info[channel_identity - 1].LCGID = 0;
}
void nr_rrc_mac_config_req_ue_logicalChannelBearer(module_id_t module_id, void nr_rrc_mac_config_req_ue_logicalChannelBearer(module_id_t module_id,
struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_toadd_list, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_toadd_list,
struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_torelease_list) struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_torelease_list)
{ {
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
if (rlc_toadd_list) {
for (int i = 0; i < rlc_toadd_list->list.count; i++) {
NR_RLC_BearerConfig_t *rlc_bearer = rlc_toadd_list->list.array[i];
int id = rlc_bearer->logicalChannelIdentity - 1;
mac->active_RLC_bearer[id] = true;
}
}
if (rlc_torelease_list) { if (rlc_torelease_list) {
for (int i = 0; i < rlc_torelease_list->list.count; i++) { for (int i = 0; i < rlc_torelease_list->list.count; i++) {
if (rlc_torelease_list->list.array[i]) { if (rlc_torelease_list->list.array[i]) {
int id = *rlc_torelease_list->list.array[i] - 1; int lc_identity = *rlc_torelease_list->list.array[i];
mac->active_RLC_bearer[id] = false; nr_release_mac_config_logicalChannelBearer(module_id, lc_identity);
}
}
}
if (rlc_toadd_list) {
for (int i = 0; i < rlc_toadd_list->list.count; i++) {
NR_RLC_BearerConfig_t *rlc_bearer = rlc_toadd_list->list.array[i];
int lc_identity = rlc_bearer->logicalChannelIdentity;
mac->lc_ordered_info[i].lcids_ordered = lc_identity;
NR_LogicalChannelConfig_t *mac_lc_config;
if (mac->logicalChannelConfig[lc_identity - 1] == NULL) {
/* setup of new LCID*/
LOG_D(NR_MAC, "Establishing the logical channel %d\n", lc_identity);
AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer should be present for LCID establishment\n");
if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { /* SRB */
NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity;
if (rlc_bearer->mac_LogicalChannelConfig != NULL) {
mac_lc_config = rlc_bearer->mac_LogicalChannelConfig;
} else {
LOG_I(NR_RRC, "Applying the default logicalChannelConfig for SRB\n");
if (srb_id == 1)
mac_lc_config = (NR_LogicalChannelConfig_t *)&NR_SRB1_logicalChannelConfig_defaultValue;
else if (srb_id == 2)
mac_lc_config = (NR_LogicalChannelConfig_t *)&NR_SRB2_logicalChannelConfig_defaultValue;
else if (srb_id == 3)
mac_lc_config = (NR_LogicalChannelConfig_t *)&NR_SRB3_logicalChannelConfig_defaultValue;
else
AssertFatal(1 == 0, "The logical id %d is not a valid SRB id %li\n", lc_identity, srb_id);
}
} else { /* DRB */
mac_lc_config = rlc_bearer->mac_LogicalChannelConfig;
AssertFatal(mac_lc_config != NULL, "For DRB, it should be mandatorily present\n");
}
} else {
/* LC is already established, reconfiguring the LC */
LOG_D(NR_MAC, "Logical channel %d is already established, Reconfiguring now\n", lc_identity);
if (rlc_bearer->mac_LogicalChannelConfig != NULL) {
mac_lc_config = rlc_bearer->mac_LogicalChannelConfig;
} else {
/* Need M - Maintains current value */
continue;
}
} }
mac->lc_ordered_info[i].logicalChannelConfig_ordered = mac_lc_config;
nr_configure_mac_config_logicalChannelBearer(module_id, lc_identity, mac_lc_config);
} }
// reorder the logical channels as per its priority
qsort_r(mac->lc_ordered_info, rlc_toadd_list->list.count, sizeof(nr_lcordered_info_t), lcid_cmp, mac);
} }
} }
......
...@@ -170,24 +170,38 @@ typedef enum { ...@@ -170,24 +170,38 @@ typedef enum {
RA_4STEP RA_4STEP
} nr_ra_type_e; } nr_ra_type_e;
typedef struct {
// after multiplexing buffer remain for each lcid
int32_t LCID_buffer_remain;
// buffer status for each lcid
uint8_t LCID_status;
// Bj bucket usage per lcid
int32_t Bj;
// Bucket size per lcid
int32_t bucket_size;
// logical channel group id for each LCID
uint8_t LCGID;
} NR_LC_SCHEDULING_INFO;
typedef struct {
// buffer status for each lcgid
uint8_t BSR; // should be more for mesh topology
// keep the number of bytes in rlc buffer for each lcgid
int32_t BSR_bytes;
} NR_LCG_SCHEDULING_INFO;
// LTE structure, might need to be adapted for NR // LTE structure, might need to be adapted for NR
typedef struct { typedef struct {
/// buffer status for each lcgid // lcs scheduling info
uint8_t BSR[NR_MAX_NUM_LCGID]; // should be more for mesh topology NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID];
/// keep the number of bytes in rlc buffer for each lcgid // lcg scheduling info
int32_t BSR_bytes[NR_MAX_NUM_LCGID]; NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID];
/// after multiplexing buffer remain for each lcid
int32_t LCID_buffer_remain[NR_MAX_NUM_LCID];
/// sum of all lcid buffer size /// sum of all lcid buffer size
uint16_t All_lcid_buffer_size_lastTTI; uint16_t All_lcid_buffer_size_lastTTI;
/// buffer status for each lcid
uint8_t LCID_status[NR_MAX_NUM_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;
/// logical channel group ide for each LCID
uint8_t LCGID[NR_MAX_NUM_LCID];
/// retxBSR-Timer, default value is sf2560 /// retxBSR-Timer, default value is sf2560
uint16_t retxBSR_Timer; uint16_t retxBSR_Timer;
/// retxBSR_SF, number of subframe before triggering a regular BSR /// retxBSR_SF, number of subframe before triggering a regular BSR
...@@ -225,11 +239,6 @@ typedef struct { ...@@ -225,11 +239,6 @@ typedef struct {
uint16_t extendedBSR_Sizes_r10; uint16_t extendedBSR_Sizes_r10;
/// default value is false /// default value is false
uint16_t extendedPHR_r10; uint16_t extendedPHR_r10;
//Bj bucket usage per lcid
int16_t Bj[NR_MAX_NUM_LCID];
// Bucket size per lcid
int16_t bucket_size[NR_MAX_NUM_LCID];
} NR_UE_SCHEDULING_INFO; } NR_UE_SCHEDULING_INFO;
typedef enum { typedef enum {
...@@ -423,6 +432,14 @@ typedef struct ssb_list_info { ...@@ -423,6 +432,14 @@ typedef struct ssb_list_info {
uint8_t nb_tx_ssb; uint8_t nb_tx_ssb;
} ssb_list_info_t; } ssb_list_info_t;
typedef struct nr_lcordered_info_s {
// logical channels ids ordered as per priority
int lcids_ordered;
// logical channel configurations reordered as per priority
NR_LogicalChannelConfig_t *logicalChannelConfig_ordered;
} nr_lcordered_info_t;
/*!\brief Top level UE MAC structure */ /*!\brief Top level UE MAC structure */
typedef struct { typedef struct {
NR_UE_L2_STATE_t state; NR_UE_L2_STATE_t state;
...@@ -503,8 +520,11 @@ typedef struct { ...@@ -503,8 +520,11 @@ typedef struct {
/// BSR report flag management /// BSR report flag management
uint8_t BSR_reporting_active; uint8_t BSR_reporting_active;
/// LogicalChannelConfig has bearer. // Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive.
bool active_RLC_bearer[NR_MAX_NUM_LCID]; NR_LogicalChannelConfig_t *logicalChannelConfig[NR_MAX_NUM_LCID];
// order lc info
nr_lcordered_info_t lc_ordered_info[NR_MAX_NUM_LCID];
NR_UE_SCHEDULING_INFO scheduling_info; NR_UE_SCHEDULING_INFO scheduling_info;
/// PHR /// PHR
......
...@@ -145,6 +145,13 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t ...@@ -145,6 +145,13 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size, uint8_t nr_locate_BsrIndexByBufferSize(const uint32_t *table, int size,
int value); int value);
/*! \fn int nr_get_pbr(uint8_t 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(uint8_t prioritizedbitrate);
/*! \fn int nr_get_sf_periodicBSRTimer(uint8_t periodicBSR_Timer) /*! \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 \brief get the number of subframe from the periodic BSR timer configured by the higher layers
\param[in] periodicBSR_Timer timer for periodic BSR \param[in] periodicBSR_Timer timer for periodic BSR
......
...@@ -191,17 +191,11 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) ...@@ -191,17 +191,11 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac)
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 LCGID %d\n", i); LOG_D(NR_MAC, "Applying default logical channel config for LCGID %d\n", i);
mac->scheduling_info.Bj[i] = -1; mac->scheduling_info.lc_sched_info[i].Bj = -1;
mac->scheduling_info.bucket_size[i] = -1; mac->scheduling_info.lc_sched_info[i].bucket_size = -1;
mac->scheduling_info.lc_sched_info[i].LCGID = 0; // defaults to 0 irrespective of SRB or DRB
if (i < UL_SCH_LCID_DTCH) { // initialize all control channels lcgid to 0 mac->scheduling_info.lc_sched_info[i].LCID_status = LCID_EMPTY;
mac->scheduling_info.LCGID[i] = 0; mac->scheduling_info.lc_sched_info[i].LCID_buffer_remain = 0;
} else { // initialize all the data channels lcgid to 1
mac->scheduling_info.LCGID[i] = 1;
}
mac->scheduling_info.LCID_status[i] = LCID_EMPTY;
mac->scheduling_info.LCID_buffer_remain[i] = 0;
for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++) for (int k = 0; k < NR_MAX_HARQ_PROCESSES; k++)
mac->first_ul_tx[k] = 1; mac->first_ul_tx[k] = 1;
} }
......
...@@ -1094,6 +1094,31 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info) ...@@ -1094,6 +1094,31 @@ void nr_ue_ul_scheduler(nr_uplink_indication_t *ul_info)
pthread_mutex_unlock(&ul_config->mutex_ul_config); pthread_mutex_unlock(&ul_config->mutex_ul_config);
} }
// 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);
for (nr_lcordered_info_t *lc_bearer = mac->lc_ordered_info; lc_bearer->logicalChannelConfig_ordered != NULL; lc_bearer++) {
int lcid = lc_bearer->lcids_ordered;
NR_LogicalChannelConfig_t *lcconfig = mac->logicalChannelConfig[lcid - 1];
NR_LC_SCHEDULING_INFO *sched_lc = &mac->scheduling_info.lc_sched_info[lcid - 1];
int32_t bucketSize_max =
sched_lc->bucket_size; // max amount of data that can be buffered/accumulated in a logical channel buffer
/*
measure Bj
increment the value of Bj by product PBR * T
*/
int T = 1; // time elapsed since Bj was last incremented
int32_t bj = sched_lc->Bj;
bj += nr_get_pbr(lcconfig->ul_SpecificParameters->prioritisedBitRate) * T;
if (lcconfig->ul_SpecificParameters->prioritisedBitRate
== NR_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity) {
bj = nr_get_pbr(lcconfig->ul_SpecificParameters->prioritisedBitRate);
}
// bj > max bucket size, set bj to max bucket size, as in ts38.321 5.4.3.1 Logical Channel Prioritization
sched_lc->Bj = min(bj, bucketSize_max);
}
// Call BSR procedure as described in Section 5.4.5 in 38.321 // Call BSR procedure as described in Section 5.4.5 in 38.321
// First check ReTxBSR Timer because it is always configured // First check ReTxBSR Timer because it is always configured
...@@ -1146,23 +1171,23 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t ...@@ -1146,23 +1171,23 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) { for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
// Reset transmission status // Reset transmission status
lcid_bytes_in_buffer[lcid - 1] = 0; lcid_bytes_in_buffer[lcid - 1] = 0;
mac->scheduling_info.LCID_status[lcid - 1] = LCID_EMPTY; mac->scheduling_info.lc_sched_info[lcid - 1].LCID_status = LCID_EMPTY;
} }
for (int lcgid = 0; lcgid < NR_MAX_NUM_LCGID; lcgid++) { for (int lcgid = 0; lcgid < NR_MAX_NUM_LCGID; lcgid++) {
// Reset Buffer Info // Reset Buffer Info
mac->scheduling_info.BSR[lcgid] = 0; mac->scheduling_info.lcg_sched_info[lcgid].BSR = 0;
mac->scheduling_info.BSR_bytes[lcgid] = 0; mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes = 0;
} }
//Get Buffer Occupancy and fill lcid_reordered_array //Get Buffer Occupancy and fill lcid_reordered_array
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) { for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
if (mac->active_RLC_bearer[lcid - 1]) { // todo if (mac->logicalChannelConfig[lcid - 1] != NULL) { // todo
int lcgid = mac->scheduling_info.LCGID[lcid - 1]; int lcgid = mac->scheduling_info.lc_sched_info[lcid - 1].LCGID;
// Store already available data to transmit per Group // Store already available data to transmit per Group
if (lcgid < NR_MAX_NUM_LCGID) { if (lcgid < NR_MAX_NUM_LCGID) {
lcgid_buffer_remain[lcgid] += mac->scheduling_info.LCID_buffer_remain[lcid - 1]; 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(module_idP, mac->crnti,gNB_index,frameP,slotP,ENB_FLAG_NO,MBMS_FLAG_NO, lcid, 0, 0); mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(module_idP, mac->crnti,gNB_index,frameP,slotP,ENB_FLAG_NO,MBMS_FLAG_NO, lcid, 0, 0);
...@@ -1172,13 +1197,13 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t ...@@ -1172,13 +1197,13 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
if (rlc_status.bytes_in_buffer > 0) { 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", LOG_D(NR_MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d slot %d\n",
module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,slotP); module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,slotP);
mac->scheduling_info.LCID_status[lcid - 1] = LCID_NOT_EMPTY; mac->scheduling_info.lc_sched_info[lcid - 1].LCID_status = LCID_NOT_EMPTY;
//Update BSR_bytes and position in lcid_reordered_array only if Group is defined //Update BSR_bytes and position in lcid_reordered_array only if Group is defined
if (lcgid < NR_MAX_NUM_LCGID) { if (lcgid < NR_MAX_NUM_LCGID) {
num_lcid_with_data ++; num_lcid_with_data ++;
// sum lcid buffer which has same lcgid // sum lcid buffer which has same lcgid
mac->scheduling_info.BSR_bytes[lcgid] += rlc_status.bytes_in_buffer; mac->scheduling_info.lcg_sched_info[lcgid].BSR_bytes += rlc_status.bytes_in_buffer;
//Fill in the array //Fill in the array
array_index = 0; array_index = 0;
...@@ -1221,7 +1246,7 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t ...@@ -1221,7 +1246,7 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d slot %d\n", "[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d slot %d\n",
module_idP, module_idP,
lcid, lcid,
mac->scheduling_info.LCGID[lcid - 1], mac->scheduling_info.lc_sched_info[lcid - 1].LCGID,
frameP, frameP,
slotP); slotP);
break; break;
...@@ -1241,7 +1266,7 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t ...@@ -1241,7 +1266,7 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t
//Store Buffer Occupancy in remain buffers for next TTI //Store Buffer Occupancy in remain buffers for next TTI
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) { for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) {
mac->scheduling_info.LCID_buffer_remain[lcid - 1] = lcid_bytes_in_buffer[lcid - 1]; mac->scheduling_info.lc_sched_info[lcid - 1].LCID_buffer_remain = lcid_bytes_in_buffer[lcid - 1];
} }
return bsr_regular_triggered; return bsr_regular_triggered;
...@@ -2629,7 +2654,7 @@ int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP, ...@@ -2629,7 +2654,7 @@ int nr_ue_get_sdu_mac_ce_pre(module_id_t module_idP,
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_MAX_NUM_LCGID) {
if (mac->scheduling_info.BSR_bytes[lcg_id]) { if (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes) {
num_lcg_id_with_data++; num_lcg_id_with_data++;
} }
...@@ -2710,11 +2735,17 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP, ...@@ -2710,11 +2735,17 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
int lcg_id_bsr_trunc = 0; int lcg_id_bsr_trunc = 0;
for (lcg_id = 0; lcg_id < NR_MAX_NUM_LCGID; lcg_id++) { for (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.BSR[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE, NR_SHORT_BSR_TABLE_SIZE, mac->scheduling_info.BSR_bytes[lcg_id]); mac->scheduling_info.lcg_sched_info[lcg_id].BSR =
nr_locate_BsrIndexByBufferSize(NR_SHORT_BSR_TABLE,
NR_SHORT_BSR_TABLE_SIZE,
mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes);
} else { } else {
mac->scheduling_info.BSR[lcg_id] = nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE, NR_LONG_BSR_TABLE_SIZE, mac->scheduling_info.BSR_bytes[lcg_id]); mac->scheduling_info.lcg_sched_info[lcg_id].BSR =
nr_locate_BsrIndexByBufferSize(NR_LONG_BSR_TABLE,
NR_LONG_BSR_TABLE_SIZE,
mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes);
} }
if (mac->scheduling_info.BSR_bytes[lcg_id]) { if (mac->scheduling_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;
} }
...@@ -2748,8 +2779,8 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP, ...@@ -2748,8 +2779,8 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
// 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.LCGID[lcid - 1]; lcg_id = mac->scheduling_info.lc_sched_info[lcid - 1].LCGID;
if ((lcg_id < NR_MAX_NUM_LCGID) && (mac->scheduling_info.BSR_bytes[lcg_id])) { if ((lcg_id < NR_MAX_NUM_LCGID) && (mac->scheduling_info.lcg_sched_info[lcg_id].BSR_bytes)) {
lcg_id_bsr_trunc = lcg_id; lcg_id_bsr_trunc = lcg_id;
} }
} }
...@@ -2775,25 +2806,29 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP, ...@@ -2775,25 +2806,29 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
} 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.BSR[0]; mac_ce_p->bsr_l->Buffer_size0 = mac->scheduling_info.lcg_sched_info[0].BSR;
mac_ce_p->bsr_l->Buffer_size1 = mac->scheduling_info.BSR[1]; mac_ce_p->bsr_l->Buffer_size1 = mac->scheduling_info.lcg_sched_info[1].BSR;
mac_ce_p->bsr_l->Buffer_size2 = mac->scheduling_info.BSR[2]; mac_ce_p->bsr_l->Buffer_size2 = mac->scheduling_info.lcg_sched_info[2].BSR;
mac_ce_p->bsr_l->Buffer_size3 = mac->scheduling_info.BSR[3]; mac_ce_p->bsr_l->Buffer_size3 = mac->scheduling_info.lcg_sched_info[3].BSR;
mac_ce_p->bsr_l->Buffer_size4 = mac->scheduling_info.BSR[4]; mac_ce_p->bsr_l->Buffer_size4 = mac->scheduling_info.lcg_sched_info[4].BSR;
mac_ce_p->bsr_l->Buffer_size5 = mac->scheduling_info.BSR[5]; mac_ce_p->bsr_l->Buffer_size5 = mac->scheduling_info.lcg_sched_info[5].BSR;
mac_ce_p->bsr_l->Buffer_size6 = mac->scheduling_info.BSR[6]; mac_ce_p->bsr_l->Buffer_size6 = mac->scheduling_info.lcg_sched_info[6].BSR;
mac_ce_p->bsr_l->Buffer_size7 = mac->scheduling_info.BSR[7]; mac_ce_p->bsr_l->Buffer_size7 = mac->scheduling_info.lcg_sched_info[7].BSR;
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 %d level LCGID4 %d,level LCGID5 %d,level LCGID6 %d,level LCGID7 %d)\n", LOG_D(NR_MAC,
module_idP, frameP, subframe, "[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",
module_idP,
frameP,
subframe,
mac->BSR_reporting_active, mac->BSR_reporting_active,
mac->scheduling_info.BSR[0], mac->scheduling_info.lcg_sched_info[0].BSR,
mac->scheduling_info.BSR[1], mac->scheduling_info.lcg_sched_info[1].BSR,
mac->scheduling_info.BSR[2], mac->scheduling_info.lcg_sched_info[2].BSR,
mac->scheduling_info.BSR[3], mac->scheduling_info.lcg_sched_info[3].BSR,
mac->scheduling_info.BSR[4], mac->scheduling_info.lcg_sched_info[4].BSR,
mac->scheduling_info.BSR[5], mac->scheduling_info.lcg_sched_info[5].BSR,
mac->scheduling_info.BSR[6], mac->scheduling_info.lcg_sched_info[6].BSR,
mac->scheduling_info.BSR[7]); mac->scheduling_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;
...@@ -2801,19 +2836,27 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP, ...@@ -2801,19 +2836,27 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
//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.BSR[lcg_id_bsr_trunc]; mac_ce_p->bsr_t->Buffer_size = mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR;
LOG_D(NR_MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", LOG_D(NR_MAC,
module_idP, frameP, subframe, "[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
module_idP,
frameP,
subframe,
mac->BSR_reporting_active, mac->BSR_reporting_active,
mac->scheduling_info.BSR[lcg_id_bsr_trunc], lcg_id_bsr_trunc); mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR,
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.BSR[lcg_id_bsr_trunc]; mac_ce_p->bsr_s->Buffer_size = mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR;
LOG_D(NR_MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", LOG_D(NR_MAC,
module_idP, frameP, subframe, "[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
module_idP,
frameP,
subframe,
mac->BSR_reporting_active, mac->BSR_reporting_active,
mac->scheduling_info.BSR[lcg_id_bsr_trunc], lcg_id_bsr_trunc); mac->scheduling_info.lcg_sched_info[lcg_id_bsr_trunc].BSR,
lcg_id_bsr_trunc);
} }
} }
...@@ -2842,6 +2885,237 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP, ...@@ -2842,6 +2885,237 @@ void nr_ue_get_sdu_mac_ce_post(module_id_t module_idP,
} }
} }
uint32_t get_count_lcids_same_priority(NR_UE_MAC_INST_t *mac, uint8_t start, uint8_t total_active_lcids, int *lcid_ordered_array)
{
// count number of logical channels with same priority as curr_lcid
uint8_t same_priority_count = 0;
uint8_t curr_lcid = lcid_ordered_array[start];
NR_LogicalChannelConfig_t *lc_config_curr = mac->logicalChannelConfig[curr_lcid - 1];
for (uint8_t index = start; index < total_active_lcids; index++) {
uint8_t next_lcid = lcid_ordered_array[index];
NR_LogicalChannelConfig_t *lc_config_next = mac->logicalChannelConfig[next_lcid - 1];
if (lc_config_curr->ul_SpecificParameters->priority == lc_config_next->ul_SpecificParameters->priority) {
same_priority_count++;
}
}
LOG_D(NR_MAC, "Number of lcids with same priority as that of lcid %d is %d\n", curr_lcid, same_priority_count);
return same_priority_count;
}
long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
uint8_t same_priority_count,
uint8_t lc_num,
uint16_t buflen_remain_ep,
int16_t buflen_remain,
uint8_t round_id,
uint32_t *bytes_read_fromlc,
long *target)
{
/* Calculates the number of bytes the logical channel should request from the correcponding RLC buffer*/
NR_LogicalChannelConfig_t *lc_config = mac->logicalChannelConfig[lc_num - 1];
long pbr = nr_get_pbr(lc_config->ul_SpecificParameters->prioritisedBitRate);
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;
long num_remaining_bytes = 0;
long num_bytes_requested = 0;
if (round_id == 0) { // initial round
uint16_t pdu_remain = (same_priority_count > 1) ? buflen_remain_ep : buflen_remain;
num_bytes_requested = (pdu_remain < pbr) ? min(pdu_remain, lcid_remain_buffer) : min(pbr, lcid_remain_buffer);
num_remaining_bytes = *target - bytes_read_fromlc[lc_num - 1];
num_bytes_requested = min(num_bytes_requested, num_remaining_bytes);
} else { // from first round
if (same_priority_count > 1) {
num_bytes_requested = min(buflen_remain_ep, lcid_remain_buffer);
num_remaining_bytes = buflen_remain_ep - bytes_read_fromlc[lc_num - 1];
num_bytes_requested = min(num_bytes_requested, num_remaining_bytes);
} else {
num_bytes_requested = min(buflen_remain, lcid_remain_buffer);
}
}
AssertFatal(num_remaining_bytes >= 0, "the total number of bytes allocated until target length is greater than expected\n");
LOG_D(NR_MAC, "number of bytes requested for lcid %d is %li\n", lc_num, num_bytes_requested);
return num_bytes_requested;
}
bool get_dataavailability_buffers(uint8_t total_active_lcids, int *lcid_ordered_array, bool *data_status_lcbuffers)
{
// check whether there is any data in the rlc buffer corresponding to active lcs
for (uint8_t id = 0; id < total_active_lcids; id++) {
int lcid = lcid_ordered_array[id];
if (data_status_lcbuffers[lcid - 1]) {
return true;
}
}
return false;
}
uint8_t select_logical_channels(NR_UE_MAC_INST_t *mac, uint8_t *num_active_lcids, int *active_lcids)
{
// (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical
// channels, TS38.321)
// selection of logical channels with Bj > 0
for (nr_lcordered_info_t *lc_bearer = mac->lc_ordered_info; lc_bearer->logicalChannelConfig_ordered != NULL; lc_bearer++) {
uint8_t lcid = lc_bearer->lcids_ordered;
if (mac->scheduling_info.lc_sched_info[lcid - 1].Bj > 0) {
active_lcids[*num_active_lcids] = lcid;
(*num_active_lcids)++;
LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, *num_active_lcids);
}
}
return 0;
}
static bool fill_mac_sdu(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframe,
uint8_t gNB_index,
uint16_t buflen,
int16_t *buflen_remain,
int lcid,
uint8_t **pdu,
uint32_t *counter,
uint8_t count_same_priority_lcids,
uint16_t buflen_ep,
uint32_t *lcids_bytes_tot,
uint16_t *num_sdus,
NR_UE_MAC_CE_INFO *mac_ce_p,
bool *lcids_data_status,
uint8_t *num_lcids_same_priority)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
NR_UE_SCHEDULING_INFO *sched_info = &mac->scheduling_info;
const uint8_t sh_size = sizeof(NR_MAC_SUBHEADER_LONG);
/* prepare the MAC sdu */
int32_t lcid_remain_buffer = sched_info->lc_sched_info[lcid - 1].LCID_buffer_remain;
LOG_D(NR_MAC,
"In %s: [UE %d] [%d.%d] lcp round = %d, remaining mac pdu length = %d, lcid buffer remaining = %d, lcid = %d \n",
__FUNCTION__,
module_idP,
frameP,
subframe,
*counter,
*buflen_remain,
lcid_remain_buffer,
lcid);
// Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *)(*pdu);
*pdu += sh_size;
// number of bytes requested from RLC for each LCID
long target = 0;
long bytes_requested =
get_num_bytes_to_reqlc(mac, count_same_priority_lcids, lcid, buflen_ep, *buflen_remain, *counter, lcids_bytes_tot, &target);
uint16_t sdu_length = mac_rlc_data_req(module_idP,
mac->crnti,
gNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
bytes_requested,
(char *)(*pdu),
0,
0);
AssertFatal(bytes_requested >= sdu_length,
"In %s: LCID = 0x%02x RLC has segmented %d bytes but MAC has max %li remaining bytes\n",
__FUNCTION__,
lcid,
sdu_length,
bytes_requested);
// Decrement Bj by the total size of MAC SDUs(RLC PDU) served to logical channel
// 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
// 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;
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",
lcid,
sdu_length,
lcid,
sched_info->lc_sched_info[lcid - 1].Bj);
if (sdu_length > 0) {
LOG_D(NR_MAC,
"In %s: [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",
__FUNCTION__,
module_idP,
frameP,
subframe,
(*num_sdus) + 1,
sdu_length,
lcid,
buflen);
header->R = 0;
header->F = 1;
header->LCID = lcid;
header->L = htons(sdu_length);
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: dumping MAC sub-header with length %d: \n", __FUNCTION__, sh_size);
log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n");
LOG_I(NR_MAC, "In %s: dumping MAC SDU with length %d \n", __FUNCTION__, sdu_length);
log_dump(NR_MAC, *pdu, sdu_length, LOG_DUMP_CHAR, "\n");
#endif
*pdu += sdu_length;
mac_ce_p->sdu_length_total += sdu_length;
mac_ce_p->total_mac_pdu_header_len += sh_size;
(*num_sdus)++;
} else {
*pdu -= sh_size;
lcids_data_status[lcid - 1] = false;
(*num_lcids_same_priority)--;
LOG_D(NR_MAC, "In %s: no data to transmit for RB with LCID 0x%02x\n and hence set to false", __FUNCTION__, lcid);
return 0;
}
*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
NR_LC_SCHEDULING_INFO *lc_info = &sched_info->lc_sched_info[0] + lcid - 1;
NR_LCG_SCHEDULING_INFO *lcg_info = &sched_info->lcg_sched_info[0];
lc_info->LCID_buffer_remain -= sdu_length;
(lcg_info + lc_info->LCGID)->BSR_bytes -= sdu_length;
LOG_D(NR_MAC,
"[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%d = %d\n",
module_idP,
frameP,
subframe,
lc_info->LCGID,
(lcg_info + lc_info->LCGID)->BSR_bytes);
if ((lcg_info + lc_info->LCGID)->BSR_bytes < 0)
(lcg_info + lc_info->LCGID)->BSR_bytes = 0;
// 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);
if ((*counter == 0 && lcids_bytes_tot[lcid - 1] >= target)
|| (count_same_priority_lcids > 1
&& lcids_bytes_tot[lcid - 1] >= buflen_ep)) { // only prioritized bit rate should be taken from logical channel in
// the first lcp run except when infinity
LOG_D(NR_MAC,
"In %s: total number bytes read from rlc buffer for lcid %d are %d\n",
__FUNCTION__,
lcid,
lcids_bytes_tot[lcid - 1]);
(*num_lcids_same_priority)--;
return 0;
}
return 1;
}
/** /**
* Function: to fetch data to be transmitted from RLC, place it in the ULSCH PDU buffer * Function: to fetch data to be transmitted from RLC, place it in the ULSCH PDU buffer
to generate the complete MAC PDU with sub-headers and MAC CEs according to ULSCH MAC PDU generation (6.1.2 TS 38.321) to generate the complete MAC PDU with sub-headers and MAC CEs according to ULSCH MAC PDU generation (6.1.2 TS 38.321)
...@@ -2872,7 +3146,6 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP, ...@@ -2872,7 +3146,6 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
//mac_ce_p->phr_ce_len = 0; //mac_ce_p->phr_ce_len = 0;
//mac_ce_p->phr_header_len = 0; //mac_ce_p->phr_header_len = 0;
uint16_t sdu_length = 0;
uint16_t num_sdus = 0; uint16_t num_sdus = 0;
mac_ce_p->sdu_length_total = 0; mac_ce_p->sdu_length_total = 0;
NR_BSR_SHORT bsr_short, bsr_truncated; NR_BSR_SHORT bsr_short, bsr_truncated;
...@@ -2883,113 +3156,120 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP, ...@@ -2883,113 +3156,120 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
//NR_POWER_HEADROOM_CMD phr; //NR_POWER_HEADROOM_CMD phr;
//mac_ce_p->phr_p = &phr; //mac_ce_p->phr_p = &phr;
NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
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);
// Pointer used to build the MAC PDU by placing the RLC SDUs in the ULSCH buffer // Pointer used to build the MAC PDU by placing the RLC SDUs in the ULSCH buffer
uint8_t *pdu = ulsch_buffer; uint8_t *pdu = ulsch_buffer;
//nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length // variable used to build the lcids with positive Bj
mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(module_idP, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p); int lcids_bj_pos[NR_MAX_NUM_LCID] = {0};
mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len; uint8_t avail_lcids_count = 0;
LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", __FUNCTION__, module_idP, frameP, subframe, buflen); // variable used to store the lcid data status during lcp
bool lcids_data_status[NR_MAX_NUM_LCID] = {0};
memset(lcids_data_status, 1, NR_MAX_NUM_LCID);
// Check for DCCH first uint32_t lcp_allocation_counter =
// TO DO: Multiplex in the order defined by the logical channel prioritization 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
for (int lcid = 1; lcid <= NR_MAX_NUM_LCID; lcid++) { // bj and prioritized bit rate but just consider priority
if (!mac->active_RLC_bearer[lcid - 1]) uint16_t buflen_ep = 0; // this variable holds the length in bytes in mac pdu when multiple equal priority channels are present
continue; // because as per standard(TS38.321), all equal priority channels should be served equally
buflen_remain = buflen - (mac_ce_p->total_mac_pdu_header_len + mac_ce_p->sdu_length_total + sh_size);
LOG_D(NR_MAC, // nr_ue_get_sdu_mac_ce_pre updates all mac_ce related header field related to length
"[UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header len %d " mac_ce_p->tot_mac_ce_len = nr_ue_get_sdu_mac_ce_pre(module_idP, CC_id, frameP, subframe, gNB_index, ulsch_buffer, buflen, mac_ce_p);
"bytes, buflen_remain %d bytes)\n", mac_ce_p->total_mac_pdu_header_len = mac_ce_p->tot_mac_ce_len;
module_idP,
frameP,
subframe,
lcid,
buflen,
mac_ce_p->sdu_length_total,
mac_ce_p->tot_mac_ce_len,
buflen_remain);
while (buflen_remain > 0) {
// Pointer used to build the MAC sub-PDU headers in the ULSCH buffer for each SDU
NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) pdu;
pdu += sh_size;
sdu_length = mac_rlc_data_req(module_idP,
mac->crnti,
gNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
buflen_remain,
(char *)pdu,
0,
0);
AssertFatal(buflen_remain >= sdu_length,
"LCID = 0x%02x RLC has segmented %d bytes but MAC has max %d remaining bytes\n",
lcid,
sdu_length,
buflen_remain);
if (sdu_length > 0) {
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 0x%02x "
"(buflen (TBS) %d bytes)\n",
module_idP,
frameP,
subframe,
num_sdus + 1,
sdu_length,
lcid,
buflen);
header->R = 0;
header->F = 1;
header->LCID = lcid;
header->L = htons(sdu_length);
#ifdef ENABLE_MAC_PAYLOAD_DEBUG
LOG_I(NR_MAC, "In %s: dumping MAC sub-header with length %d: \n", __FUNCTION__, sh_size);
log_dump(NR_MAC, header, sh_size, LOG_DUMP_CHAR, "\n");
LOG_I(NR_MAC, "In %s: dumping MAC SDU with length %d \n", __FUNCTION__, sdu_length);
log_dump(NR_MAC, pdu, sdu_length, LOG_DUMP_CHAR, "\n");
#endif
pdu += sdu_length; LOG_D(NR_MAC, "In %s: [UE %d] [%d.%d] process UL transport block at with size TBS = %d bytes \n", __FUNCTION__, module_idP, frameP, subframe, buflen);
mac_ce_p->sdu_length_total += sdu_length;
mac_ce_p->total_mac_pdu_header_len += sh_size;
num_sdus++; // selection of logical channels
select_logical_channels(mac, &avail_lcids_count, lcids_bj_pos);
// multiplex in the order of highest priority
do {
/*
go until there is space availabile in the MAC PDU and there is data available in RLC buffers of active logical channels
*/
uint8_t num_lcids_same_priority = 0;
uint8_t count_same_priority_lcids = 0;
// variable used to store the total bytes read from rlc for each lcid
uint32_t lcids_bytes_tot[NR_MAX_NUM_LCID] = {0};
for (uint8_t id = 0; id < avail_lcids_count; id++) {
/*
loop over all logical channels in the order of priority. As stated in TS138.321 Section 5.4.3.1, in the first run, only
prioritized number of bytes are taken out from the corresponding RLC buffers of all active logical channels and if there is
still space availble in the MAC PDU, then from the next run all the remaining data from the higher priority logical channel
is placed in the MAC PDU before going on to next high priority logical channel
*/
int lcid = lcids_bj_pos[id];
// 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
if (!sched_info->lc_sched_info[lcid - 1].LCID_status || !lcids_data_status[lcid - 1]) {
lcids_data_status[lcid - 1] = false;
continue;
}
} else { // count number of lc with same priority as lcid
pdu -= sh_size; if (!num_lcids_same_priority) {
LOG_D(NR_MAC, "no data to transmit for RB with LCID 0x%02x\n", lcid); num_lcids_same_priority = count_same_priority_lcids =
break; get_count_lcids_same_priority(mac, id, avail_lcids_count, lcids_bj_pos);
} }
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
mac->scheduling_info.LCID_buffer_remain[lcid - 1] -= sdu_length;
mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid - 1]] -= sdu_length;
LOG_D(NR_MAC, LOG_D(NR_MAC,
"[UE %d] Update BSR [%d.%d] BSR_bytes for LCG%d=%d\n", "In %s: [UE %d] [%d.%d] UL-DXCH -> ULSCH, RLC with LCID 0x%02x (TBS %d bytes, sdu_length_total %d bytes, MAC header "
"len %d bytes,"
"buflen_remain %d bytes)\n",
__FUNCTION__,
module_idP, module_idP,
frameP, frameP,
subframe, subframe,
mac->scheduling_info.LCGID[lcid - 1], lcid,
mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid - 1]]); buflen,
if (mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid - 1]] < 0) mac_ce_p->sdu_length_total,
mac->scheduling_info.BSR_bytes[mac->scheduling_info.LCGID[lcid - 1]] = 0; mac_ce_p->tot_mac_ce_len,
buflen_remain);
if (num_lcids_same_priority == count_same_priority_lcids) {
buflen_ep = (buflen_remain - (count_same_priority_lcids * sh_size)) / count_same_priority_lcids;
}
while (buflen_remain > 0) {
/*
loops until the requested number of bytes from MAC to RLC are placed in the MAC PDU. The number of requested bytes
depends on whether it is the first run or otherwise because in the first run only prioritited number of bytes of all
active logical channels in the order of priority are placed in the MAC PDU. The 'get_num_bytes_to_reqlc' calculates
the target number of bytes to request from RLC via 'mac_rlc_data_req'
*/
if (!fill_mac_sdu(module_idP,
frameP,
subframe,
gNB_index,
buflen,
&buflen_remain,
lcid,
&pdu,
&lcp_allocation_counter,
count_same_priority_lcids,
buflen_ep,
lcids_bytes_tot,
&num_sdus,
mac_ce_p,
lcids_data_status,
&num_lcids_same_priority)) {
break;
}
}
} }
}
lcp_allocation_counter++;
} while (buflen_remain > 0 && get_dataavailability_buffers(avail_lcids_count, lcids_bj_pos, lcids_data_status));
//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.
...@@ -3058,3 +3338,80 @@ void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIG ...@@ -3058,3 +3338,80 @@ void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIG
dl_config->number_pdus += 1; dl_config->number_pdus += 1;
ul_time_alignment->ta_apply = false; ul_time_alignment->ta_apply = false;
} }
uint32_t nr_get_pbr(uint8_t 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;
}
...@@ -460,8 +460,10 @@ void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, ...@@ -460,8 +460,10 @@ void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig,
{ {
ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig, *rbconfig); ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig, *rbconfig);
*rbconfig = NULL; *rbconfig = NULL;
ASN_STRUCT_FREE(asn_DEF_NR_RLC_BearerConfig, *rlc_rbconfig); if (rlc_rbconfig != NULL) {
*rlc_rbconfig = NULL; ASN_STRUCT_FREE(asn_DEF_NR_RLC_BearerConfig, *rlc_rbconfig);
*rlc_rbconfig = NULL;
}
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
......
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