Commit af676180 authored by Cedric Roux's avatar Cedric Roux

Merge branch 'bugfix-188-multi-UEs-fixes' into develop_integration_w03

parents 69c8b8a9 a0f19a72
......@@ -195,10 +195,14 @@ rrc_mac_config_req(
}
}
else {
if (logicalChannelConfig)
UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup;
else
UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0;
if (UE_id == -1) {
LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
} else {
if (logicalChannelConfig)
UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup;
else
UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0;
}
}
}
......@@ -296,7 +300,10 @@ rrc_mac_config_req(
if (physicalConfigDedicated != NULL) {
if (eNB_flagP==1) {
mac_xface->phy_config_dedicated_eNB(Mod_idP, CC_idP, UE_RNTI(Mod_idP, UE_id), physicalConfigDedicated);
if (UE_id == -1)
LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
else
mac_xface->phy_config_dedicated_eNB(Mod_idP, CC_idP, UE_RNTI(Mod_idP, UE_id), physicalConfigDedicated);
} else {
mac_xface->phy_config_dedicated_ue(Mod_idP,0,eNB_index,physicalConfigDedicated);
UE_mac_inst[Mod_idP].physicalConfigDedicated=physicalConfigDedicated; // for SR proc
......@@ -308,7 +315,10 @@ rrc_mac_config_req(
if (sCellToAddMod_r10 != NULL) {
if (eNB_flagP==1) {
mac_xface->phy_config_dedicated_scell_eNB(Mod_idP,UE_RNTI(Mod_idP,UE_id),sCellToAddMod_r10,1);
if (UE_id == -1)
LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
else
mac_xface->phy_config_dedicated_scell_eNB(Mod_idP,UE_RNTI(Mod_idP,UE_id),sCellToAddMod_r10,1);
} else {
//#warning "phy_config_dedicated_scell_ue is empty"
......
......@@ -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;
......@@ -121,10 +121,21 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
memset(eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map,0,100);
}
// clear DCI and BCCH contents before scheduling
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
DCI_pdu[CC_id]->Num_common_dci = 0;
DCI_pdu[CC_id]->Num_ue_spec_dci = 0;
#ifdef Rel10
eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active =0;
#endif
eNB_mac_inst[module_idP].frame = frameP;
eNB_mac_inst[module_idP].subframe = subframeP;
}
// 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))
......@@ -132,8 +143,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
UE_list->UE_sched_ctrl[i].ul_out_of_sync==0 ? "in synch" : "out of sync",
UE_list->UE_template[CC_id][i].phr_info);
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]);
......@@ -261,8 +270,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)
......@@ -319,22 +326,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
#endif
// clear DCI and BCCH contents before scheduling
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
DCI_pdu[CC_id]->Num_common_dci = 0;
DCI_pdu[CC_id]->Num_ue_spec_dci = 0;
#ifdef Rel10
eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active =0;
#endif
eNB_mac_inst[module_idP].frame = frameP;
eNB_mac_inst[module_idP].subframe = subframeP;
}
/* #ifndef DISABLE_SF_TRIGGER */
/* //Send subframe trigger to the controller */
/* if (mac_agent_registered[module_idP]) { */
......
......@@ -73,7 +73,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
unsigned char i,harq_pid,round;
int16_t rrc_sdu_length;
unsigned char lcid,offset;
module_id_t UE_id= UE_INDEX_INVALID;
int UE_id = -1;
unsigned short TBsize = -1;
unsigned short msg4_padding,msg4_post_padding,msg4_header;
uint8_t *vrb_map;
......@@ -266,6 +266,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
// check for Msg4 Message
UE_id = find_UE_id(module_idP,RA_template->rnti);
if (UE_id == -1) { printf("%s:%d:%s: FATAL ERROR\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
if (Is_rrc_registered == 1) {
......@@ -709,7 +710,10 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
RA_template->RA_dci_size_bits2,
RA_template->RA_dci_fmt2,
0);
printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP);
}
else
printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP);
LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n",
module_idP,CC_id,frameP,subframeP,RA_template->rnti);
} else {
......@@ -718,6 +722,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un
remove UE instance across all the layers: mac_xface->cancel_RA();
}
*/
printf("MAC: msg4 acknowledged for rnti %x fsf %d/%d, let's configure it\n", RA_template->rnti, frameP, subframeP);
LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP);
RA_template->wait_ack_Msg4=0;
RA_template->RA_active=FALSE;
......@@ -746,14 +751,26 @@ void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0);
for (i=0; i<NB_RA_PROC_MAX; i++) {
if (RA_template[i].RA_active==FALSE) {
if (RA_template[i].RA_active==FALSE &&
RA_template[i].wait_ack_Msg4 == 0) {
int loop = 0;
RA_template[i].RA_active=TRUE;
RA_template[i].generate_rar=1;
RA_template[i].generate_Msg4=0;
RA_template[i].wait_ack_Msg4=0;
RA_template[i].timing_offset=timing_offset;
// Put in random rnti (to be replaced with proper procedure!!)
RA_template[i].rnti = taus();
/* TODO: find better procedure to allocate RNTI */
do {
RA_template[i].rnti = taus();
loop++;
} while (loop != 100 &&
/* TODO: this is not correct, the rnti may be in use without
* being in the MAC yet. To be refined.
*/
!(find_UE_id(module_idP, RA_template[i].rnti) == -1 &&
/* 1024 and 60000 arbirarily chosen, not coming from standard */
RA_template[i].rnti >= 1024 && RA_template[i].rnti < 60000));
if (loop == 100) { printf("%s:%d:%s: FATAL ERROR! contact the authors\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
RA_template[i].RA_rnti = 1+subframeP+(10*f_id);
RA_template[i].preamble_index = preamble_index;
LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation for process %d, rnti %x, RA_active %d\n",
......@@ -763,6 +780,8 @@ void initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t
return;
}
}
LOG_E(MAC,"[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
}
void cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, rnti_t rnti)
......
......@@ -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);
......
......@@ -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,17 @@ 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;
printf("MAC: new UE id %d rnti %x\n", i, rntiP);
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;
......@@ -273,6 +268,7 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
return(UE_id);
}
printf("MAC: cannot add new UE for rnti %x\n", rntiP);
LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
dump_ue_list(UE_list,0);
return(-1);
......@@ -282,23 +278,27 @@ 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 = UE_PCCID(mod_idP,UE_id);
int pCC_id;
if (UE_id == -1) {
printf("MAC: cannot remove UE rnti %x\n", rntiP);
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;
}
pCC_id = UE_PCCID(mod_idP,UE_id);
printf("MAC: remove UE %d rnti %x\n", UE_id, 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;
......@@ -313,58 +313,13 @@ 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
RA_TEMPLATE *RA_template;
for (i=0;i<NB_RA_PROC_MAX;i++) {
RA_template = (RA_TEMPLATE *)&eNB_mac_inst[mod_idP].common_channels[pCC_id].RA_template[i];
if ((RA_template->RA_active == TRUE) &&
(RA_template->rnti == rntiP)){
if (RA_template->rnti == rntiP){
RA_template->RA_active=FALSE;
RA_template->generate_rar=0;
RA_template->generate_Msg4=0;
......@@ -372,18 +327,11 @@ int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP)
RA_template->timing_offset=0;
RA_template->RRC_timer=20;
RA_template->rnti = 0;
break;
//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;
}
......@@ -1096,7 +1044,7 @@ try_again:
1<<DCI_pdu->dci_alloc[j].L,
nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols);
}
dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,dci_alloc->L);
//dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,dci_alloc->L);
goto failed;
}
......
......@@ -751,6 +751,39 @@ void schedule_ulsch_rnti(module_id_t module_idP,
continue;
}
/* let's drop the UE if get_eNB_UE_stats returns NULL when calling it with any of the UE's active UL CCs */
/* TODO: refine? */
drop_ue = 0;
for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
CC_id = UE_list->ordered_ULCCids[n][UE_id];
if (mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti) == NULL) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
drop_ue = 1;
break;
}
}
if (drop_ue == 1) {
/* we can't come here, ulsch_scheduler_pre_processor won't put in the list a UE with no PHY context */
abort();
/* TODO: this is a hack. Sometimes the UE has no PHY context but
* is still present in the MAC with 'ul_failure_timer' = 0 and
* 'ul_out_of_sync' = 0. It seems wrong and the UE stays there forever. Let's
* start an UL out of sync procedure in this case.
* The root cause of this problem has to be found and corrected.
* In the meantime, this hack...
*/
if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0 &&
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: UE in weird state, let's put it 'out of sync'\n",
module_idP,frameP,subframeP,UE_id,rnti,CC_id);
// inform RRC of failure and clear timer
mac_eNB_rrc_ul_failure(module_idP,CC_id,frameP,subframeP,rnti);
UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0;
UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=1;
}
continue;
}
// loop over all active UL CC_ids for this UE
for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
// This is the actual CC_id in the list
......@@ -758,15 +791,6 @@ void schedule_ulsch_rnti(module_id_t module_idP,
frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
if (eNB_UE_stats==NULL) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: no PHY context\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
drop_ue=1;
continue; // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
}
if (drop_ue==1)
continue;
if (CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti)) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d: not enough nCCE\n", module_idP,frameP,subframeP,UE_id,rnti,CC_id);
continue; // break;
......@@ -882,6 +906,12 @@ void schedule_ulsch_rnti(module_id_t module_idP,
T_INT(subframeP), T_INT(harq_pid), T_INT(mcs), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]),
T_INT(TBS), T_INT(ndi));
if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED)
LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
first_rb[CC_id],rb_table[rb_table_index],
rb_table_index,TBS,harq_pid);
// bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB)
// increment for next UE allocation
first_rb[CC_id]+=rb_table[rb_table_index];
......@@ -891,12 +921,6 @@ void schedule_ulsch_rnti(module_id_t module_idP,
if (UE_id == UE_list->head)
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled);
if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED)
LOG_I(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, rb_table_index %d, TBS %d, harq_pid %d)\n",
module_idP,harq_pid,rnti,CC_id,frameP,subframeP,UE_id,mcs,
first_rb[CC_id],rb_table[rb_table_index],
rb_table_index,TBS,harq_pid);
// adjust total UL buffer status by TBS, wait for UL sdus to do final update
LOG_D(MAC,"[eNB %d] CC_id %d UE %d/%x : adjusting ul_total_buffer, old %d, TBS %d\n", module_idP,CC_id,UE_id,rnti,UE_template->ul_total_buffer,TBS);
if (UE_template->ul_total_buffer > TBS)
......
......@@ -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];
......@@ -155,10 +170,16 @@ void assign_rbs_required (module_id_t Mod_id,
LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
// 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) */
if (!phy_stats_exist(Mod_id, rnti))
continue;
//update CQI information across component carriers
for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
......@@ -262,7 +283,7 @@ int maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uin
}
// This function scans all CC_ids for a particular UE to find the maximum DL CQI
// it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL)
int maxcqi(module_id_t Mod_id,int32_t UE_id)
{
......@@ -276,8 +297,9 @@ int maxcqi(module_id_t Mod_id,int32_t UE_id)
eNB_UE_stats = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,UE_RNTI(Mod_id,UE_id));
if (eNB_UE_stats==NULL) {
mac_xface->macphy_exit("maxcqi: could not get eNB_UE_stats\n");
return 0; // not reached
/* the UE may have been removed in the PHY layer, don't exit */
//mac_xface->macphy_exit("maxcqi: could not get eNB_UE_stats\n");
return -1;
}
if (eNB_UE_stats->DL_cqi[0] > CQI) {
......@@ -288,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] <