Commit daa1b689 authored by Sakthivel Velumani's avatar Sakthivel Velumani

Add slice support to scheduler

Loop over active slices per UE and allocate RBs based on slice policy
parent 0f574c35
......@@ -43,6 +43,7 @@
#define NR_NB_REG_PER_CCE 6
#define NR_NB_SC_PER_RB 12
#define NR_MAX_NUM_LCID 32
#define NR_MAX_NUM_SLICES 8
typedef enum {
nr_FR1 = 0,
......
......@@ -316,52 +316,128 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
return offset;
}
static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot)
static int get_slice_index(module_id_t module_id, nssai_t nssai)
{
NR_slice_sched_t *sliceConfig = RC.nrmac[module_id]->sliceConfig;
for (int i = 0; i < NR_MAX_NUM_SLICES; i++) {
if (sliceConfig[i].nssai.sd == nssai.sd && sliceConfig[i].nssai.sst == nssai.sst)
return i;
}
return -1;
}
static int find_slice_in_ue(module_id_t module_id, const NR_UE_slice_info_t *sliceInfoUE, int num_slice, nssai_t nssai)
{
NR_slice_sched_t *sliceConfig = RC.nrmac[module_id]->sliceConfig;
for (int i = 0; i < num_slice; i++) {
if (sliceConfig[sliceInfoUE[i].sliceIdx].nssai.sd == nssai.sd && sliceConfig[sliceInfoUE[i].sliceIdx].nssai.sst == nssai.sd)
return i;
}
return -1;
}
/* Temporary function. To be removed */
static void set_slice_config_temp(module_id_t module_id, int bwpSize)
{
NR_slice_sched_t *sliceConfig = RC.nrmac[module_id]->sliceConfig;
for (int i = 0; i < 2; i++) {
sliceConfig[i].numDedicatedPrbs = ((float)10 / 100) * bwpSize;
sliceConfig[i].numPrioritizedPrbs = ((float)10 / 100) * bwpSize;
sliceConfig[i].numSharedPrbs = ((float)30 / 100) * bwpSize;
sliceConfig[i].nssai.sd = 0xffffff;
sliceConfig[i].nssai.sst = 1;
}
for (int i = 2; i < NR_MAX_NUM_SLICES; i++) {
sliceConfig[i].nssai.sd = -1;
sliceConfig[i].nssai.sst = -1;
}
}
/* Prepare a list of active slices for each UE
Used by the scheduler to allocate resources */
static void nr_set_ue_slices(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->num_total_bytes = 0;
sched_ctrl->dl_pdus_total = 0;
memset(sched_ctrl->sliceInfo, 0, sizeof(sched_ctrl->sliceInfo));
sched_ctrl->numSlices = 0;
bool defaultSliceSet = false;
/* loop over all activated logical channels */
// Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
const int lcid = sched_ctrl->dl_lc[i].id;
const uint16_t rnti = UE->rnti;
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
continue;
}
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
rnti,
module_id,
frame,
slot,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0,
0);
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
continue;
sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
LOG_D(MAC,
"[gNB %d][%4d.%2d] %s%d->DLSCH, RLC status for UE %d: %d bytes in buffer, total DL buffer size = %d bytes, %d total PDU bytes, %s TA command\n",
module_id,
frame,
slot,
lcid < 4 ? "DCCH":"DTCH",
lcid,
UE->rnti,
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
sched_ctrl->num_total_bytes,
sched_ctrl->dl_pdus_total,
sched_ctrl->ta_apply ? "send":"do not send");
if (lcid < 3) { /* SRBs are on default slice */
NR_UE_slice_info_t *slInfo = &sched_ctrl->sliceInfo[0];
slInfo->lcid[slInfo->numLcids] = lcid;
slInfo->numLcids++;
if (!defaultSliceSet) {
slInfo->sliceIdx = 0;
sched_ctrl->numSlices++;
defaultSliceSet = true;
}
} else {
int ueSliceIdx = find_slice_in_ue(module_id, sched_ctrl->sliceInfo, sched_ctrl->numSlices, sched_ctrl->dl_lc[i].nssai);
if (ueSliceIdx < 0) { /* Slice not in UE's list */
int configSliceIdx = get_slice_index(module_id, sched_ctrl->dl_lc[i].nssai);
AssertFatal(configSliceIdx > -1, "Error in getting stored slice index from MAC structure.\n");
NR_UE_slice_info_t *slInfo = sched_ctrl->sliceInfo + sched_ctrl->numSlices;
slInfo->lcid[slInfo->numLcids++] = lcid;
/* add slice to UE's list */
sched_ctrl->numSlices++;
slInfo->sliceIdx = configSliceIdx;
} else { /* Slice exists in UE's list */
NR_UE_slice_info_t *slInfo = sched_ctrl->sliceInfo + ueSliceIdx;
slInfo->lcid[slInfo->numLcids++] = lcid;
}
}
}
}
}
static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
UE_iterator(RC.nrmac[module_id]->UE_info.list, UE)
{
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
for (NR_UE_slice_info_t *sl = sched_ctrl->sliceInfo; sl < sched_ctrl->sliceInfo + sched_ctrl->numSlices; sl++) {
sl->num_total_bytes = 0;
sl->dl_pdus_total = 0;
for (int i = 0; i < sl->numLcids; i++) {
const int lcid = sl->lcid[i];
const uint16_t rnti = UE->rnti;
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
sched_ctrl->rlc_status[lcid] =
mac_rlc_status_ind(module_id, rnti, module_id, frame, slot, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0, 0);
stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
continue;
sl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
sl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
LOG_D(MAC,
"[gNB %d][%4d.%2d] %s%d->DLSCH, RLC status for UE %d: %d bytes in buffer, total DL buffer size = %d bytes, %d total "
"PDU bytes, %s TA command\n",
module_id,
frame,
slot,
lcid < 4 ? "DCCH" : "DTCH",
lcid,
UE->rnti,
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
sl->num_total_bytes,
sl->dl_pdus_total,
sched_ctrl->ta_apply ? "send" : "do not send");
}
}
}
}
......@@ -649,7 +725,11 @@ static void pf_dl(module_id_t module_id,
}
/* Check DL buffer and skip this UE if no bytes and no TA necessary */
if (sched_ctrl->num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024)
int num_total_bytes = 0;
for (int i = 0; i < sched_ctrl->numSlices; i++) {
num_total_bytes += sched_ctrl->sliceInfo[i].num_total_bytes;
}
if (num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024)
continue;
/* Calculate coeff */
......@@ -763,52 +843,72 @@ static void pf_dl(module_id_t module_id,
const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
int rbStop = 0;
int rbStart = 0;
get_start_stop_allocation(mac, iterator->UE, &rbStart, &rbStop);
// Freq-demain allocation
while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap) != slbitmap)
rbStart++;
const int lastSchedSliceIdx = sched_ctrl->curSchedSliceIdx;
for (int i = 0; i < sched_ctrl->numSlices; i++) {
NR_UE_slice_info_t *sl = &sched_ctrl->sliceInfo[i];
NR_slice_sched_t *slConfig = &mac->sliceConfig[sl->sliceIdx];
/* Schedule the next slice for fairness. Still not optimal for more than 2 slices */
if (lastSchedSliceIdx == i && sched_ctrl->numSlices > 1)
continue;
const int max_avail_rb_slice = slConfig->numDedicatedPrbs + slConfig->numPrioritizedPrbs + slConfig->numSharedPrbs;
int rem_rbs = max_avail_rb_slice;
int rbStop = 0;
int rbStart = 0;
get_start_stop_allocation(mac, iterator->UE, &rbStart, &rbStop);
// Freq-demain allocation
while (rbStart < rbStop && (rballoc_mask[rbStart] & slbitmap) != slbitmap)
rbStart++;
uint16_t max_rbSize = 1;
while (rbStart + max_rbSize < rbStop && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap)
max_rbSize++;
sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc,
dl_bwp,
tda_info,
sched_pdsch->nrOfLayers);
sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
sched_pdsch->pucch_allocation = alloc;
uint32_t TBS = 0;
uint16_t rbSize;
// Fix me: currently, the RLC does not give us the total number of PDUs
// awaiting. Therefore, for the time being, we put a fixed overhead of 12
// (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of
// PDUs, we replace with 3 * numPDUs
const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
//const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
nr_find_nb_rb(sched_pdsch->Qm,
sched_pdsch->R,
1, // no transform precoding for DL
sched_pdsch->nrOfLayers,
tda_info->nrOfSymbols,
sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
sched_ctrl->num_total_bytes + oh,
min_rbSize,
max_rbSize,
&TBS,
&rbSize);
sched_pdsch->rbSize = rbSize;
sched_pdsch->rbStart = rbStart;
sched_pdsch->tb_size = TBS;
/* transmissions: directly allocate */
n_rb_sched -= sched_pdsch->rbSize;
for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
rballoc_mask[rb + sched_pdsch->rbStart] ^= slbitmap;
uint16_t max_rbSize = 1;
while (rbStart + max_rbSize < rbStop && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap && max_rbSize < rem_rbs)
max_rbSize++;
sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, tda_info, sched_pdsch->nrOfLayers);
sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
sched_pdsch->pucch_allocation = alloc;
uint32_t TBS = 0;
uint16_t rbSize;
// Fix me: currently, the RLC does not give us the total number of PDUs
// awaiting. Therefore, for the time being, we put a fixed overhead of 12
// (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of
// PDUs, we replace with 3 * numPDUs
const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
// const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
nr_find_nb_rb(sched_pdsch->Qm,
sched_pdsch->R,
1, // no transform precoding for DL
sched_pdsch->nrOfLayers,
tda_info->nrOfSymbols,
sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
sl->num_total_bytes + oh,
min_rbSize,
max_rbSize,
&TBS,
&rbSize);
sched_pdsch->rbSize = rbSize;
sched_pdsch->rbStart = rbStart;
sched_pdsch->tb_size = TBS;
rem_rbs -= sched_pdsch->rbSize;
/* transmissions: directly allocate */
n_rb_sched -= sched_pdsch->rbSize;
LOG_D(NR_MAC,
"Slice idx: %d\nDedicated RBs: %d\nPrioritized RBs: %d\nShared RBs: %d\nSum: %d\nAllocated: %d\n",
i,
slConfig->numDedicatedPrbs,
slConfig->numPrioritizedPrbs,
slConfig->numSharedPrbs,
max_avail_rb_slice,
max_avail_rb_slice - rem_rbs);
for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
rballoc_mask[rb + sched_pdsch->rbStart] ^= slbitmap;
/* Can scheduler only one slice per slot per UE */
sched_ctrl->curSchedSliceIdx = i;
break;
}
remainUEs--;
iterator++;
......@@ -856,6 +956,12 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_
}
}
/* temp hardcoding */
set_slice_config_temp(module_id, bwpSize);
/* Prepare list of slices for UEs */
nr_set_ue_slices(module_id, frame, slot);
/* Retrieve amount of data to send for this UE */
nr_store_dlsch_buffer(module_id, frame, slot);
......@@ -1244,10 +1350,10 @@ void nr_schedule_ue_spec(module_id_t module_id,
start_meas(&gNB_mac->rlc_data_req);
int sdus = 0;
if (sched_ctrl->num_total_bytes > 0) {
/* loop over all activated logical channels */
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
const int lcid = sched_ctrl->dl_lc[i].id;
if (sched_ctrl->sliceInfo[sched_ctrl->curSchedSliceIdx].num_total_bytes > 0) {
/* loop over all activated logical channels in current slice */
for (int i = 0; i < sched_ctrl->sliceInfo[sched_ctrl->curSchedSliceIdx].numLcids; ++i) {
const int lcid = sched_ctrl->sliceInfo[sched_ctrl->curSchedSliceIdx].lcid[i];
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
continue; // no data for this LC tbs_size_t len = 0;
......
......@@ -96,7 +96,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
rbStart += rbSize;
}
sched_ctrl->num_total_bytes = 0;
sched_ctrl->sliceInfo[0].num_total_bytes = 0;
sched_ctrl->dl_lc_num = 1;
const int lcid = DL_SCH_LCID_DTCH;
sched_ctrl->dl_lc[sched_ctrl->dl_lc_num - 1].id = lcid;
......@@ -113,7 +113,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
lcid,
0,
0);
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
sched_ctrl->sliceInfo[0].num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
int CCEIndex = get_cce_index(RC.nrmac[module_id],
CC_id, slot, UE->rnti,
......
......@@ -232,13 +232,24 @@ static NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *o
return cloned;
}
static int get_idx_from_lcid(const NR_UE_sched_ctrl_t *sched_ctrl, int lcid)
{
for (int i = 0; i < sched_ctrl->dl_lc_num; i++) {
if (sched_ctrl->dl_lc[i].id == lcid)
return i;
}
return -1;
}
static void set_nssaiConfig(const int drb_len, const f1ap_drb_to_be_setup_t *req_drbs, NR_UE_sched_ctrl_t *sched_ctrl)
{
for (int i = 0; i < drb_len; i++) {
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
long lcid = get_lcid_from_drbid(drb->drb_id);
sched_ctrl->dl_lc[lcid].nssai = drb->nssai;
int lcid_idx = get_idx_from_lcid(sched_ctrl, lcid);
DevAssert(lcid_idx > -1);
sched_ctrl->dl_lc[lcid_idx].nssai = drb->nssai;
LOG_I(NR_MAC, "Setting NSSAI sst: %d, sd: %d for DRB: %ld\n", drb->nssai.sst, drb->nssai.sd, drb->drb_id);
}
}
......
......@@ -541,6 +541,25 @@ typedef struct {
nssai_t nssai;
} NR_LC_info_t;
/*! \brief Slice information used by the scheduler */
typedef struct {
int numSharedPrbs;
int numPrioritizedPrbs;
int numDedicatedPrbs;
nssai_t nssai;
} NR_slice_sched_t;
typedef struct {
/// the index of slice from slice config stored in gNB_MAC_INST
int sliceIdx;
/// LCs in this slice
uint8_t numLcids;
uint8_t lcid[NR_MAX_NUM_LCID];
/// total amount of data awaiting for this UE for each slice
uint32_t num_total_bytes;
uint16_t dl_pdus_total;
} NR_UE_slice_info_t;
/*! \brief scheduling control information set through an API */
#define MAX_CSI_REPORTS 48
typedef struct {
......@@ -585,12 +604,16 @@ typedef struct {
frame_t last_ul_frame;
sub_frame_t last_ul_slot;
/// total amount of data awaiting for this UE
uint32_t num_total_bytes;
uint16_t dl_pdus_total;
/// UE slice specific info
int numSlices;
int curSchedSliceIdx;
NR_UE_slice_info_t sliceInfo[NR_MAX_NUM_SLICES];
/// per-LC status data
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID];
uint32_t num_total_bytes;
uint16_t dl_pdus_total;
/// Estimation of HARQ from BLER
NR_bler_stats_t dl_bler_stats;
NR_bler_stats_t ul_bler_stats;
......@@ -852,6 +875,9 @@ typedef struct gNB_MAC_INST_s {
pthread_mutex_t sched_lock;
/// store slice config. First slice is always default slice
NR_slice_sched_t sliceConfig[NR_MAX_NUM_SLICES];
} gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */
......
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