diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index d00167160f9decbd3eab5266fca5d909e7c6d83b..023d01d656d95c0e906b13a726d7887a5b3290f7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -99,7 +99,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, int result; #endif DCI_PDU *DCI_pdu[MAX_NUM_CCs]; - int CC_id,i,next_i; + int CC_id,i; //,next_i; UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list; rnti_t rnti; void *DLSCH_dci=NULL; @@ -133,17 +133,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } // refresh UE list based on UEs dropped by PHY in previous subframe - i = UE_list->head; + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) continue; - while (i>=0) { rnti = UE_RNTI(module_idP, i); CC_id = UE_PCCID(module_idP, i); if ((frameP==0)&&(subframeP==0)) LOG_I(MAC,"UE rnti %x : %s\n", rnti, UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync"); - next_i= UE_list->next[i]; - PHY_vars_eNB_g[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]=-63; if (i==UE_list->head) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,PHY_vars_eNB_g[module_idP][CC_id]->pusch_stats_bsr[i][(frameP*10)+subframeP]); @@ -271,8 +269,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } } // ul_failure_timer>0 - - i = next_i; } #if defined(ENABLE_ITTI) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 93dc9937119390e893d7ea084c20878b62c203ce..770264074f42a011130abe4bb7d175431c4dce9a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -453,9 +453,11 @@ schedule_ue_spec( UE_sched_ctrl *ue_sched_ctl; int i; +#if 0 if (UE_list->head==-1) { return; } +#endif start_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 3cf36eaa8d3845350018632a8bf7b47f0f16dfda..db204c77625e23fc5a8a67d7ee4bb13cabdc3ba1 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -107,18 +107,17 @@ DCI_PDU *get_dci_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame int find_UE_id(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { - int UE_id; UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list; - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) continue; if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) { return(UE_id); } } return(-1); - } //------------------------------------------------------------------------------ @@ -235,21 +234,16 @@ void dump_ue_list(UE_list_t *listP, int ul_flag) int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP) { int UE_id; - int j; + int i, j; UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list; LOG_D(MAC,"[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n",mod_idP,cc_idP,rntiP,UE_list->avail,UE_list->num_UEs); dump_ue_list(UE_list,0); - if (UE_list->avail>=0) { - UE_id = UE_list->avail; - AssertFatal( UE_id < NUMBER_OF_UE_MAX, "BAD UE_id %u > NUMBER_OF_UE_MAX",UE_id ); - UE_list->avail = UE_list->next[UE_list->avail]; - UE_list->next[UE_id] = UE_list->head; - UE_list->next_ul[UE_id] = UE_list->head_ul; - UE_list->head = UE_id; - UE_list->head_ul = UE_id; + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] == TRUE) continue; + UE_id = i; UE_list->UE_template[cc_idP][UE_id].rnti = rntiP; UE_list->UE_template[cc_idP][UE_id].configured = FALSE; UE_list->numactiveCCs[UE_id] = 1; @@ -282,17 +276,14 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP) int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) //------------------------------------------------------------------------------ { - - int prev,i, ret=-1; - - + int i; UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list; int UE_id = find_UE_id(mod_idP,rntiP); int pCC_id; if (UE_id == -1) { LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP); - mac_phy_remove_ue(mod_idP,rntiP); + mac_phy_remove_ue(mod_idP, rntiP); return 0; } @@ -301,6 +292,9 @@ int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP); dump_ue_list(UE_list,0); + UE_list->active[UE_id] = FALSE; + UE_list->num_UEs--; + // clear all remaining pending transmissions UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0] = 0; UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1] = 0; @@ -315,50 +309,6 @@ int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti = NOT_A_RNTI; eNB_dlsch_info[mod_idP][pCC_id][UE_id].status = S_DL_NONE; - prev = UE_list->head; - - for (i=UE_list->head; i>=0; i=UE_list->next[i]) { - if (i == UE_id) { - // link prev to next in Active list - if (i==UE_list->head) { - UE_list->head = UE_list->next[i]; - } else { - UE_list->next[prev] = UE_list->next[i]; - } - - // add UE id (i)to available - UE_list->next[i] = UE_list->avail; - UE_list->avail = i; - UE_list->active[i] = FALSE; - UE_list->num_UEs--; - ret=0; - break; - } - - prev=i; - } - - // do the same for UL - prev = UE_list->head_ul; - - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { - if (i == UE_id) { - // link prev to next in Active list - if (i==UE_list->head_ul) { - UE_list->head_ul = UE_list->next_ul[i]; - } else { - UE_list->next_ul[prev] = UE_list->next_ul[i]; - } - - // add UE id (i)to available - UE_list->next_ul[i] = UE_list->avail; - ret = 0; - break; - } - - prev=i; - } - mac_phy_remove_ue(mod_idP,rntiP); // check if this has an RA process active @@ -376,15 +326,8 @@ int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) //break; } } - if (ret == 0) { - return (0); - } - - LOG_E(MAC,"error in mac_remove_ue(), could not find previous to %d in UE_list, should never happen, Dumping UE list\n",UE_id); - dump_ue_list(UE_list,0); - mac_xface->macphy_exit("mac_remove_ue: Problem in UE_list"); - return(-1); + return 0; } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 150f2c15de346510cda092875ebd93c5667bee76..f2f8c643e8bbe2e59d69e9f2c1918ed333860270 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -29,6 +29,9 @@ */ +#define _GNU_SOURCE +#include <stdlib.h> + #include "assertions.h" #include "PHY/defs.h" #include "PHY/extern.h" @@ -62,6 +65,17 @@ #endif */ +/* this function checks that get_eNB_UE_stats returns + * a non-NULL pointer for all CCs for a given UE + */ +static int phy_stats_exist(module_id_t Mod_id, int rnti) +{ + int CC_id; + for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) + if (mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti) == NULL) + return 0; + return 1; +} // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer (module_id_t Mod_id, @@ -75,7 +89,8 @@ void store_dlsch_buffer (module_id_t Mod_id, UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; UE_TEMPLATE *UE_template; - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) continue; UE_template = &UE_list->UE_template[UE_PCCID(Mod_id,UE_id)][UE_id]; @@ -153,23 +168,16 @@ void assign_rbs_required (module_id_t Mod_id, UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list; // UE_TEMPLATE *UE_template; LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; - int skip_ue; // clear rb allocations across all CC_ids - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { + if (UE_list->active[UE_id] != TRUE) continue; + pCCid = UE_PCCID(Mod_id,UE_id); rnti = UE_list->UE_template[pCCid][UE_id].rnti; /* skip UE not present in PHY (for any of its active CCs) */ - skip_ue = 0; - for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - if (mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti) == NULL) { - skip_ue = 1; - break; - } - } - if (skip_ue == 1) + if (!phy_stats_exist(Mod_id, rnti)) continue; //update CQI information across component carriers @@ -302,13 +310,124 @@ int maxcqi(module_id_t Mod_id,int32_t UE_id) return(CQI); } +struct sort_ue_dl_params { + int Mod_idP; + int frameP; + int subframeP; +}; + +static int ue_dl_compare(const void *_a, const void *_b, void *_params) +{ + struct sort_ue_dl_params *params = _params; + UE_list_t *UE_list = &eNB_mac_inst[params->Mod_idP].UE_list; + + int UE_id1 = *(const int *)_a; + int UE_id2 = *(const int *)_b; + + int rnti1 = UE_RNTI(params->Mod_idP, UE_id1); + int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1); + int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP, 1); + + int rnti2 = UE_RNTI(params->Mod_idP, UE_id2); + int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2); + int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP, 1); + + int cqi1 = maxcqi(params->Mod_idP, UE_id1); + int cqi2 = maxcqi(params->Mod_idP, UE_id2); + + if (round1 > round2) return -1; + if (round1 < round2) return 1; + + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] > + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) + return -1; + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) + return 1; + + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max > + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) + return -1; + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) + return 1; + + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total > + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) + return -1; + if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) + return 1; + + if (cqi1 > cqi2) return -1; + if (cqi1 < cqi2) return 1; + + return 0; +#if 0 + /* The above order derives from the following. */ + if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order + swap_UEs(UE_list,UE_id1,UE_id2,0); + } else if (round2 == round1) { + // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service. + // for(j=0;j<MAX_NUM_LCID;j++){ + // if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] < + // eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){ + + // first check the buffer status for SRB1 and SRB2 + if ( (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2]) < + (UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) ) { + swap_UEs(UE_list,UE_id1,UE_id2,0); + } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max ) { + swap_UEs(UE_list,UE_id1,UE_id2,0); + } else if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < + UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total ) { + swap_UEs(UE_list,UE_id1,UE_id2,0); + } else if (cqi1 < cqi2) { + swap_UEs(UE_list,UE_id1,UE_id2,0); + } + } +#endif +} // This fuction sorts the UE in order their dlsch buffer and CQI void sort_UEs (module_id_t Mod_idP, int frameP, sub_frame_t subframeP) { + int i; + int list[NUMBER_OF_UE_MAX]; + int list_size = 0; + int rnti; + struct sort_ue_dl_params params = { Mod_idP, frameP, subframeP }; + + UE_list_t *UE_list = &eNB_mac_inst[Mod_idP].UE_list; + + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + rnti = UE_RNTI(Mod_idP, i); + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + if (!phy_stats_exist(Mod_idP, rnti)) + continue; + list[list_size] = i; + list_size++; + } + + qsort_r(list, list_size, sizeof(int), ue_dl_compare, ¶ms); + + if (list_size) { + for (i = 0; i < list_size-1; i++) + UE_list->next[list[i]] = list[i+1]; + UE_list->next[list[list_size-1]] = -1; + UE_list->head = list[0]; + } else { + UE_list->head = -1; + } + +#if 0 int UE_id1,UE_id2; @@ -329,6 +448,8 @@ void sort_UEs (module_id_t Mod_idP, continue; if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(Mod_idP, rnti1)) + continue; pCC_id1 = UE_PCCID(Mod_idP,UE_id1); cqi1 = maxcqi(Mod_idP,UE_id1); // round1 = maxround(Mod_idP,rnti1,frameP,subframeP,0); @@ -339,17 +460,13 @@ void sort_UEs (module_id_t Mod_idP, continue; if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(Mod_idP, rnti2)) + continue; cqi2 = maxcqi(Mod_idP,UE_id2); round2 = maxround(Mod_idP,rnti2,frameP,subframeP,0); //mac_xface->get_ue_active_harq_pid(Mod_id,rnti2,subframe,&harq_pid2,&round2,0); pCC_id2 = UE_PCCID(Mod_idP,UE_id2); - /* if 2nd UE is not in PHY, do nothing */ - if (cqi2 == -1) - continue; - /* if 1st UE is not in PHY, swap with 2nd UE */ - if (cqi1 == -1) { - swap_UEs(UE_list,UE_id1,UE_id2,0); - } else if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order + if(round2 > round1) { // Check first if one of the UEs has an active HARQ process which needs service and swap order swap_UEs(UE_list,UE_id1,UE_id2,0); } else if (round2 == round1) { // RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels. This should be done on the sum of all information that has to be sent. And still it wouldn't ensure fairness. It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service. @@ -374,6 +491,7 @@ void sort_UEs (module_id_t Mod_idP, } } } +#endif } @@ -427,7 +545,9 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id); - for (i=UE_list->head; i>=0; i=UE_list->next[i]) { + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) continue; + UE_id = i; // Initialize scheduling information for all active UEs @@ -473,11 +593,9 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, continue; if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; - UE_id = i; - - // if there is no available harq_process, skip the UE - if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0) + if (!phy_stats_exist(Mod_id, rnti)) continue; + UE_id = i; for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) { CC_id = UE_list->ordered_CCids[ii][UE_id]; @@ -485,6 +603,10 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, harq_pid = ue_sched_ctl->harq_pid[CC_id]; round = ue_sched_ctl->round[CC_id]; + // if there is no available harq_process, skip the UE + if (UE_list->UE_sched_ctrl[UE_id].harq_pid[CC_id]<0) + continue; + average_rbs_per_user[CC_id]=0; frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id); @@ -526,6 +648,13 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, for(i=UE_list->head; i>=0; i=UE_list->next[i]) { rnti = UE_RNTI(Mod_id,i); + if(rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + if (!phy_stats_exist(Mod_id, rnti)) + continue; + for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) { CC_id = UE_list->ordered_CCids[ii][i]; @@ -584,6 +713,8 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, continue; if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(Mod_id, rnti)) + continue; transmission_mode = mac_xface->get_transmission_mode(Mod_id,CC_id,rnti); // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0); @@ -630,6 +761,8 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, continue; if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(Mod_idP, rnti2)) + continue; eNB_UE_stats2 = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti2); //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); @@ -993,6 +1126,9 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(module_idP, rnti)) + continue; + UE_id = i; for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) { @@ -1043,6 +1179,8 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, continue; if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(module_idP, rnti)) + continue; UE_id = i; @@ -1073,6 +1211,8 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, continue; if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(module_idP, rnti)) + continue; UE_id = i; @@ -1130,7 +1270,8 @@ void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subfra LTE_DL_FRAME_PARMS *frame_parms; - for (i=UE_list->head_ul; i>=0; i=UE_list->next_ul[i]) { + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (UE_list->active[i] != TRUE) continue; rnti = UE_RNTI(module_idP,i); @@ -1138,6 +1279,8 @@ void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subfra continue; if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(module_idP, rnti)) + continue; if (UE_list->UE_sched_ctrl[i].phr_received == 1) mcs = 20; // if we've received the power headroom information the UE, we can go to maximum mcs @@ -1221,10 +1364,103 @@ void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subfra } } +struct sort_ue_ul_params { + int module_idP; + int frameP; + int subframeP; +}; + +static int ue_ul_compare(const void *_a, const void *_b, void *_params) +{ + struct sort_ue_ul_params *params = _params; + UE_list_t *UE_list = &eNB_mac_inst[params->module_idP].UE_list; + + int UE_id1 = *(const int *)_a; + int UE_id2 = *(const int *)_b; + + int rnti1 = UE_RNTI(params->module_idP, UE_id1); + int pCCid1 = UE_PCCID(params->module_idP, UE_id1); + int round1 = maxround(params->module_idP, rnti1, params->frameP, params->subframeP, 1); + + int rnti2 = UE_RNTI(params->module_idP, UE_id2); + int pCCid2 = UE_PCCID(params->module_idP, UE_id2); + int round2 = maxround(params->module_idP, rnti2, params->frameP, params->subframeP, 1); + + if (round1 > round2) return -1; + if (round1 < round2) return 1; + + if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) + return -1; + if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) + return 1; + + if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer > UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) + return -1; + if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) + return 1; + + if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + return -1; + if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + return 1; + + return 0; + +#if 0 + /* The above order derives from the following. + * The last case is not handled: "if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 )" + * I don't think it makes a big difference. + */ + if(round2 > round1) { + swap_UEs(UE_list,UE_id1,UE_id2,1); + } else if (round2 == round1) { + if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) { + swap_UEs(UE_list,UE_id1,UE_id2,1); + } else if (UE_list->UE_template[pCCid1][UE_id1].ul_total_buffer < UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer) { + swap_UEs(UE_list,UE_id1,UE_id2,1); + } else if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) { + if (UE_list->UE_template[pCCid2][UE_id2].ul_total_buffer > 0 ) { + swap_UEs(UE_list,UE_id1,UE_id2,1); + } + } + } +#endif +} void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP) { + int i; + int list[NUMBER_OF_UE_MAX]; + int list_size = 0; + int rnti; + struct sort_ue_ul_params params = { module_idP, frameP, subframeP }; + UE_list_t *UE_list = &eNB_mac_inst[module_idP].UE_list; + + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + rnti = UE_RNTI(module_idP, i); + if (rnti == NOT_A_RNTI) + continue; + if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) + continue; + if (!phy_stats_exist(module_idP, rnti)) + continue; + list[list_size] = i; + list_size++; + } + + qsort_r(list, list_size, sizeof(int), ue_ul_compare, ¶ms); + + if (list_size) { + for (i = 0; i < list_size-1; i++) + UE_list->next_ul[list[i]] = list[i+1]; + UE_list->next_ul[list[list_size-1]] = -1; + UE_list->head_ul = list[0]; + } else { + UE_list->head_ul = -1; + } + +#if 0 int UE_id1,UE_id2; int pCCid1,pCCid2; int round1,round2; @@ -1246,6 +1482,8 @@ void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP) continue; if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(module_idP, rnti1)) + continue; pCCid1 = UE_PCCID(module_idP,UE_id1); round1 = maxround(module_idP,rnti1,frameP,subframeP,1); @@ -1257,6 +1495,8 @@ void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP) continue; if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1) continue; + if (!phy_stats_exist(module_idP, rnti2)) + continue; pCCid2 = UE_PCCID(module_idP,UE_id2); round2 = maxround(module_idP,rnti2,frameP,subframeP,1); @@ -1276,4 +1516,5 @@ void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP) } } } +#endif }