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 @@ ...@@ -43,6 +43,7 @@
#define NR_NB_REG_PER_CCE 6 #define NR_NB_REG_PER_CCE 6
#define NR_NB_SC_PER_RB 12 #define NR_NB_SC_PER_RB 12
#define NR_MAX_NUM_LCID 32 #define NR_MAX_NUM_LCID 32
#define NR_MAX_NUM_SLICES 8
typedef enum { typedef enum {
nr_FR1 = 0, nr_FR1 = 0,
......
...@@ -316,52 +316,128 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, ...@@ -316,52 +316,128 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
return offset; 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) { UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; 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 */ /* loop over all activated logical channels */
// Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH // Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) {
const int lcid = sched_ctrl->dl_lc[i].id; 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) { if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
continue; continue;
} }
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); start_meas(&RC.nrmac[module_id]->rlc_status_ind);
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id, sched_ctrl->rlc_status[lcid] =
rnti, mac_rlc_status_ind(module_id, rnti, module_id, frame, slot, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0, 0);
module_id,
frame,
slot,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0,
0);
stop_meas(&RC.nrmac[module_id]->rlc_status_ind); stop_meas(&RC.nrmac[module_id]->rlc_status_ind);
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
continue; continue;
sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer; sl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; sl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
LOG_D(MAC, 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", "[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, module_id,
frame, frame,
slot, slot,
lcid < 4 ? "DCCH":"DTCH", lcid < 4 ? "DCCH" : "DTCH",
lcid, lcid,
UE->rnti, UE->rnti,
sched_ctrl->rlc_status[lcid].bytes_in_buffer, sched_ctrl->rlc_status[lcid].bytes_in_buffer,
sched_ctrl->num_total_bytes, sl->num_total_bytes,
sched_ctrl->dl_pdus_total, sl->dl_pdus_total,
sched_ctrl->ta_apply ? "send":"do not send"); sched_ctrl->ta_apply ? "send" : "do not send");
}
} }
} }
} }
...@@ -649,7 +725,11 @@ static void pf_dl(module_id_t module_id, ...@@ -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 */ /* 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; continue;
/* Calculate coeff */ /* Calculate coeff */
...@@ -763,6 +843,15 @@ static void pf_dl(module_id_t module_id, ...@@ -763,6 +843,15 @@ static void pf_dl(module_id_t module_id,
const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
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 rbStop = 0;
int rbStart = 0; int rbStart = 0;
get_start_stop_allocation(mac, iterator->UE, &rbStart, &rbStop); get_start_stop_allocation(mac, iterator->UE, &rbStart, &rbStop);
...@@ -772,13 +861,10 @@ static void pf_dl(module_id_t module_id, ...@@ -772,13 +861,10 @@ static void pf_dl(module_id_t module_id,
uint16_t max_rbSize = 1; uint16_t max_rbSize = 1;
while (rbStart + max_rbSize < rbStop && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap) while (rbStart + max_rbSize < rbStop && (rballoc_mask[rbStart + max_rbSize] & slbitmap) == slbitmap && max_rbSize < rem_rbs)
max_rbSize++; max_rbSize++;
sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, tda_info, sched_pdsch->nrOfLayers);
dl_bwp,
tda_info,
sched_pdsch->nrOfLayers);
sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx); 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->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
sched_pdsch->pucch_allocation = alloc; sched_pdsch->pucch_allocation = alloc;
...@@ -789,14 +875,14 @@ static void pf_dl(module_id_t module_id, ...@@ -789,14 +875,14 @@ static void pf_dl(module_id_t module_id,
// (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of // (for 4 PDUs) and optionally + 2 for TA. Once RLC gives the number of
// PDUs, we replace with 3 * numPDUs // PDUs, we replace with 3 * numPDUs
const int oh = 3 * 4 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024); 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); // const int oh = 3 * sched_ctrl->dl_pdus_total + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
nr_find_nb_rb(sched_pdsch->Qm, nr_find_nb_rb(sched_pdsch->Qm,
sched_pdsch->R, sched_pdsch->R,
1, // no transform precoding for DL 1, // no transform precoding for DL
sched_pdsch->nrOfLayers, sched_pdsch->nrOfLayers,
tda_info->nrOfSymbols, tda_info->nrOfSymbols,
sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT, sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
sched_ctrl->num_total_bytes + oh, sl->num_total_bytes + oh,
min_rbSize, min_rbSize,
max_rbSize, max_rbSize,
&TBS, &TBS,
...@@ -804,12 +890,26 @@ static void pf_dl(module_id_t module_id, ...@@ -804,12 +890,26 @@ static void pf_dl(module_id_t module_id,
sched_pdsch->rbSize = rbSize; sched_pdsch->rbSize = rbSize;
sched_pdsch->rbStart = rbStart; sched_pdsch->rbStart = rbStart;
sched_pdsch->tb_size = TBS; sched_pdsch->tb_size = TBS;
rem_rbs -= sched_pdsch->rbSize;
/* transmissions: directly allocate */ /* transmissions: directly allocate */
n_rb_sched -= sched_pdsch->rbSize; 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++) for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
rballoc_mask[rb + sched_pdsch->rbStart] ^= slbitmap; rballoc_mask[rb + sched_pdsch->rbStart] ^= slbitmap;
/* Can scheduler only one slice per slot per UE */
sched_ctrl->curSchedSliceIdx = i;
break;
}
remainUEs--; remainUEs--;
iterator++; iterator++;
} }
...@@ -856,6 +956,12 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_ ...@@ -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 */ /* Retrieve amount of data to send for this UE */
nr_store_dlsch_buffer(module_id, frame, slot); nr_store_dlsch_buffer(module_id, frame, slot);
...@@ -1244,10 +1350,10 @@ void nr_schedule_ue_spec(module_id_t module_id, ...@@ -1244,10 +1350,10 @@ void nr_schedule_ue_spec(module_id_t module_id,
start_meas(&gNB_mac->rlc_data_req); start_meas(&gNB_mac->rlc_data_req);
int sdus = 0; int sdus = 0;
if (sched_ctrl->num_total_bytes > 0) { if (sched_ctrl->sliceInfo[sched_ctrl->curSchedSliceIdx].num_total_bytes > 0) {
/* loop over all activated logical channels */ /* loop over all activated logical channels in current slice */
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { for (int i = 0; i < sched_ctrl->sliceInfo[sched_ctrl->curSchedSliceIdx].numLcids; ++i) {
const int lcid = sched_ctrl->dl_lc[i].id; const int lcid = sched_ctrl->sliceInfo[sched_ctrl->curSchedSliceIdx].lcid[i];
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
continue; // no data for this LC tbs_size_t len = 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, ...@@ -96,7 +96,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
rbStart += rbSize; rbStart += rbSize;
} }
sched_ctrl->num_total_bytes = 0; sched_ctrl->sliceInfo[0].num_total_bytes = 0;
sched_ctrl->dl_lc_num = 1; sched_ctrl->dl_lc_num = 1;
const int lcid = DL_SCH_LCID_DTCH; const int lcid = DL_SCH_LCID_DTCH;
sched_ctrl->dl_lc[sched_ctrl->dl_lc_num - 1].id = lcid; 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, ...@@ -113,7 +113,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
lcid, lcid,
0, 0,
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], int CCEIndex = get_cce_index(RC.nrmac[module_id],
CC_id, slot, UE->rnti, CC_id, slot, UE->rnti,
......
...@@ -232,13 +232,24 @@ static NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *o ...@@ -232,13 +232,24 @@ static NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *o
return cloned; 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) 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++) { for (int i = 0; i < drb_len; i++) {
const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; const f1ap_drb_to_be_setup_t *drb = &req_drbs[i];
long lcid = get_lcid_from_drbid(drb->drb_id); 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); 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 { ...@@ -541,6 +541,25 @@ typedef struct {
nssai_t nssai; nssai_t nssai;
} NR_LC_info_t; } 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 */ /*! \brief scheduling control information set through an API */
#define MAX_CSI_REPORTS 48 #define MAX_CSI_REPORTS 48
typedef struct { typedef struct {
...@@ -585,12 +604,16 @@ typedef struct { ...@@ -585,12 +604,16 @@ typedef struct {
frame_t last_ul_frame; frame_t last_ul_frame;
sub_frame_t last_ul_slot; sub_frame_t last_ul_slot;
/// total amount of data awaiting for this UE /// UE slice specific info
uint32_t num_total_bytes; int numSlices;
uint16_t dl_pdus_total; int curSchedSliceIdx;
NR_UE_slice_info_t sliceInfo[NR_MAX_NUM_SLICES];
/// per-LC status data /// per-LC status data
mac_rlc_status_resp_t rlc_status[NR_MAX_NUM_LCID]; 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 /// Estimation of HARQ from BLER
NR_bler_stats_t dl_bler_stats; NR_bler_stats_t dl_bler_stats;
NR_bler_stats_t ul_bler_stats; NR_bler_stats_t ul_bler_stats;
...@@ -852,6 +875,9 @@ typedef struct gNB_MAC_INST_s { ...@@ -852,6 +875,9 @@ typedef struct gNB_MAC_INST_s {
pthread_mutex_t sched_lock; 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; } gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */ #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