Commit 43036eb8 authored by sriharsha's avatar sriharsha Committed by Sriharsha Korada

Add implementation of logical channel prioritization at UE

- Reorder the logical channels based on priority
- Handling of configuration and release of logical channel bearer
- Add changes in the implementation of lcp procedure for equal priority logical channels
- Restructure the lcp parameters as a separate structure
- Further code clean up
parent 0accb601
...@@ -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,24 +539,105 @@ void configure_ss_coreset(NR_UE_MAC_INST_t *mac, ...@@ -511,24 +539,105 @@ 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 *lcid1, const void *lcid2, void *mac_inst)
{
uint8_t id1 = *(uint8_t *)lcid1;
uint8_t id2 = *(uint8_t *)lcid2;
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);
}
}
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.lcids_ordered[i] = lc_identity;
NR_LogicalChannelConfig_t *mac_lc_config;
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");
} }
nr_configure_mac_config_logicalChannelBearer(module_id, lc_identity, mac_lc_config);
}
// reorder the logical channels as per its priority
qsort_r((void *)mac->lc_ordered_info.lcids_ordered, rlc_toadd_list->list.count, sizeof(uint32_t), lcid_cmp, (void *)mac);
for (uint8_t i = 0; i < rlc_toadd_list->list.count; i++) {
mac->lc_ordered_info.logicalChannelConfig_ordered[i] = mac->logicalChannelConfig[mac->lc_ordered_info.lcids_ordered[i] - 1];
} }
} }
} }
......
...@@ -171,24 +171,38 @@ typedef enum { ...@@ -171,24 +171,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
...@@ -226,11 +240,6 @@ typedef struct { ...@@ -226,11 +240,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 {
...@@ -424,6 +433,14 @@ typedef struct ssb_list_info { ...@@ -424,6 +433,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[NR_MAX_NUM_LCID];
// logical channel configurations reordered as per priority
NR_LogicalChannelConfig_t *logicalChannelConfig_ordered[NR_MAX_NUM_LCID];
} 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;
...@@ -508,8 +525,11 @@ typedef struct { ...@@ -508,8 +525,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_UE_SCHEDULING_INFO scheduling_info; NR_UE_SCHEDULING_INFO scheduling_info;
/// PHR /// PHR
......
...@@ -148,6 +148,20 @@ bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t ...@@ -148,6 +148,20 @@ 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_ms_bucketsizeduration(uint8_t bucketSizeduration)
\brief get the time in ms from the bucket size duration configured by the higher layer
\param[in] bucketSize the bucket size duration
\return the time in ms
*/
uint16_t nr_get_ms_bucketsizeduration(uint8_t bucketsizeduration);
/*! \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
......
...@@ -188,17 +188,11 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) ...@@ -188,17 +188,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;
} }
......
This diff is collapsed.
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