Commit 3317f276 authored by Sakthivel Velumani's avatar Sakthivel Velumani Committed by Chieh-Chun Chen

Add support for multiple slices per UE

parent bdaff4aa
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#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_QFI 64 #define NR_MAX_NUM_QFI 64
#define NR_MAX_NUM_SLICES 10
#define RNTI_NAMES /* see 38.321 Table 7.1-2 RNTI usage */ \ #define RNTI_NAMES /* see 38.321 Table 7.1-2 RNTI usage */ \
R(TYPE_C_RNTI_) /* Cell RNTI */ \ R(TYPE_C_RNTI_) /* Cell RNTI */ \
R(TYPE_CS_RNTI_) /* Configured Scheduling RNTI */ \ R(TYPE_CS_RNTI_) /* Configured Scheduling RNTI */ \
......
...@@ -317,12 +317,15 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, ...@@ -317,12 +317,15 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
return offset; return offset;
} }
void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot) 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) { 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; /* add all LCID to fist slice. This is to have a common post-processor function for both slicing and non-slicing scheduler */
sched_ctrl->dl_pdus_total = 0; sched_ctrl->last_sched_slice = 0;
sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].num_total_bytes = 0;
sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].dl_pdus_total = 0;
reset_nr_list(&sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].lcid);
/* 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
...@@ -349,20 +352,22 @@ void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slo ...@@ -349,20 +352,22 @@ void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slo
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; sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
add_nr_list(&sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].lcid, lcid);
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, sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].num_total_bytes,
sched_ctrl->dl_pdus_total, sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].dl_pdus_total,
sched_ctrl->ta_apply ? "send":"do not send"); sched_ctrl->ta_apply ? "send" : "do not send");
} }
} }
} }
...@@ -673,7 +678,7 @@ static int nr_pf_dl(module_id_t module_id, ...@@ -673,7 +678,7 @@ static int nr_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) if (sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].num_total_bytes == 0 && frame != (sched_ctrl->ta_frame + 10) % 1024)
continue; continue;
/* Calculate coeff */ /* Calculate coeff */
...@@ -826,7 +831,7 @@ static int nr_pf_dl(module_id_t module_id, ...@@ -826,7 +831,7 @@ static int nr_pf_dl(module_id_t module_id,
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, sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].num_total_bytes + oh,
min_rbSize, min_rbSize,
max_rbSize, max_rbSize,
&TBS, &TBS,
...@@ -1288,10 +1293,11 @@ void nr_schedule_ue_spec(module_id_t module_id, ...@@ -1288,10 +1293,11 @@ 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->last_sched_slice].num_total_bytes > 0) {
/* loop over all activated logical channels */ /* loop over all activated logical channels in this slice */
for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { NR_List_Iterator(&sched_ctrl->sliceInfo[sched_ctrl->last_sched_slice].lcid, lcidP)
const int lcid = sched_ctrl->dl_lc_ids[i]; {
const int lcid = *lcidP;
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;
...@@ -1343,6 +1349,7 @@ void nr_schedule_ue_spec(module_id_t module_id, ...@@ -1343,6 +1349,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes; UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes;
} }
sched_ctrl->harq_slice_map[sched_ctrl->sched_pdsch.dl_harq_pid] = sched_ctrl->last_sched_slice;
} else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) {
/* we will need the large header, phy-test typically allocates all /* we will need the large header, phy-test typically allocates all
* resources and fills to the last byte below */ * resources and fills to the last byte below */
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#define DEBUG_gNB_SCHEDULER 1 #define DEBUG_gNB_SCHEDULER 1
#include "common/ran_context.h" #include "common/ran_context.h"
#include "NR_MAC_gNB/slicing/nr_slicing.h"
//#define DEBUG_DCI //#define DEBUG_DCI
...@@ -1842,6 +1843,30 @@ void create_nr_list(NR_list_t *list, int len) ...@@ -1842,6 +1843,30 @@ void create_nr_list(NR_list_t *list, int len)
list->len = len; list->len = len;
} }
/*
* Reset NR_list
*/
void reset_nr_list(NR_list_t *list)
{
list->head = -1;
memset(list->next, -1, list->len);
list->tail = -1;
}
/*
* Check if id is in the list
*/
bool check_nr_list(const NR_list_t *listP, int id)
{
const int *cur = &listP->head;
while (*cur >= 0) {
if (*cur == id)
return true;
cur = &listP->next[*cur];
}
return false;
}
/* /*
* Resize an NR_list * Resize an NR_list
*/ */
...@@ -2018,6 +2043,10 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca ...@@ -2018,6 +2043,10 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca
destroy_nr_list(&sched_ctrl->retrans_ul_harq); destroy_nr_list(&sched_ctrl->retrans_ul_harq);
free_sched_pucch_list(sched_ctrl); free_sched_pucch_list(sched_ctrl);
uid_linear_allocator_free(uia, UE->uid); uid_linear_allocator_free(uia, UE->uid);
for (int slice = 0; slice < NR_MAX_NUM_SLICES; slice++) {
destroy_nr_list(&sched_ctrl->sliceInfo[slice].lcid);
}
destroy_nr_list(&UE->dl_id);
LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti); LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti);
free(UE); free(UE);
} }
...@@ -2430,6 +2459,12 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf ...@@ -2430,6 +2459,12 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
reset_srs_stats(UE); reset_srs_stats(UE);
/* prepare LC list for all slices in this UE */
for (int slice = 0; slice < NR_MAX_NUM_SLICES; slice++) {
create_nr_list(&sched_ctrl->sliceInfo[slice].lcid, NR_MAX_NUM_LCID);
}
create_nr_list(&UE->dl_id, NR_MAX_NUM_SLICES);
// associate UEs to the first slice if slice exists (there is no DRB setup in this stage) // associate UEs to the first slice if slice exists (there is no DRB setup in this stage)
nr_pp_impl_param_dl_t *dl = &RC.nrmac[0]->pre_processor_dl; nr_pp_impl_param_dl_t *dl = &RC.nrmac[0]->pre_processor_dl;
if (dl->slices) if (dl->slices)
...@@ -2573,6 +2608,14 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) ...@@ -2573,6 +2608,14 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti)
return; return;
} }
/* Dissociate UE from all corresponding slice*/
nr_pp_impl_param_dl_t *dl = &nr_mac->pre_processor_dl;
if (dl->slices) {
for (int i = 0; i < dl->slices->num; i++) {
dl->remove_UE(dl->slices, UE, i);
}
}
NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0}; NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0};
int newListIdx=0; int newListIdx=0;
for (int i=0; i<MAX_MOBILES_PER_GNB; i++) for (int i=0; i<MAX_MOBILES_PER_GNB; i++)
...@@ -3044,6 +3087,17 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) ...@@ -3044,6 +3087,17 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
UE->CellGroup = cellGroupConfig; UE->CellGroup = cellGroupConfig;
process_CellGroup(cellGroupConfig, UE); process_CellGroup(cellGroupConfig, UE);
/* Assign SRB1 to default slice */
const long lcid = 1;
nr_pp_impl_param_dl_t *dl = &mac->pre_processor_dl;
if (dl->slices) {
nssai_t *default_nssai = &dl->slices->s[0]->nssai;
UE->UE_sched_ctrl.dl_lc_nssai[lcid] = *default_nssai;
LOG_I(NR_MAC, "Setting NSSAI sst: %d, sd: %d for SRB: %ld\n", default_nssai->sst, default_nssai->sd, lcid);
dl->add_UE(dl->slices, UE);
}
/* activate SRB0 */ /* activate SRB0 */
nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message); nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message);
......
...@@ -298,6 +298,8 @@ void remove_nr_list(NR_list_t *listP, int id); ...@@ -298,6 +298,8 @@ void remove_nr_list(NR_list_t *listP, int id);
void add_tail_nr_list(NR_list_t *listP, int id); void add_tail_nr_list(NR_list_t *listP, int id);
void add_front_nr_list(NR_list_t *listP, int id); void add_front_nr_list(NR_list_t *listP, int id);
void remove_front_nr_list(NR_list_t *listP); void remove_front_nr_list(NR_list_t *listP);
void reset_nr_list(NR_list_t *listP);
bool check_nr_list(const NR_list_t *listP, int id);
NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP); NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "openair2/F1AP/f1ap_ids.h" #include "openair2/F1AP/f1ap_ids.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "F1AP_CauseRadioNetwork.h" #include "F1AP_CauseRadioNetwork.h"
#include "NR_MAC_gNB/slicing/nr_slicing.h"
#include "uper_decoder.h" #include "uper_decoder.h"
#include "uper_encoder.h" #include "uper_encoder.h"
...@@ -237,8 +238,25 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig) ...@@ -237,8 +238,25 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
return cloned; return cloned;
} }
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 srb_len,
const f1ap_srb_to_be_setup_t *req_srbs,
const int drb_len,
const f1ap_drb_to_be_setup_t *req_drbs,
NR_UE_sched_ctrl_t *sched_ctrl)
{ {
gNB_MAC_INST *mac = RC.nrmac[0];
for (int i = 0; i < srb_len; i++) {
const f1ap_srb_to_be_setup_t *srb = &req_srbs[i];
const long lcid = get_lcid_from_srbid(srb->srb_id);
/* consider first slice as default slice and assign it for SRBs */
nr_pp_impl_param_dl_t *dl = &mac->pre_processor_dl;
if (dl->slices) {
nssai_t *default_nssai = &dl->slices->s[0]->nssai;
sched_ctrl->dl_lc_nssai[lcid] = *default_nssai;
LOG_I(NR_MAC, "Setting NSSAI sst: %d, sd: %d for SRB: %ld\n", default_nssai->sst, default_nssai->sd, srb->srb_id);
}
}
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];
...@@ -358,8 +376,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) ...@@ -358,8 +376,16 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
set_QoSConfig(req, &UE->UE_sched_ctrl); set_QoSConfig(req, &UE->UE_sched_ctrl);
/* Set NSSAI config in MAC for each active DRB */ /* Set NSSAI config in MAC for each active DRB */
set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); set_nssaiConfig(req->srbs_to_be_setup_length,
req->srbs_to_be_setup,
req->drbs_to_be_setup_length,
req->drbs_to_be_setup,
&UE->UE_sched_ctrl);
/* Associate UE to the corresponding slice*/
nr_pp_impl_param_dl_t *dl = &mac->pre_processor_dl;
if (dl->slices)
dl->add_UE(dl->slices, UE);
NR_SCHED_UNLOCK(&mac->sched_lock); NR_SCHED_UNLOCK(&mac->sched_lock);
/* some sanity checks, since we use the same type for request and response */ /* some sanity checks, since we use the same type for request and response */
...@@ -461,7 +487,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) ...@@ -461,7 +487,11 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
set_QoSConfig(req, &UE->UE_sched_ctrl); set_QoSConfig(req, &UE->UE_sched_ctrl);
/* Set NSSAI config in MAC for each active DRB */ /* Set NSSAI config in MAC for each active DRB */
set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); set_nssaiConfig(req->srbs_to_be_setup_length,
req->srbs_to_be_setup,
req->drbs_to_be_setup_length,
req->drbs_to_be_setup,
&UE->UE_sched_ctrl);
/* Associate UE to the corresponding slice*/ /* Associate UE to the corresponding slice*/
nr_pp_impl_param_dl_t *dl = &mac->pre_processor_dl; nr_pp_impl_param_dl_t *dl = &mac->pre_processor_dl;
......
...@@ -111,6 +111,8 @@ typedef struct { ...@@ -111,6 +111,8 @@ typedef struct {
int len; int len;
} NR_list_t; } NR_list_t;
#define NR_List_Iterator(BaSe, CuR) for (int *CuR = &(BaSe)->head, *nxt = (BaSe)->next; *CuR >= 0; CuR = &nxt[*CuR])
typedef enum { typedef enum {
RA_IDLE = 0, RA_IDLE = 0,
Msg2 = 1, Msg2 = 1,
...@@ -543,6 +545,14 @@ typedef struct NR_QoS_config_s { ...@@ -543,6 +545,14 @@ typedef struct NR_QoS_config_s {
uint64_t priority; uint64_t priority;
} NR_QoS_config_t; } NR_QoS_config_t;
typedef struct {
/// LCs in this slice
NR_list_t lcid;
/// total amount of data awaiting for this UE
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 {
...@@ -643,6 +653,13 @@ typedef struct { ...@@ -643,6 +653,13 @@ typedef struct {
nr_srs_feedback_t srs_feedback; nr_srs_feedback_t srs_feedback;
nssai_t dl_lc_nssai[NR_MAX_NUM_LCID]; nssai_t dl_lc_nssai[NR_MAX_NUM_LCID];
/// last scheduled slice index
int last_sched_slice;
/// hold information of slices
NR_UE_slice_info_t sliceInfo[NR_MAX_NUM_SLICES];
/// DL harq to slice map
int harq_slice_map[NR_MAX_HARQ_PROCESSES];
// Information about the QoS configuration for each LCID/DRB // Information about the QoS configuration for each LCID/DRB
NR_QoS_config_t qos_config[NR_MAX_NUM_LCID - 4][NR_MAX_NUM_QFI]; // 0 -CCCH and 1- 3 SRBs(0,1,2) NR_QoS_config_t qos_config[NR_MAX_NUM_LCID - 4][NR_MAX_NUM_QFI]; // 0 -CCCH and 1- 3 SRBs(0,1,2)
} NR_UE_sched_ctrl_t; } NR_UE_sched_ctrl_t;
...@@ -717,7 +734,7 @@ typedef struct { ...@@ -717,7 +734,7 @@ typedef struct {
float dl_thr_ue; float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook; long pdsch_HARQ_ACK_Codebook;
/// Assoc slice /// Assoc slice
slice_id_t dl_id; NR_list_t dl_id;
} NR_UE_info_t; } NR_UE_info_t;
typedef struct { typedef struct {
......
...@@ -92,36 +92,36 @@ void nr_slicing_add_UE(nr_slice_info_t *si, NR_UE_info_t *new_ue) ...@@ -92,36 +92,36 @@ void nr_slicing_add_UE(nr_slice_info_t *si, NR_UE_info_t *new_ue)
{ {
AssertFatal(si->num > 0 && si->s != NULL, "no slices exists, cannot add UEs\n"); AssertFatal(si->num > 0 && si->s != NULL, "no slices exists, cannot add UEs\n");
NR_UE_sched_ctrl_t *sched_ctrl = &new_ue->UE_sched_ctrl; NR_UE_sched_ctrl_t *sched_ctrl = &new_ue->UE_sched_ctrl;
bool matched_ue = 0;
long lcid = 0; long lcid = 0;
int slice_idx = 0; reset_nr_list(&new_ue->dl_id);
for (int i = 0; i < si->num; ++i) { for (int i = 0; i < si->num; ++i) {
reset_nr_list(&new_ue->UE_sched_ctrl.sliceInfo[i].lcid);
bool matched_ue = false;
for (int l = 0; l < sched_ctrl->dl_lc_num; ++l) { for (int l = 0; l < sched_ctrl->dl_lc_num; ++l) {
lcid = sched_ctrl->dl_lc_ids[l]; lcid = sched_ctrl->dl_lc_ids[l];
LOG_D(NR_MAC, "l %d, lcid %ld, sst %d, sd %d\n", l, lcid, sched_ctrl->dl_lc_nssai[lcid].sst, sched_ctrl->dl_lc_nssai[lcid].sd); LOG_D(NR_MAC, "l %d, lcid %ld, sst %d, sd %d\n", l, lcid, sched_ctrl->dl_lc_nssai[lcid].sst, sched_ctrl->dl_lc_nssai[lcid].sd);
if (nssai_matches(sched_ctrl->dl_lc_nssai[lcid], si->s[i]->nssai.sst, &si->s[i]->nssai.sd)) { if (nssai_matches(sched_ctrl->dl_lc_nssai[lcid], si->s[i]->nssai.sst, &si->s[i]->nssai.sd)) {
matched_ue = 1; // assume UE only associates to one slice add_nr_list(&new_ue->UE_sched_ctrl.sliceInfo[i].lcid, lcid);
break; matched_ue = true;
} }
} }
if (matched_ue) { if (matched_ue) {
slice_idx = i; add_nr_list(&new_ue->dl_id, si->s[i]->id);
break; int num_UEs = si->s[i]->num_UEs;
} else { if (si->s[i]->UE_list[num_UEs] == NULL) {
LOG_W(NR_MAC, "cannot find lcid for UE rnti 0x%04x, associate UE at the first slice\n", new_ue->rnti); si->s[i]->UE_list[num_UEs] = new_ue;
si->s[i]->num_UEs += 1;
} else {
LOG_E(NR_MAC, "cannot add new UE rnti 0x%04x to slice idx %d, num_UEs %d\n", new_ue->rnti, i, si->s[i]->num_UEs);
}
LOG_W(NR_MAC,
"Add UE rnti 0x%04x to slice idx %d, sst %d, sd %d\n",
new_ue->rnti,
i,
si->s[i]->nssai.sst,
si->s[i]->nssai.sd);
} }
} }
new_ue->dl_id = si->s[slice_idx]->id;
int num_UEs = si->s[slice_idx]->num_UEs;
if (si->s[slice_idx]->UE_list[num_UEs] == NULL) {
si->s[slice_idx]->UE_list[num_UEs] = new_ue;
si->s[slice_idx]->num_UEs += 1;
} else {
LOG_E(NR_MAC, "cannot add new UE rnti 0x%04x to slice idx %d, num_UEs %d\n", new_ue->rnti, slice_idx, si->s[slice_idx]->num_UEs);
}
LOG_W(NR_MAC, "Add UE rnti 0x%04x to slice idx %d, sst %d, sd %d\n", new_ue->rnti, slice_idx, si->s[slice_idx]->nssai.sst, si->s[slice_idx]->nssai.sd);
} }
void nr_slicing_remove_UE(nr_slice_info_t *si, NR_UE_info_t* rm_ue, int idx) void nr_slicing_remove_UE(nr_slice_info_t *si, NR_UE_info_t* rm_ue, int idx)
...@@ -131,7 +131,7 @@ void nr_slicing_remove_UE(nr_slice_info_t *si, NR_UE_info_t* rm_ue, int idx) ...@@ -131,7 +131,7 @@ void nr_slicing_remove_UE(nr_slice_info_t *si, NR_UE_info_t* rm_ue, int idx)
if (si->s[idx]->UE_list[i]->rnti == rm_ue->rnti) { if (si->s[idx]->UE_list[i]->rnti == rm_ue->rnti) {
si->s[idx]->UE_list[i] = NULL; si->s[idx]->UE_list[i] = NULL;
si->s[idx]->num_UEs -= 1; si->s[idx]->num_UEs -= 1;
rm_ue->dl_id = -1; remove_nr_list(&rm_ue->dl_id, si->s[idx]->id);
break; break;
} }
} }
...@@ -144,7 +144,8 @@ void nr_slicing_move_UE(nr_slice_info_t *si, NR_UE_info_t* assoc_ue, int old_idx ...@@ -144,7 +144,8 @@ void nr_slicing_move_UE(nr_slice_info_t *si, NR_UE_info_t* assoc_ue, int old_idx
DevAssert(old_idx >= -1 && old_idx < si->num); DevAssert(old_idx >= -1 && old_idx < si->num);
// add UE to new slice // add UE to new slice
assoc_ue->dl_id = si->s[new_idx]->id; remove_nr_list(&assoc_ue->dl_id, si->s[old_idx]->id);
add_nr_list(&assoc_ue->dl_id, si->s[new_idx]->id);
int cur_idx = si->s[new_idx]->num_UEs; int cur_idx = si->s[new_idx]->num_UEs;
si->s[new_idx]->UE_list[cur_idx] = assoc_ue; si->s[new_idx]->UE_list[cur_idx] = assoc_ue;
si->s[new_idx]->num_UEs += 1; si->s[new_idx]->num_UEs += 1;
...@@ -339,7 +340,7 @@ int remove_nvs_nr_slice_dl(nr_slice_info_t *si, uint8_t slice_idx) ...@@ -339,7 +340,7 @@ int remove_nvs_nr_slice_dl(nr_slice_info_t *si, uint8_t slice_idx)
return 0; return 0;
UE_iterator(si->s[slice_idx]->UE_list, rm_ue) { UE_iterator(si->s[slice_idx]->UE_list, rm_ue) {
nr_slicing_remove_UE(si, rm_ue, slice_idx); nr_slicing_remove_UE(si, rm_ue, slice_idx);
rm_ue->dl_id = si->s[0]->id; remove_nr_list(&rm_ue->dl_id, si->s[slice_idx]->id);
LOG_D(NR_MAC, "%s(), move UE rnti 0x%04x in slice ID %d idx %d to slice ID %d idx %d\n", LOG_D(NR_MAC, "%s(), move UE rnti 0x%04x in slice ID %d idx %d to slice ID %d idx %d\n",
__func__, rm_ue->rnti, si->s[slice_idx]->id, slice_idx, si->s[0]->id, 0); __func__, rm_ue->rnti, si->s[slice_idx]->id, slice_idx, si->s[0]->id, 0);
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) { for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
...@@ -360,7 +361,50 @@ int remove_nvs_nr_slice_dl(nr_slice_info_t *si, uint8_t slice_idx) ...@@ -360,7 +361,50 @@ int remove_nvs_nr_slice_dl(nr_slice_info_t *si, uint8_t slice_idx)
return 1; return 1;
} }
extern void nr_store_dlsch_buffer(module_id_t, frame_t, sub_frame_t); static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot)
{
nr_slice_info_t *si = RC.nrmac[module_id]->pre_processor_dl.slices;
for (int s = 0; s < si->num; s++) {
UE_iterator (si->s[s]->UE_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->sliceInfo[s].num_total_bytes = 0;
sched_ctrl->sliceInfo[s].dl_pdus_total = 0;
NR_List_Iterator(&UE->UE_sched_ctrl.sliceInfo[s].lcid, lcidP)
{
const int lcid = *lcidP;
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->sliceInfo[s].dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer;
sched_ctrl->sliceInfo[s].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, slice %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,
s,
sched_ctrl->rlc_status[lcid].bytes_in_buffer,
sched_ctrl->sliceInfo[s].num_total_bytes,
sched_ctrl->sliceInfo[s].dl_pdus_total,
sched_ctrl->ta_apply ? "send" : "do not send");
}
}
}
}
void nvs_nr_dl(module_id_t mod_id, void nvs_nr_dl(module_id_t mod_id,
frame_t frame, frame_t frame,
...@@ -416,16 +460,15 @@ void nvs_nr_dl(module_id_t mod_id, ...@@ -416,16 +460,15 @@ void nvs_nr_dl(module_id_t mod_id,
nr_slice_info_t *si = RC.nrmac[mod_id]->pre_processor_dl.slices; nr_slice_info_t *si = RC.nrmac[mod_id]->pre_processor_dl.slices;
int bytes_last_round[MAX_NVS_SLICES] = {0}; int bytes_last_round[MAX_NVS_SLICES] = {0};
for (int s_idx = 0; s_idx < si->num; ++s_idx) { for (int s_idx = 0; s_idx < si->num; ++s_idx) {
UE_iterator(UE_info->list, UE) { UE_iterator (si->s[s_idx]->UE_list, UE) {
const NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; const NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (si->s[s_idx]->id == UE->dl_id) { bytes_last_round[s_idx] += UE->mac_stats.dl.current_bytes;
bytes_last_round[s_idx] += UE->mac_stats.dl.current_bytes;
/* if UE has data or retransmission, mark respective slice as active */ /* if UE has data or retransmission, mark respective slice as active */
const int retx_pid = sched_ctrl->retrans_dl_harq.head; const int retx_pid = sched_ctrl->retrans_dl_harq.head;
const bool active = sched_ctrl->num_total_bytes > 0 || retx_pid >= 0; const int retx_slice = sched_ctrl->harq_slice_map[retx_pid];
((_nvs_int_t *)si->s[s_idx]->int_data)->active |= active; const bool active = sched_ctrl->sliceInfo[s_idx].num_total_bytes > 0 || retx_slice == s_idx;
} ((_nvs_int_t *)si->s[s_idx]->int_data)->active |= active;
} }
} }
...@@ -471,6 +514,10 @@ void nvs_nr_dl(module_id_t mod_id, ...@@ -471,6 +514,10 @@ void nvs_nr_dl(module_id_t mod_id,
((_nvs_int_t *)si->s[maxidx]->int_data)->rb = n_rb_sched; ((_nvs_int_t *)si->s[maxidx]->int_data)->rb = n_rb_sched;
UE_iterator (si->s[maxidx]->UE_list, UE) {
UE->UE_sched_ctrl.last_sched_slice = maxidx;
}
/* proportional fair scheduling algorithm */ /* proportional fair scheduling algorithm */
int rb_rem = si->s[maxidx]->dl_algo.run(mod_id, int rb_rem = si->s[maxidx]->dl_algo.run(mod_id,
frame, frame,
......
...@@ -60,7 +60,7 @@ typedef struct nr_slice_info_s { ...@@ -60,7 +60,7 @@ typedef struct nr_slice_info_s {
#define NVS_SLICING 20 #define NVS_SLICING 20
/* arbitrary upper limit, increase if you want to instantiate more slices */ /* arbitrary upper limit, increase if you want to instantiate more slices */
#define MAX_NVS_SLICES 10 #define MAX_NVS_SLICES NR_MAX_NUM_SLICES
/* window for slice weight averaging -> 1s for fine granularity */ /* window for slice weight averaging -> 1s for fine granularity */
#define BETA 0.001f #define BETA 0.001f
typedef struct { typedef struct {
......
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