Commit 2bf11808 authored by Cedric Roux's avatar Cedric Roux

Merge remote-tracking branch 'origin/feature-68-enb-agent' into develop_integration_w06

 Conflicts:
	openair2/LAYER2/MAC/flexran_agent_scheduler_dlsch_ue.c
parents ce14050b 274030c4
......@@ -92,6 +92,9 @@ extern uint16_t hundred_times_log10_NPRB[100];
unsigned int max_peak_val;
int max_sync_pos;
int harq_pid_updated[NUMBER_OF_UE_MAX][8] = {{0}};
int harq_pid_round[NUMBER_OF_UE_MAX][8] = {{0}};
//DCI_ALLOC_t dci_alloc[8];
#ifdef EMOS
......@@ -1444,15 +1447,6 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
eNB->dlsch_ra->active = 0;
}
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_SF_TRIGGER
//Send subframe trigger to the controller
if (mac_agent_registered[eNB->Mod_id]) {
agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
}
#endif
#endif
// Now scan UE specific DLSCH
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
{
......@@ -1553,7 +1547,6 @@ void process_HARQ_feedback(uint8_t UE_id,
int subframe = proc->subframe_rx;
int harq_pid = subframe2harq_pid( fp,frame,subframe);
if (fp->frame_type == FDD) { //FDD
subframe_m4 = (subframe<4) ? subframe+6 : subframe-4;
......@@ -1681,6 +1674,7 @@ void process_HARQ_feedback(uint8_t UE_id,
mp = m;
dl_harq_pid[m] = dlsch->harq_ids[dl_subframe];
harq_pid_updated[UE_id][dl_harq_pid[m]] = 1;
if ((pucch_sel != 2)&&(pusch_flag == 0)) { // multiplexing
if ((SR_payload == 1)&&(all_ACKed == 1))
......@@ -1768,7 +1762,7 @@ void process_HARQ_feedback(uint8_t UE_id,
eNB->dlsch[(uint8_t)UE_id][0]->harq_processes[dl_harq_pid[m]]->TBS;
*/
}
// Do fine-grain rate-adaptation for DLSCH
if (ue_stats->dlsch_NAK_round0 > dlsch->error_threshold) {
if (ue_stats->dlsch_mcs_offset == 1)
......@@ -1781,7 +1775,7 @@ void process_HARQ_feedback(uint8_t UE_id,
LOG_D(PHY,"[process_HARQ_feedback] Frame %d Setting round to %d for pid %d (subframe %d)\n",frame,
dlsch_harq_proc->round,dl_harq_pid[m],subframe);
#endif
harq_pid_round[UE_id][dl_harq_pid[m]] = dlsch_harq_proc->round;
// Clear NAK stats and adjust mcs offset
// after measurement window timer expires
if (ue_stats->dlsch_sliding_cnt == dlsch->ra_window_size) {
......@@ -1800,8 +1794,6 @@ void process_HARQ_feedback(uint8_t UE_id,
ue_stats->dlsch_NAK_round0 = 0;
ue_stats->dlsch_sliding_cnt = 0;
}
}
}
}
......@@ -3426,14 +3418,21 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
}
#endif
//}
#ifdef EMOS
phy_procedures_emos_eNB_RX(subframe,eNB);
#endif
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_SF_TRIGGER
//Send subframe trigger to the controller
if (mac_agent_registered[eNB->Mod_id]) {
agent_mac_xface[eNB->Mod_id]->flexran_agent_send_sf_trigger(eNB->Mod_id);
}
#endif
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
stop_meas(&eNB->phy_proc_rx);
......
......@@ -443,14 +443,14 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
if (rlc_reports[j] == NULL)
goto error;
protocol__flex_rlc_bsr__init(rlc_reports[j]);
rlc_reports[j]->lc_id = j+1;
rlc_reports[j]->lc_id = j + 1;
rlc_reports[j]->has_lc_id = 1;
rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id,i,j+1);
rlc_reports[j]->tx_queue_size = flexran_get_tx_queue_size(enb_id,i,j + 1);
rlc_reports[j]->has_tx_queue_size = 1;
//TODO:Set tx queue head of line delay in ms
rlc_reports[j]->tx_queue_hol_delay = 100;
rlc_reports[j]->has_tx_queue_hol_delay = 0;
rlc_reports[j]->tx_queue_hol_delay = flexran_get_hol_delay(enb_id, i, j+1);
rlc_reports[j]->has_tx_queue_hol_delay = 1;
//TODO:Set retransmission queue size in bytes
rlc_reports[j]->retransmission_queue_size = 10;
rlc_reports[j]->has_retransmission_queue_size = 0;
......@@ -657,6 +657,8 @@ int flexran_agent_mac_stats_reply(mid_t mod_id,
full_ul_report->pucch_dbm[j]->p0_pucch_dbm = flexran_get_p0_pucch_dbm(enb_id,i,j);
full_ul_report->pucch_dbm[j]->has_p0_pucch_dbm = 1;
}
full_ul_report->pucch_dbm[j]->has_p0_pucch_updated = 1;
full_ul_report->pucch_dbm[j]->p0_pucch_updated = flexran_get_p0_pucch_status(enb_id, i, j);
}
//Add full UL CQI report to the UE report
......@@ -921,9 +923,13 @@ int flexran_agent_mac_destroy_sr_info(Protocol__FlexranMessage *msg) {
int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__FlexranMessage **msg) {
Protocol__FlexHeader *header;
int i,j;
int i, j, UE_id;
int available_harq[NUMBER_OF_UE_MAX];
const int xid = *((int *)params);
Protocol__FlexSfTrigger *sf_trigger_msg;
sf_trigger_msg = malloc(sizeof(Protocol__FlexSfTrigger));
if (sf_trigger_msg == NULL) {
......@@ -937,29 +943,47 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
frame_t frame;
sub_frame_t subframe;
int ahead_of_time = 1;
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
available_harq[i] = -1;
}
int ahead_of_time = 0;
frame = (frame_t) flexran_get_current_system_frame_num(mod_id);
subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
subframe = ((subframe + ahead_of_time) % 10);
int full_frames_ahead = ((ahead_of_time / 10) % 10);
frame = frame + full_frames_ahead;
if (subframe < flexran_get_current_subframe(mod_id)) {
frame++;
frame = (frame + 1) % 1024;
}
int additional_frames = ahead_of_time / 10;
frame = (frame + additional_frames) % 1024;
sf_trigger_msg->header = header;
sf_trigger_msg->has_sfn_sf = 1;
sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 1);
sf_trigger_msg->sfn_sf = flexran_get_future_sfn_sf(mod_id, 3);
sf_trigger_msg->n_dl_info = 0;
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
for (j = 0; j < 8; j++) {
if (harq_pid_updated[i][j] == 1) {
available_harq[i] = j;
sf_trigger_msg->n_dl_info++;
break;
}
}
}
// LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10);
/*TODO: Fill in the number of dl HARQ related info, based on the number of currently
*transmitting UEs
*/
sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
// sf_trigger_msg->n_dl_info = flexran_get_num_ues(mod_id);
Protocol__FlexDlInfo **dl_info = NULL;
......@@ -967,29 +991,39 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle
dl_info = malloc(sizeof(Protocol__FlexDlInfo *) * sf_trigger_msg->n_dl_info);
if(dl_info == NULL)
goto error;
i = -1;
//Fill the status of the current HARQ process for each UE
for(i = 0; i < sf_trigger_msg->n_dl_info; i++) {
for(UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
if (available_harq[UE_id] < 0) {
continue;
} else {
i++;
}
dl_info[i] = malloc(sizeof(Protocol__FlexDlInfo));
if(dl_info[i] == NULL)
goto error;
protocol__flex_dl_info__init(dl_info[i]);
dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, i);
dl_info[i]->rnti = flexran_get_ue_crnti(mod_id, UE_id);
dl_info[i]->has_rnti = 1;
/*Fill in the right id of this round's HARQ process for this UE*/
unsigned char harq_id;
unsigned char harq_status;
flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
dl_info[i]->harq_process_id = harq_id;
// uint8_t harq_id;
//uint8_t harq_status;
// flexran_get_harq(mod_id, UE_PCCID(mod_id,i), i, frame, subframe, &harq_id, &harq_status);
dl_info[i]->harq_process_id = available_harq[UE_id];
harq_pid_updated[UE_id][available_harq[UE_id]] = 0;
dl_info[i]->has_harq_process_id = 1;
/* Fill in the status of the HARQ process (2 TBs)*/
dl_info[i]->n_harq_status = 2;
dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status);
for (j = 0; j < dl_info[i]->n_harq_status; j++) {
dl_info[i]->harq_status[j] = harq_pid_round[UE_id][available_harq[UE_id]];
// TODO: This should be different per TB
if(harq_status == 0)
dl_info[i]->harq_status[j] = PROTOCOL__FLEX_HARQ_STATUS__FLHS_ACK;
else if (harq_status > 0)
dl_info[i]->harq_status[j] = PROTOCOL__FLEX_HARQ_STATUS__FLHS_NACK;
}
// LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
if(dl_info[i]->harq_status[0] > 0) {
// LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Need to make a retransmission for harq %d (round %d)\n", flexran_get_current_frame(mod_id), flexran_get_current_subframe(mod_id), dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]);
}
/*Fill in the serving cell index for this UE */
dl_info[i]->serv_cell_index = UE_PCCID(mod_id,i);
......@@ -1234,12 +1268,18 @@ int flexran_agent_mac_handle_dl_mac_config(mid_t mod_id, const void *params, Pro
}
void flexran_agent_init_mac_agent(mid_t mod_id) {
int i, j;
lfds700_misc_library_init_valid_on_current_logical_core();
lfds700_misc_prng_init(&ps[mod_id]);
int num_elements = RINGBUFFER_SIZE + 1;
//Allow RINGBUFFER_SIZE messages to be stored in the ringbuffer at any time
dl_mac_config_array[mod_id] = malloc( sizeof(struct lfds700_ringbuffer_element) * num_elements);
lfds700_ringbuffer_init_valid_on_current_logical_core( &ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL );
for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
for (j = 0; j < 8; j++) {
harq_pid_updated[i][j] = 0;
}
}
}
/***********************************************
......
......@@ -166,6 +166,7 @@ message flex_ul_cqi_report {
message flex_pucch_dbm {
optional int32 p0_pucch_dbm = 1;
optional uint32 serv_cell_index = 2;
optional uint32 p0_pucch_updated = 3;
}
//
......
......@@ -516,15 +516,14 @@ uint16_t flexran_get_future_sfn_sf (mid_t mod_id, int ahead_of_time) {
subframe = (sub_frame_t) flexran_get_current_subframe(mod_id);
subframe = ((subframe + ahead_of_time) % 10);
int full_frames_ahead = ((ahead_of_time / 10) % 10);
frame = frame + full_frames_ahead;
if (subframe < flexran_get_current_subframe(mod_id)) {
frame++;
frame = (frame + 1) % 1024;
}
int additional_frames = ahead_of_time / 10;
frame = (frame + additional_frames) % 1024;
frame_mask = ((1<<12) - 1);
sf_mask = ((1<<4) - 1);
sfn_sf = (subframe & sf_mask) | ((frame & frame_mask) << 4);
......@@ -553,69 +552,81 @@ int flexran_get_ue_phr (mid_t mod_id, mid_t ue_id) {
}
int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) {
return ((UE_list_t *)enb_ue[mod_id])->eNB_UE_stats[UE_PCCID(mod_id,ue_id)][ue_id].dl_cqi;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, 0, UE_RNTI(mod_id, ue_id));
return eNB_UE_stats->DL_cqi[0];
// return ((UE_list_t *)enb_ue[mod_id])->eNB_UE_stats[UE_PCCID(mod_id,ue_id)][ue_id].dl_cqi;
}
int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO,channel_id,0);
return rlc_status.bytes_in_buffer;
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0);
return rlc_status.bytes_in_buffer;
}
int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id) {
int flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0);
return rlc_status.head_sdu_creation_time;
}
short flexran_get_TA(mid_t mod_id, mid_t ue_id, int CC_id) {
UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list;
UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
int rnti;
rnti = flexran_get_ue_crnti(mod_id, ue_id);
if (ue_sched_ctl->ta_timer == 0) {
// WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY
switch (PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RB_DL) {
case 6:
ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update;
break;
case 15:
ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2;
break;
case 25:
ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4;
break;
case 50:
ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8;
break;
case 75:
ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12;
break;
case 100:
ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16;
break;
LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
//ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY
switch (PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.N_RB_DL) {
case 6:
return eNB_UE_stats->timing_advance_update;
case 15:
return eNB_UE_stats->timing_advance_update/2;
case 25:
return eNB_UE_stats->timing_advance_update/4;
case 50:
return eNB_UE_stats->timing_advance_update/8;
case 75:
return eNB_UE_stats->timing_advance_update/12;
case 100:
if (PHY_vars_eNB_g[mod_id][CC_id]->frame_parms.threequarter_fs == 0) {
return eNB_UE_stats->timing_advance_update/16;
} else {
return eNB_UE_stats->timing_advance_update/12;
}
// clear the update in case PHY does not have a new measurement after timer expiry
eNB_UE_stats->timing_advance_update = 0;
}
else {
ue_sched_ctl->ta_timer--;
ue_sched_ctl->ta_update = 0; // don't trigger a timing advance command
default:
return 0;
}
}
return ue_sched_ctl->ta_update = 0;
void flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id) {
UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list;
UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
if (ue_sched_ctl->ta_timer == 0) {
// WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
// LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
//ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY
ue_sched_ctl->ta_update = flexran_get_TA(mod_id, ue_id, CC_id);
// clear the update in case PHY does not have a new measurement after timer expiry
// eNB_UE_stats->timing_advance_update = 0;
} else {
ue_sched_ctl->ta_timer--;
ue_sched_ctl->ta_update = 0; // don't trigger a timing advance command
}
}
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id,int CC_id) {
UE_list_t *UE_list = &eNB_mac_inst[mod_id].UE_list;
UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id];
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
......@@ -624,8 +635,8 @@ int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id,int CC_id) {
return 0;
}
if (ue_sched_ctl->ta_update == 0) {
return 1;
if (flexran_get_TA(mod_id, ue_id, CC_id) != 0) {
return PROTOCOL__FLEX_CE_TYPE__FLPCET_TA;
} else {
return 0;
}
......@@ -680,8 +691,13 @@ int flexran_get_tpc(mid_t mod_id, mid_t ue_id) {
return tpc;
}
int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id, const int frame, const uint8_t subframe,
unsigned char *id, unsigned char *round) { //flag_id_status = 0 then id, else status
int flexran_get_harq(const mid_t mod_id,
const uint8_t CC_id,
const mid_t ue_id,
const int frame,
const uint8_t subframe,
uint8_t *id,
uint8_t *round) { //flag_id_status = 0 then id, else status
/*TODO: Add int TB in function parameters to get the status of the second TB. This can be done to by editing in
* get_ue_active_harq_pid function in line 272 file: phy_procedures_lte_eNB.c to add
* DLSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->dlsch_eNB[(uint32_t)UE_id][1];*/
......@@ -707,43 +723,43 @@ int flexran_get_harq(const mid_t mod_id, const uint8_t CC_id, const mid_t ue_id,
}
int flexran_get_p0_pucch_dbm(mid_t mod_id, mid_t ue_id, int CC_id) {
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
if (eNB_UE_stats == NULL) {
return -1;
}
if(eNB_UE_stats->Po_PUCCH_update == 1) {
return eNB_UE_stats->Po_PUCCH_dBm;
}
else
return -1;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
if (eNB_UE_stats == NULL) {
return -1;
}
// if(eNB_UE_stats->Po_PUCCH_update == 1) {
return eNB_UE_stats->Po_PUCCH_dBm;
//}
//else
// return -1;
}
int flexran_get_p0_nominal_pucch(mid_t mod_id, int CC_id) {
int32_t pucch_rx_received = mac_xface->get_target_pucch_rx_power(mod_id, CC_id);
return pucch_rx_received;
int32_t pucch_rx_received = mac_xface->get_target_pucch_rx_power(mod_id, CC_id);
return pucch_rx_received;
}
int flexran_get_p0_pucch_status(mid_t mod_id, mid_t ue_id, int CC_id) {
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
return eNB_UE_stats->Po_PUCCH_update;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
return eNB_UE_stats->Po_PUCCH_update;
}
int flexran_update_p0_pucch(mid_t mod_id, mid_t ue_id, int CC_id) {
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
eNB_UE_stats->Po_PUCCH_update = 0;
return 0;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint32_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id, CC_id, rnti);
eNB_UE_stats->Po_PUCCH_update = 0;
return 0;
}
......
......@@ -185,8 +185,14 @@ int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id);
/* Get the transmission queue size for a UE with a channel_id logical channel id */
int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id);
/* Get the head of line delay for a UE with a channel_id logical channel id */
int flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id);
/* Check the status of the timing advance for a UE */
short flexran_get_TA(mid_t mod_id, mid_t ue_id, int CC_id);
/* Update the timing advance status (find out whether a timing advance command is required) */
int flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id);
void flexran_update_TA(mid_t mod_id, mid_t ue_id, int CC_id);
/* Return timing advance MAC control element for a designated cell and UE */
int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, int CC_id);
......
......@@ -45,4 +45,8 @@ extern AGENT_MAC_xface *agent_mac_xface[NUM_MAX_ENB];
/* Flag indicating whether the VSFs for the MAC control module have been registered */
extern unsigned int mac_agent_registered[NUM_MAX_ENB];
/* Requried to know which UEs had a harq updated over some subframe */
extern int harq_pid_updated[NUMBER_OF_UE_MAX][8];
extern int harq_pid_round[NUMBER_OF_UE_MAX][8];
#endif
......@@ -172,7 +172,7 @@ Protocol__FlexranMessage* flexran_agent_process_timeout(long timer_id, void* tim
struct flexran_agent_timer_element_s *found = get_timer_entry(timer_id);
if (found == NULL ) goto error;
LOG_I(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx 0x%lx\n", found, timer_id, found->timer_id);
LOG_D(FLEXRAN_AGENT, "Found the entry (%p): timer_id is 0x%lx 0x%lx\n", found, timer_id, found->timer_id);
if (timer_args == NULL)
LOG_W(FLEXRAN_AGENT,"null timer args\n");
......
......@@ -131,19 +131,6 @@ void _assign_rbs_required (module_id_t Mod_id,
uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES],
int min_rb_unit[MAX_NUM_CCs]);
int _maxround(module_id_t Mod_id,
uint16_t rnti,
int frame,
sub_frame_t subframe,
uint8_t ul_flag );
int _maxcqi(module_id_t Mod_id,
int32_t UE_id);
void _sort_UEs (module_id_t Mod_idP,
int frameP,
sub_frame_t subframeP);
void _dlsch_scheduler_pre_processor (module_id_t Mod_id,
int slice_id,
frame_t frameP,
......
......@@ -53,6 +53,9 @@
#include "header.pb-c.h"
#include "flexran.pb-c.h"
#include "flexran_agent_extern.h"
#include "flexran_agent_common.h"
#include "SIMULATION/TOOLS/defs.h" // for taus
......@@ -97,10 +100,10 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
unsigned char header_len = 0, header_len_tmp = 0;
unsigned char sdu_lcids[11],offset,num_sdus=0;
uint16_t nb_rb;
uint16_t TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0;
uint16_t TBS, sdu_lengths[11],rnti,padding=0,post_padding=0;
unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
unsigned char round = 0;
unsigned char harq_pid = 0;
uint8_t round = 0;
uint8_t harq_pid = 0;
// LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs];
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
uint16_t sdu_length_total = 0;
......@@ -112,17 +115,16 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
int last_sdu_header_len = 0;
int i;
int i, j;
Protocol__FlexDlData *dl_data;
Protocol__FlexDlDci *dl_dci;
uint32_t rlc_size, n_lc, lcid;
// For each UE-related command
for (i = 0; i < n_dl_ue_data; i++) {
dl_data = dl_ue_data[i];
dl_dci = dl_data->dl_dci;
......@@ -138,6 +140,9 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
round = dl_dci->rv[0];
harq_pid = dl_dci->harq_process;
//LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d] Scheduling harq %d\n", frame, subframe, harq_pid);
// LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d]Now scheduling harq_pid %d (round %d)\n", frame, subframe, harq_pid, round);
// If this is a new transmission
if (round == 0) {
// First we have to deal with the creation of the PDU based on the message instructions
......@@ -147,27 +152,22 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
if (dl_data->n_ce_bitmap > 0) {
//Check if there is TA command and set the length appropriately
ta_len = (dl_data->ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 1 : 0;
ta_len = (dl_data->ce_bitmap[0] & PROTOCOL__FLEX_CE_TYPE__FLPCET_TA) ? 2 : 0;
}
num_sdus = 0;
sdu_length_total = 0;
if (ta_len > 0) {
// Reset the measurement
ue_sched_ctl->ta_timer = 20;
eNB_UE_stats->timing_advance_update = 0;
header_len = ta_len;
last_sdu_header_len = ta_len;
}
n_lc = dl_data->n_rlc_pdu;
// Go through each one of the channel commands and create SDUs
for (i = 0; i < n_lc; i++) {
lcid = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->logical_channel_id;
rlc_size = dl_data->rlc_pdu[i]->rlc_pdu_tb[0]->size;
LOG_D(MAC,"[TEST] [eNB %d] Frame %d, LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
mod_id, frame, lcid, CC_id, rlc_size);
header_len = 0;
last_sdu_header_len = 0;
for (j = 0; j < n_lc; j++) {
sdu_lengths[j] = 0;
lcid = dl_data->rlc_pdu[j]->rlc_pdu_tb[0]->logical_channel_id;
rlc_size = dl_data->rlc_pdu[j]->rlc_pdu_tb[0]->size;
LOG_D(MAC,"[TEST] [eNB %d] [Frame %d] [Subframe %d], LCID %d, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
mod_id, frame, subframe, lcid, CC_id, rlc_size);
if (rlc_size > 0) {
rlc_status = mac_rlc_status_ind(mod_id,
......@@ -181,10 +181,14 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
if (rlc_status.bytes_in_buffer > 0) {
if (rlc_size <= 2) {
rlc_size = 3;
if (rlc_status.bytes_in_buffer < rlc_size) {
rlc_size = rlc_status.bytes_in_buffer;
}
if (rlc_size <= 2) {
rlc_size = 3;
}
rlc_status = mac_rlc_status_ind(mod_id,
rnti,
mod_id,
......@@ -194,29 +198,27 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
lcid,
rlc_size); // transport block set size
sdu_lengths[i] = 0;
LOG_D(MAC, "[TEST] RLC can give %d bytes for LCID %d during second call\n", rlc_status.bytes_in_buffer, lcid);
if (rlc_status.bytes_in_buffer > 0) {
sdu_lengths[i] += mac_rlc_data_req(mod_id,
rnti,
mod_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
(char *)&dlsch_buffer[sdu_length_total]);
sdu_lengths[j] = mac_rlc_data_req(mod_id,
rnti,
mod_id,
frame,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
(char *)&dlsch_buffer[sdu_length_total]);
LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[i]);
sdu_length_total += sdu_lengths[i];
sdu_lcids[i] = lcid;
LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[j]);
sdu_length_total += sdu_lengths[j];
sdu_lcids[j] = lcid;
UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1;
UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[i];
UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[j];
if (sdu_lengths[i] <= 128) {
if (sdu_lengths[j] < 128) {
header_len += 2;
last_sdu_header_len = 2;
} else {
......@@ -230,38 +232,46 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
} // SDU creation end
if (((sdu_length_total + header_len) > 0)) {
// header_len_tmp = header_len;
if (((sdu_length_total + header_len + ta_len) > 0)) {
header_len_tmp = header_len;
// If we have only a single SDU, header length becomes 1
if ((num_sdus + ta_len) == 1) {
if ((num_sdus) == 1) {
//if (header_len == 2 || header_len == 3) {
header_len = 1;
} else {
header_len = (header_len - last_sdu_header_len) + 1;
}
// there is a payload
if (((sdu_length_total + header_len) > 0)) {
// If we need a 1 or 2 bit padding or no padding at all
if ((TBS - header_len - sdu_length_total - ta_len) <= 2
|| (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow
padding = (TBS - header_len - sdu_length_total - ta_len);
post_padding = 0;
} else { // The last sdu needs to have a length field, since we add padding
padding = 0;
header_len = header_len_tmp;
post_padding = TBS - sdu_length_total - header_len - ta_len - 1; // 1 is for the postpadding header
}
// If we need a 1 or 2 bit padding or no padding at all
if ((TBS - header_len - sdu_length_total - ta_len) <= 2
|| (TBS - header_len - sdu_length_total - ta_len) > TBS) { //protect from overflow
padding = (TBS - header_len - sdu_length_total - ta_len);
post_padding = 0;
} else { // The last sdu needs to have a length field, since we add padding
padding = 0;
header_len = header_len_tmp;
post_padding = TBS - sdu_length_total - header_len - ta_len; // 1 is for the postpadding header
}
if (ta_len > 0) {
// Reset the measurement
ta_update = flexran_get_TA(mod_id, UE_id, CC_id);
ue_sched_ctl->ta_timer = 20;
eNB_UE_stats->timing_advance_update = 0;
} else {
ta_update = 0;
}
ta_update = (ta_len > 0) ? ue_sched_ctl->ta_update : 0;
// If there is nothing to schedule, just leave
if ((sdu_length_total) <= 0) {
return;
harq_pid_updated[UE_id][harq_pid] = 1;
harq_pid_round[UE_id][harq_pid] = 0;
continue;
}
// LOG_I(FLEXRAN_AGENT, "[Frame %d][Subframe %d] TBS is %d and bytes are %d\n", frame, subframe, TBS, sdu_length_total);
offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
num_sdus, //num_sdus
......@@ -272,6 +282,10 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
NULL, // contention res id
padding,
post_padding);
#ifdef DEBUG_eNB_SCHEDULER
LOG_T(MAC,"[eNB %d] First 16 bytes of DLSCH : \n");
......@@ -289,7 +303,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
// fill remainder of DLSCH with random data
for (j=0; j<(TBS-sdu_length_total-offset); j++) {
UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff);
}
}
//eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0][offset+sdu_lengths[0]+j] = (char)(taus()&0xff);
if (opt_enabled == 1) {
......@@ -319,6 +333,8 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
nb_rb += get_min_rb_unit(mod_id, CC_id);
stats_tbs = mac_xface->get_TBS_DL(dl_dci->mcs[0], nb_rb);
}
// LOG_I(FLEXRAN_AGENT, "The MCS was %d\n", dl_dci->mcs[0]);
UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb;
......@@ -333,10 +349,14 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
//eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]];
//eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
} else {
LOG_D(FLEXRAN_AGENT, "No need to schedule a dci after all. Just drop it\n");
harq_pid_updated[UE_id][harq_pid] = 1;
harq_pid_round[UE_id][harq_pid] = 0;
continue;
}
} else {
// No need to create anything apart of DCI in case of retransmission
/*TODO: Must add these */
// eNB_UE_stats->dlsch_trials[round]++;
//UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1;
......@@ -345,8 +365,8 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
//UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCECC_id];
}
UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0];
eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0];
// UE_list->UE_template[CC_id][UE_id].oldNDI[dl_dci->harq_process] = dl_dci->ndi[0];
// eNB_UE_stats->dlsch_mcs1 = dl_dci->mcs[0];
//Fill the proper DCI of OAI
flexran_fill_oai_dci(mod_id, CC_id, rnti, dl_dci);
......
......@@ -104,8 +104,8 @@ float total_slice_percentage = 0;
int slice_maxmcs[MAX_NUM_SLICES] = {28, 28, 28, 28};
int slice_maxmcs_current[MAX_NUM_SLICES] = {28, 28, 28, 28};
int update_dl_scheduler[MAX_NUM_SLICES] = {1, 0, 0, 0};
int update_dl_scheduler_current[MAX_NUM_SLICES] = {1, 0, 0, 0};
int update_dl_scheduler[MAX_NUM_SLICES] = {1, 1, 1, 1};
int update_dl_scheduler_current[MAX_NUM_SLICES] = {1, 1, 1, 1};
// name of available scheduler
char *dl_scheduler_type[MAX_NUM_SLICES] = {"flexran_schedule_ue_spec_embb",
......@@ -137,8 +137,9 @@ 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;
if (flexran_slice_member(UE_id, slice_id) == 0)
continue;
......@@ -221,7 +222,8 @@ void _assign_rbs_required (module_id_t Mod_id,
// UE_TEMPLATE *UE_template;
// 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;
if (flexran_slice_member(UE_id, slice_id) == 0)
continue;
......@@ -229,11 +231,15 @@ void _assign_rbs_required (module_id_t Mod_id,
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++) {
CC_id = UE_list->ordered_CCids[n][UE_id];
eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
eNB_UE_stats[CC_id]->dlsch_mcs1=cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)];
eNB_UE_stats[CC_id]->dlsch_mcs1 = cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)];
}
// provide the list of CCs sorted according to MCS
......@@ -260,143 +266,34 @@ void _assign_rbs_required (module_id_t Mod_id,
CC_id = UE_list->ordered_CCids[i][UE_id];
eNB_UE_stats[CC_id] = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti);
if (eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
if (cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)] == 0) {//eNB_UE_stats[CC_id]->dlsch_mcs1==0) {
nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small
} else {
nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id];
}
TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]);
nb_rbs_allowed_slice[CC_id][slice_id] = flexran_nb_rbs_allowed_slice(slice_percentage[slice_id],
flexran_get_N_RB_DL(Mod_id, CC_id));
LOG_D(MAC,"[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n",
UE_id, CC_id, UE_list->UE_template[pCCid][UE_id].dl_buffer_total,
nb_rbs_required[CC_id][UE_id],eNB_UE_stats[CC_id]->dlsch_mcs1,TBS);
nb_rbs_required[CC_id][UE_id], flexran_get_ue_wcqi(Mod_id, UE_id), TBS);
/* calculating required number of RBs for each UE */
while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) {
nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id];
if (nb_rbs_required[CC_id][UE_id] > nb_rbs_allowed_slice[CC_id][slice_id]) {
TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1, nb_rbs_allowed_slice[CC_id][slice_id]);
TBS = mac_xface->get_TBS_DL(flexran_get_ue_wcqi(Mod_id, UE_id), nb_rbs_allowed_slice[CC_id][slice_id]);
nb_rbs_required[CC_id][UE_id] = nb_rbs_allowed_slice[CC_id][slice_id];
break;
}
TBS = mac_xface->get_TBS_DL(eNB_UE_stats[CC_id]->dlsch_mcs1,nb_rbs_required[CC_id][UE_id]);
TBS = mac_xface->get_TBS_DL(cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)], nb_rbs_required[CC_id][UE_id]);
} // end of while
LOG_D(MAC,"[eNB %d][SLICE %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n",
Mod_id, slice_id,frameP,UE_id, CC_id, min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats[CC_id]->dlsch_mcs1);
}
}
}
}
// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes
int _maxround(module_id_t Mod_id,uint16_t rnti,int frame,sub_frame_t subframe,uint8_t ul_flag )
{
uint8_t round,round_max=0,UE_id;
int CC_id;
UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
UE_id = find_UE_id(Mod_id,rnti);
round = UE_list->UE_sched_ctrl[UE_id].round[CC_id];
if (round > round_max) {
round_max = round;
}
}
return round_max;
}
// This function scans all CC_ids for a particular UE to find the maximum DL CQI
int _maxcqi(module_id_t Mod_id,int32_t UE_id)
{
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
int CC_id,n;
int CQI = 0;
for (n=0; n<UE_list->numactiveCCs[UE_id]; n++) {
CC_id = UE_list->ordered_CCids[n][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
}
if (eNB_UE_stats->DL_cqi[0] > CQI) {
CQI = eNB_UE_stats->DL_cqi[0];
}
}
return(CQI);
}
// 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 UE_id1,UE_id2;
int pCC_id1,pCC_id2;
int cqi1,cqi2,round1,round2;
int i=0,ii=0;//,j=0;
rnti_t rnti1,rnti2;
UE_list_t *UE_list = &eNB_mac_inst[Mod_idP].UE_list;
for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
for(ii=UE_list->next[i]; ii>=0; ii=UE_list->next[ii]) {
UE_id1 = i;
rnti1 = UE_RNTI(Mod_idP,UE_id1);
if(rnti1 == NOT_A_RNTI)
continue;
if (UE_list->UE_sched_ctrl[UE_id1].ul_out_of_sync == 1)
continue;
pCC_id1 = UE_PCCID(Mod_idP,UE_id1);
cqi1 = _maxcqi(Mod_idP,UE_id1); //
round1 = _maxround(Mod_idP,rnti1,frameP,subframeP,0);
UE_id2 = ii;
rnti2 = UE_RNTI(Mod_idP,UE_id2);
if(rnti2 == NOT_A_RNTI)
continue;
if (UE_list->UE_sched_ctrl[UE_id2].ul_out_of_sync == 1)
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(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.
// 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);
}
Mod_id, slice_id,frameP,UE_id, CC_id, min_rb_unit[CC_id], nb_rbs_required[CC_id][UE_id], TBS, cqi_to_mcs[flexran_get_ue_wcqi(Mod_id, UE_id)]);
}
}
}
......@@ -543,10 +440,11 @@ void _dlsch_scheduler_pre_processor (module_id_t Mod_id,
int *mbsfn_flag)
{
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], harq_pid=0, total_ue_count;
unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], total_ue_count;
unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
int UE_id, i;
unsigned char round = 0;
uint8_t round = 0;
uint8_t harq_pid = 0;
uint16_t ii,j;
uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
uint16_t nb_rbs_allowed_slice[MAX_NUM_CCs][MAX_NUM_SLICES];
......@@ -574,7 +472,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
......@@ -602,24 +502,24 @@ void _dlsch_scheduler_pre_processor (module_id_t Mod_id,
_assign_rbs_required (Mod_id,slice_id, frameP,subframeP,nb_rbs_required,nb_rbs_allowed_slice,min_rb_unit);
// Sorts the user on the basis of dlsch logical channel buffer and CQI
_sort_UEs (Mod_id,frameP,subframeP);
sort_UEs (Mod_id,frameP,subframeP);
total_ue_count = 0;
// loop over all active UEs
for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
rnti = flexran_get_ue_crnti(Mod_id, i);
if(rnti == NOT_A_RNTI)
continue;
if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
continue;
UE_id = i;
if (flexran_slice_member(UE_id, slice_id) == 0)
continue;
// 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;
for (ii=0; ii < UE_num_active_CC(UE_list,UE_id); ii++) {
......@@ -628,6 +528,10 @@ void _dlsch_scheduler_pre_processor (module_id_t Mod_id,
ue_sched_ctl->max_allowed_rbs[CC_id]=nb_rbs_allowed_slice[CC_id][slice_id];
flexran_get_harq(Mod_id, CC_id, UE_id, frameP, subframeP, &harq_pid, &round);
// 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);
......@@ -669,6 +573,15 @@ 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;
if (flexran_slice_member(i, slice_id) == 0)
continue;
......@@ -733,9 +646,13 @@ void _dlsch_scheduler_pre_processor (module_id_t Mod_id,
// LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
if(rnti == NOT_A_RNTI)
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);
//rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
/* 1st allocate for the retx */
......@@ -1027,11 +944,11 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
int N_RBG[MAX_NUM_CCs];
unsigned char aggregation;
mac_rlc_status_resp_t rlc_status;
unsigned char header_len = 0, ta_len = 0;
unsigned char header_len = 0, header_len_last = 0, ta_len = 0;
uint16_t nb_rb, nb_rb_temp, total_nb_available_rb[MAX_NUM_CCs], nb_available_rb;
uint16_t TBS, j, rnti;
unsigned char round = 0;
unsigned char harq_pid = 0;
uint8_t round = 0;
uint8_t harq_pid = 0;
uint16_t sdu_length_total = 0;
int mcs, mcs_tmp;
uint16_t min_rb_unit[MAX_NUM_CCs];
......@@ -1043,7 +960,6 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
static int32_t tpc_accumulated=0;
UE_sched_ctrl *ue_sched_ctl;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
Protocol__FlexDlData *dl_data[NUM_MAX_UE];
int num_ues_added = 0;
int channels_added = 0;
......@@ -1059,17 +975,19 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
uint8_t ue_has_transmission = 0;
uint32_t ndi;
flexran_agent_mac_create_empty_dl_config(mod_id, dl_info);
#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);
//weight = get_ue_weight(module_idP,UE_id);
aggregation = 2; // set to the maximum aggregation level
aggregation = 1; // set to the maximum aggregation level
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
min_rb_unit[CC_id] = get_min_rb_unit(mod_id, CC_id);
......@@ -1106,8 +1024,9 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
if (mbsfn_flag[CC_id]>0)
continue;
for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
rnti = flexran_get_ue_crnti(mod_id, UE_id);
eNB_UE_stats = mac_xface->get_eNB_UE_stats(mod_id,CC_id,rnti);
ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
......@@ -1127,12 +1046,6 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
continue;
}
if (flexran_get_ue_crnti(mod_id, UE_id) == NOT_A_RNTI) {
LOG_D(MAC,"[eNB] Cannot find UE\n");
// mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
continue;
}
switch(mac_xface->get_transmission_mode(mod_id,CC_id,rnti)){
case 1:
case 2:
......@@ -1186,6 +1099,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
flexran_get_harq(mod_id, CC_id, UE_id, frame, subframe, &harq_pid, &round);
sdu_length_total=0;
mcs = cqi_to_mcs[flexran_get_ue_wcqi(mod_id, UE_id)];
// LOG_I(FLEXRAN_AGENT, "The MCS is %d\n", mcs);
mcs = cmin(mcs,flexran_slice_maxmcs(slice_id));
#ifdef EXMIMO
......@@ -1218,9 +1132,10 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
dl_dci->harq_process = harq_pid;
/* process retransmission */
if (round > 0) {
LOG_D(FLEXRAN_AGENT, "There was a retransmission just now and the round was %d\n", round);
if (flexran_get_duplex_mode(mod_id, CC_id) == PROTOCOL__FLEX_DUPLEX_MODE__FLDM_TDD) {
UE_list->UE_template[CC_id][UE_id].DAI++;
update_ul_dci(mod_id, CC_id, rnti, UE_list->UE_template[CC_id][UE_id].DAI);
......@@ -1291,15 +1206,16 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
//TBS = mac_xface->get_TBS(eNB_UE_stats->DL_cqi[0]<<1,nb_available_rb);
TBS = mac_xface->get_TBS_DL(mcs, nb_available_rb);
dci_tbs = TBS;
LOG_D(FLEXRAN_AGENT, "TBS is %d\n", TBS);
// check first for RLC data on DCCH
// add the length for all the control elements (timing adv, drx, etc) : header + payload
ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
ta_len = (ue_sched_ctl->ta_update != 0) ? 2 : 0;
dl_data[num_ues_added]->n_ce_bitmap = 2;
dl_data[num_ues_added]->ce_bitmap = (uint32_t *) malloc(sizeof(uint32_t) * 2);
dl_data[num_ues_added]->ce_bitmap = (uint32_t *) calloc(2, sizeof(uint32_t));
if (ta_len > 0) {
ce_flags |= PROTOCOL__FLEX_CE_TYPE__FLPCET_TA;
}
......@@ -1312,9 +1228,11 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
// TODO : Need to prioritize DRBs
// Loop through the UE logical channels (DCCH, DCCH1, DTCH for now)
header_len = 0;
header_len_last = 0;
sdu_length_total = 0;
for (j = 1; j < NB_RB_MAX; j++) {
header_len+=3;
header_len += 3;
// Need to see if we have space for data from this channel
if (dci_tbs - ta_len - header_len - sdu_length_total > 0) {
LOG_D(MAC, "[TEST]Requested %d bytes from RLC buffer on channel %d during first call\n", dci_tbs-ta_len-header_len);
......@@ -1326,15 +1244,19 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
ENB_FLAG_YES,
MBMS_FLAG_NO,
j,
(dci_tbs-ta_len-header_len)); // transport block set size
(dci_tbs - ta_len - header_len - sdu_length_total)); // transport block set size
//If data are available in channel j
if (rlc_status.bytes_in_buffer > 0) {
LOG_D(MAC, "[TEST]Have %d bytes in DCCH buffer during first call\n", rlc_status.bytes_in_buffer);
//Fill in as much as possible
data_to_request = cmin(dci_tbs-ta_len-header_len, rlc_status.bytes_in_buffer);
data_to_request = cmin(dci_tbs - ta_len - header_len - sdu_length_total, rlc_status.bytes_in_buffer);
LOG_D(FLEXRAN_AGENT, "Will request %d bytes from channel %d\n", data_to_request, j);
if (data_to_request < 128) { //The header will be one byte less
header_len--;
header_len_last = 2;
} else {
header_len_last = 3;
}
/* if (j == 1 || j == 2) {
data_to_request+=0;
......@@ -1374,17 +1296,29 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
dl_data[num_ues_added]->rlc_pdu[i] = rlc_pdus[i];
}
if (header_len == 0) {
LOG_D(FLEXRAN_AGENT, "Header was empty\n");
header_len_last = 0;
}
// there is a payload
if (( dl_data[num_ues_added]->n_rlc_pdu > 0)) {
if ((dl_data[num_ues_added]->n_rlc_pdu > 0)) {
// Now compute number of required RBs for total sdu length
// Assume RAH format 2
// adjust header lengths
if (header_len == 2 || header_len == 3) { //Only one SDU, remove length field
header_len = 1;
} else { //Remove length field from the last SDU
header_len--;
LOG_D(FLEXRAN_AGENT, "We have %d bytes to transfer\n", sdu_length_total);
if (header_len != 0) {
LOG_D(FLEXRAN_AGENT, "Header length was %d ", header_len);
header_len_last--;
header_len -= header_len_last;
LOG_D(FLEXRAN_AGENT, "so we resized it to %d\n", header_len);
}
/* if (header_len == 2 || header_len == 3) { //Only one SDU, remove length field */
/* header_len = 1; */
/* } else { //Remove length field from the last SDU */
/* header_len--; */
/* } */
mcs_tmp = mcs;
if (mcs_tmp == 0) {
......@@ -1458,7 +1392,8 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
dci_tbs = TBS;
mcs = mcs_tmp;
LOG_D(FLEXRAN_AGENT, "Final mcs was %d\n", mcs);
dl_dci->has_aggr_level = 1;
dl_dci->aggr_level = aggregation;
......@@ -1474,8 +1409,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
// do PUCCH power control
// this is the normalized RX power
normalized_rx_power = flexran_get_p0_pucch_dbm(mod_id,UE_id, CC_id); //eNB_UE_stats->Po_PUCCH_dBm;
target_rx_power = flexran_get_p0_nominal_pucch(mod_id, CC_id) + 10; //mac_xface->get_target_pucch_rx_power(mod_id, CC_id) + 10;
target_rx_power = flexran_get_p0_nominal_pucch(mod_id, CC_id) + 20; //mac_xface->get_target_pucch_rx_power(mod_id, CC_id) + 20;
// this assumes accumulated tpc
// make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
......@@ -1483,8 +1417,8 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
if (((framex10psubframe+10)<=(frame*10+subframe)) || //normal case
((framex10psubframe>(frame*10+subframe)) && (((10240-framex10psubframe+frame*10+subframe)>=10)))) //frame wrap-around
if (flexran_get_p0_pucch_status(mod_id, UE_id, CC_id) == 1) {
flexran_update_p0_pucch(mod_id, UE_id, CC_id);
flexran_update_p0_pucch(mod_id, UE_id, CC_id);
UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frame;
UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframe;
if (normalized_rx_power>(target_rx_power+1)) {
......
......@@ -68,7 +68,7 @@
/* 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 phy_stats_exist(module_id_t Mod_id, int rnti)
{
int CC_id;
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
......
......@@ -536,6 +536,7 @@ void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframe
void sort_ue_ul (module_id_t module_idP,int frameP, sub_frame_t subframeP);
void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subframeP,uint16_t *first_rb);
void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_template);
int phy_stats_exist(module_id_t Mod_id, int rnti);
/*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index)
\brief UE scheduler where all the ue background tasks are done. This function performs the following: 1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures.
......
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