diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index eba4bdcee9..d7efbeeeea 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -420,17 +420,8 @@ set_ul_DAI(int module_idP, //------------------------------------------------------------------------------ void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) { - int i = 0; - slice_info_t *sli = &RC.mac[module_idP]->slice_info; - memset(sli->rballoc_sub, 0, sizeof(sli->rballoc_sub)); - - for (i = 0; i < sli->n_dl; i++) { - // Run each enabled slice-specific schedulers one by one - sli->dl[i].sched_cb(module_idP, - i, - frameP, - subframeP, - mbsfn_flag/*, dl_info*/); + for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { + schedule_ue_spec(module_idP, CC_id, frameP, subframeP, mbsfn_flag); } } @@ -454,13 +445,12 @@ void getRepetition(UE_TEMPLATE *pue_template,unsigned int *maxRep, unsigned int */ void schedule_ue_spec(module_id_t module_idP, - int slice_idxP, + int CC_id, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) //------------------------------------------------------------------------------ { - int CC_id; int UE_id; int aggregation; mac_rlc_status_resp_t rlc_status; @@ -478,7 +468,6 @@ schedule_ue_spec(module_id_t module_idP, uint8_t ra_ii; eNB_UE_STATS *eNB_UE_stats = NULL; UE_TEMPLATE *ue_template = NULL; - eNB_STATS *eNB_stats = NULL; RRC_release_ctrl_t *release_ctrl = NULL; DLSCH_PDU *dlsch_pdu = NULL; RA_t *ra = NULL; @@ -491,11 +480,11 @@ schedule_ue_spec(module_id_t module_idP, int tpc = 1; UE_sched_ctrl_t *ue_sched_ctrl; int mcs; - int i; - int min_rb_unit[NFAPI_CC_MAX]; - int N_RB_DL[NFAPI_CC_MAX]; - int total_nb_available_rb[NFAPI_CC_MAX]; - int N_RBG[NFAPI_CC_MAX]; + const int min_rb_unit = get_min_rb_unit(module_idP, CC_id); + const int dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; + const int N_RB_DL = to_prb(dl_Bandwidth); + const int N_RBG = to_rbg(dl_Bandwidth); + int total_nb_available_rb = N_RB_DL; nfapi_dl_config_request_body_t *dl_req; nfapi_dl_config_request_pdu_t *dl_config_pdu; int tdd_sfa; @@ -503,22 +492,19 @@ schedule_ue_spec(module_id_t module_idP, int header_length_last; int header_length_total; rrc_eNB_ue_context_t *ue_contextP = NULL; - int nb_mac_CC = RC.nb_mac_CC[module_idP]; - long dl_Bandwidth; if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){ //LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP); return ; } - start_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN); // for TDD: check that we have to act here, otherwise return - if (cc[0].tdd_Config) { - tdd_sfa = cc[0].tdd_Config->subframeAssignment; + if (cc[CC_id].tdd_Config) { + tdd_sfa = cc[CC_id].tdd_Config->subframeAssignment; switch (subframeP) { case 0: @@ -567,33 +553,25 @@ schedule_ue_spec(module_id_t module_idP, aggregation = 2; - for (CC_id = 0, eNB_stats = &eNB->eNB_stats[0]; CC_id < nb_mac_CC; CC_id++, eNB_stats++) { - dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; - N_RB_DL[CC_id] = to_prb(dl_Bandwidth); - min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); - // get number of PRBs less those used by common channels - total_nb_available_rb[CC_id] = N_RB_DL[CC_id]; + for (int i = 0; i < N_RB_DL; i++) + if (cc[CC_id].vrb_map[i] != 0) + total_nb_available_rb--; - for (i = 0; i < N_RB_DL[CC_id]; i++) - if (cc[CC_id].vrb_map[i] != 0) - total_nb_available_rb[CC_id]--; - - N_RBG[CC_id] = to_rbg(dl_Bandwidth); - // store the global enb stats: - eNB_stats->num_dlactive_UEs = UE_list->num_UEs; - eNB_stats->available_prbs = total_nb_available_rb[CC_id]; - eNB_stats->total_available_prbs += total_nb_available_rb[CC_id]; - eNB_stats->dlsch_bytes_tx = 0; - eNB_stats->dlsch_pdus_tx = 0; - } + // store the global enb stats: + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb; + eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb; + eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; + eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0; // CALLING Pre_Processor for downlink scheduling // (Returns estimation of RBs required by each UE and the allocation on sub-band) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); + memset(eNB->slice_info.rballoc_sub, 0, sizeof(eNB->slice_info.rballoc_sub)); dlsch_scheduler_pre_processor(module_idP, - slice_idxP, + 0, //slice_idxP, frameP, subframeP, mbsfn_flag, @@ -610,1034 +588,1042 @@ schedule_ue_spec(module_id_t module_idP, /* the interslice multiplexing re-sorts the UE_list for the slices it tries * to multiplex, so we need to sort it for the current slice again */ sort_UEs(module_idP, - slice_idxP, + 0,//slice_idxP, frameP, subframeP); } - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", - CC_id); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", + CC_id); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - if (mbsfn_flag[CC_id] > 0) - continue; + //if (mbsfn_flag[CC_id] > 0) + // return; - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", - CC_id, - UE_id); - continue_flag = 0; // reset the flag to allow allocation for the remaining UEs - rnti = UE_RNTI(module_idP, UE_id); - ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; - ue_template = &UE_list->UE_template[CC_id][UE_id]; + for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", + CC_id, + UE_id); + continue_flag = 0; // reset the flag to allow allocation for the remaining UEs + rnti = UE_RNTI(module_idP, UE_id); + ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + ue_template = &UE_list->UE_template[CC_id][UE_id]; - if (ue_template->rach_resource_type > 0) { - continue_flag = 1; + if (ue_template->rach_resource_type > 0) { + continue_flag = 1; + } + + if (&(UE_list->eNB_UE_stats[CC_id][UE_id]) == NULL) { + LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); + continue_flag = 1; + } else { + eNB_UE_stats = &(UE_list->eNB_UE_stats[CC_id][UE_id]); + } + + if (continue_flag != 1) { + switch (get_tmode(module_idP, + CC_id, + UE_id)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format2A); + break; + + default: + AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); + aggregation = 2; + break; } + } - if (&(UE_list->eNB_UE_stats[CC_id][UE_id]) == NULL) { - LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); - continue_flag = 1; - } else { - eNB_UE_stats = &(UE_list->eNB_UE_stats[CC_id][UE_id]); - } - - if (continue_flag != 1) { - switch (get_tmode(module_idP, - CC_id, - UE_id)) { - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - break; - - case 3: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format2A); - break; - - default: - AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); - aggregation = 2; - break; - } - } - - /* if (continue_flag != 1 */ - if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0 || // no RBs allocated - CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - aggregation, - rnti)) { - LOG_D(MAC, "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - module_idP, - frameP, - UE_id, - CC_id); - continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 - } - - // If TDD - if (cc[CC_id].tdd_Config != NULL) { //TDD - set_ue_dai(subframeP, - UE_id, - CC_id, - cc[CC_id].tdd_Config->subframeAssignment, - UE_list); - // update UL DAI after DLSCH scheduling - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); - } - - if (continue_flag == 1) { - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_NONE, - rnti); - continue; - } - - nb_available_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, - frameP, - subframeP); - round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; - eNB_UE_stats->crnti = rnti; - eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); - eNB_UE_stats->harq_pid = harq_pid; - eNB_UE_stats->harq_round = round_DL; - - if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { - ue_sched_ctrl->uplane_inactivity_timer = 0; - } - - if (eNB_UE_stats->rrc_status < RRC_CONNECTED) { - LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); - continue; - } - - header_length_total = 0; - sdu_length_total = 0; - num_sdus = 0; - - /* - DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || - (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), - eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); - */ - if (NFAPI_MODE != NFAPI_MONOLITHIC) { - eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; - } else { // this operation is also done in the preprocessor - eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, - eNB->slice_info.dl[slice_idxP].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - } - - // Store stats - // eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi; - - // Initializing the rb allocation indicator for each UE - for (j = 0; j < N_RBG[CC_id]; j++) { - ue_template->rballoc_subband[harq_pid][j] = 0; - } - - LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", + /* if (continue_flag != 1 */ + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0 || // no RBs allocated + CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + aggregation, + rnti)) { + LOG_D(MAC, "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", module_idP, frameP, UE_id, - CC_id, - rnti, - harq_pid, - round_DL, - nb_available_rb, - ue_sched_ctrl->dl_cqi[CC_id], - eNB_UE_stats->dlsch_mcs1, - eNB_UE_stats->rrc_status); + CC_id); + continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 + } - /* Process retransmission */ - if (round_DL != 8) { - // get freq_allocation - nb_rb = ue_template->nb_rb[harq_pid]; - TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], - nb_rb); + // If TDD + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai(subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_list); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP, + UE_id, + CC_id, + frameP, + subframeP); + } - if (nb_rb <= nb_available_rb) { - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + if (continue_flag == 1) { + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_NONE, + rnti); + continue; + } - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + nb_available_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; + harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, + frameP, + subframeP); + round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; + eNB_UE_stats->crnti = rnti; + eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); + eNB_UE_stats->harq_pid = harq_pid; + eNB_UE_stats->harq_round = round_DL; - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } + if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { + ue_sched_ctrl->uplane_inactivity_timer = 0; + } + + if (eNB_UE_stats->rrc_status < RRC_CONNECTED) { + LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); + continue; + } + + header_length_total = 0; + sdu_length_total = 0; + num_sdus = 0; + + /* + DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || + (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), + eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); + */ + if (NFAPI_MODE != NFAPI_MONOLITHIC) { + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; + } else { // this operation is also done in the preprocessor + eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, + eNB->slice_info.dl[0/*slice_idxP*/].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + } + + // Store stats + // eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi; + + // Initializing the rb allocation indicator for each UE + for (j = 0; j < N_RBG; j++) { + ue_template->rballoc_subband[harq_pid][j] = 0; + } + + LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", + module_idP, + frameP, + UE_id, + CC_id, + rnti, + harq_pid, + round_DL, + nb_available_rb, + ue_sched_ctrl->dl_cqi[CC_id], + eNB_UE_stats->dlsch_mcs1, + eNB_UE_stats->rrc_status); + + /* Process retransmission */ + if (round_DL != 8) { + // get freq_allocation + nb_rb = ue_template->nb_rb[harq_pid]; + TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], + nb_rb); + + if (nb_rb <= nb_available_rb) { + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); } + } - if (cc[CC_id].tdd_Config != NULL) { - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); - LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", - CC_id, - subframeP, - UE_id, - ue_template->DAI); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - if (ue_template->rballoc_subband[harq_pid][j]) - LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - nb_rb_temp -= min_rb_unit[CC_id]; - - if ((j == N_RBG[CC_id] - 1) && (N_RB_DL[CC_id] == 25 || N_RB_DL[CC_id] == 50)) - nb_rb_temp++; - } - - j++; - } - } - - nb_available_rb -= nb_rb; - - switch (get_tmode(module_idP, CC_id, UE_id)) { - case 1: - case 2: - case 7: - default: - LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", - rnti); - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; - - // TDD - if (cc[CC_id].tdd_Config != NULL) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->DAI - 1, - ue_template->oldmcs1[harq_pid]); - } else { - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->oldmcs1[harq_pid]); - } - - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(eNB, - dl_req, - TBS, - -1, // retransmission, no pdu_index - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(ue_template->oldmcs1[harq_pid]), - round_DL & 3, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", - eNB->pdu_index[CC_id], - round_DL); - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - // No TX request for retransmission (check if null request for FAPI) - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", - frameP, - subframeP, - UE_id, - rnti); - } - } - - add_ue_dlsch_info(module_idP, - CC_id, UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); - //eNB_UE_stats->dlsch_trials[round]++; - eNB_UE_stats->num_retransmission += 1; - eNB_UE_stats->rbs_used_retx = nb_rb; - eNB_UE_stats->total_rbs_used_retx += nb_rb; - eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; - } else { - LOG_D(MAC, - "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", - module_idP, - frameP, + if (cc[CC_id].tdd_Config != NULL) { + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id, - UE_id); + subframeP, + UE_id, + ue_template->DAI); } - } else { - /* This is a potentially new SDU opportunity */ - rlc_status.bytes_in_buffer = 0; - // Now check RLC information to compute number of required RBs - // get maximum TBS size for RLC request - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - // add the length for all the control elements (timing adv, drx, etc) : header + payload - - if (ue_sched_ctrl->ta_timer == 0) { - ta_update = ue_sched_ctrl->ta_update; - - /* if we send TA then set timer to not send it for a while */ - if (ta_update != 31) { - ue_sched_ctrl->ta_timer = 20; + if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < N_RBG; j++) { // for indicating the rballoc for each sub-band + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; } - - /* reset ta_update */ - ue_sched_ctrl->ta_update = 31; } else { - ta_update = 31; - } + nb_rb_temp = nb_rb; + j = 0; - ta_len = (ta_update != 31) ? 2 : 0; + while ((nb_rb_temp > 0) && (j < N_RBG)) { + if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { + if (ue_template->rballoc_subband[harq_pid][j]) + LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - // RLC data on DCCH - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - sdu_lengths[0] = 0; + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; + nb_rb_temp -= min_rb_unit; - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, - frameP, - subframeP, - CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[0] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS, //not used - (char *)&dlsch_buffer[0], 0, 0 - ); - - if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { - while(pthread_mutex_trylock(&rrc_release_freelist)) { - /* spin... */ - } - - uint16_t release_total = 0; - - for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; - release_num < NUMBER_OF_UE_MAX; - release_num++, release_ctrl++) { - if(release_ctrl->flag > 0) { - release_total++; - } else { - continue; - } - - if(release_ctrl->flag == 1) { - if(release_ctrl->rnti == rnti) { - for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 3; - LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_ctrl->flag == 2) { - if(release_ctrl->rnti == rnti) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 4; - LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_total >= rrc_release_info.num_UEs) - break; - } - - pthread_mutex_unlock(&rrc_release_freelist); + if ((j == N_RBG - 1) && (N_RB_DL == 25 || N_RB_DL == 50)) + nb_rb_temp++; } - for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { - if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { - ra->crnti_harq_pid = harq_pid; - ra->state = MSGCRNTI_ACK; - break; - } - } - } - } - - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH), - T_INT(sdu_lengths[0])); - LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", - module_idP, - CC_id, - sdu_lengths[0]); - sdu_length_total = sdu_lengths[0]; - sdu_lcids[0] = DCCH; - eNB_UE_stats->lcid_sdu[0] = DCCH; - eNB_UE_stats->sdu_length_tx[DCCH] = sdu_lengths[0]; - eNB_UE_stats->num_pdu_tx[DCCH] += 1; - eNB_UE_stats->num_bytes_tx[DCCH] += sdu_lengths[0]; - header_length_last = 1 + 1 + (sdu_lengths[0] >= 128); - header_length_total += header_length_last; - num_sdus = 1; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[0]); - - for (j = 0; j < sdu_lengths[0]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); - } - - LOG_T(MAC, "\n"); -#endif + j++; } } - // RLC data on DCCH1 - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH + 1, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - // DCCH SDU - sdu_lengths[num_sdus] = 0; + nb_available_rb -= nb_rb; - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, frameP, CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, DCCH + 1, - TBS, //not used - (char *) &dlsch_buffer[sdu_length_total], 0, 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH + 1), - T_INT(sdu_lengths[num_sdus])); - sdu_lcids[num_sdus] = DCCH1; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->lcid_sdu[num_sdus] = DCCH1; - eNB_UE_stats->sdu_length_tx[DCCH1] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[DCCH1] += 1; - eNB_UE_stats->num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH1] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[num_sdus]); + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + default: + LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", + rnti); + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, + 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; - for (j = 0; j < sdu_lengths[num_sdus]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); + // TDD + if (cc[CC_id].tdd_Config != NULL) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + round_DL, + ue_template->DAI - 1, + ue_template->oldmcs1[harq_pid]); + } else { + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + round_DL, + ue_template->oldmcs1[harq_pid]); } - LOG_T(MAC, "\n"); -#endif - } + if (!CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, + rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + fill_nfapi_dlsch_config(eNB, + dl_req, + TBS, + -1, // retransmission, no pdu_index + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + 0, // resource_block_coding, to be filled in later + getQm(ue_template->oldmcs1[harq_pid]), + round_DL & 3, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", + eNB->pdu_index[CC_id], + round_DL); + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + // No TX request for retransmission (check if null request for FAPI) + } else { + LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", + frameP, + subframeP, + UE_id, + rnti); + } } - // TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list). - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - // TODO: check if the lcid is active - LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + add_ue_dlsch_info(module_idP, + CC_id, UE_id, + subframeP, + S_DL_SCHEDULED, + rnti); + //eNB_UE_stats->dlsch_trials[round]++; + eNB_UE_stats->num_retransmission += 1; + eNB_UE_stats->rbs_used_retx = nb_rb; + eNB_UE_stats->total_rbs_used_retx += nb_rb; + eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; + } else { + LOG_D(MAC, + "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", + module_idP, + frameP, + CC_id, + UE_id); + } + } else { + /* This is a potentially new SDU opportunity */ + rlc_status.bytes_in_buffer = 0; + // Now check RLC information to compute number of required RBs + // get maximum TBS size for RLC request + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_available_rb); + + // add the length for all the control elements (timing adv, drx, etc) : header + payload + + if (ue_sched_ctrl->ta_timer == 0) { + ta_update = ue_sched_ctrl->ta_update; + + /* if we send TA then set timer to not send it for a while */ + if (ta_update != 31) { + ue_sched_ctrl->ta_timer = 20; + } + + /* reset ta_update */ + ue_sched_ctrl->ta_update = 31; + } else { + ta_update = 31; + } + + ta_len = (ta_update != 31) ? 2 : 0; + + // RLC data on DCCH + if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DCCH, + TBS - ta_len - header_length_total - sdu_length_total - 3, + 0, + 0 + ); + sdu_lengths[0] = 0; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, - lcid, - TBS, + subframeP, + CC_id, TBS - ta_len - header_length_total - sdu_length_total - 3); - - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, + sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, - subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, - lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 + DCCH, + TBS, //not used + (char *)&dlsch_buffer[0], + 0, + 0 ); - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", - module_idP, - frameP, - TBS - ta_len - header_length_total - sdu_length_total - 3, - lcid, - header_length_total); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS, //not used - (char *) &dlsch_buffer[sdu_length_total], 0, 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(lcid), - T_INT(sdu_lengths[num_sdus])); - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", - module_idP, - sdu_lengths[num_sdus], - lcid); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[lcid]++; - eNB_UE_stats->lcid_sdu[num_sdus] = lcid; - eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; - ue_sched_ctrl->uplane_inactivity_timer = 0; - // reset RRC inactivity timer after uplane activity - ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); + if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { + while(pthread_mutex_trylock(&rrc_release_freelist)) { + /* spin... */ + } - if (ue_contextP != NULL) { - ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; + uint16_t release_total = 0; + + for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; + release_num < NUMBER_OF_UE_MAX; + release_num++, release_ctrl++) { + if(release_ctrl->flag > 0) { + release_total++; } else { - LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", - module_idP, - CC_id, - rnti); + continue; } - } // end if (rlc_status.bytes_in_buffer > 0) - } else { // no TBS left - break; // break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) - } - } - /* Last header does not have length field */ - if (header_length_total) { - header_length_total -= header_length_last; - header_length_total++; - } - - // there is at least one SDU or TA command - // if (num_sdus > 0 ){ - if (ta_len + sdu_length_total + header_length_total > 0) { - // Now compute number of required RBs for total sdu length - // Assume RAH format 2 - mcs = eNB_UE_stats->dlsch_mcs1; - - if (mcs == 0) { - nb_rb = 4; // don't let the TBS get too small - } else { - nb_rb = min_rb_unit[CC_id]; - } - - TBS = get_TBS_DL(mcs, nb_rb); - - while (TBS < sdu_length_total + header_length_total + ta_len) { - nb_rb += min_rb_unit[CC_id]; // - - if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs - // (can happen if N_RB_DL is odd) - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - nb_rb = nb_available_rb; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_rb); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG[CC_id]; ++j) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - - if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || (N_RB_DL[CC_id] == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; + if(release_ctrl->flag == 1) { + if(release_ctrl->rnti == rnti) { + for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 3; + LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", + release_num, + rnti, + rlc_am_mui.rrc_mui[mui_num], + mui_num); + break; + } + } } } - j++; + if(release_ctrl->flag == 2) { + if(release_ctrl->rnti == rnti) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 4; + LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", + release_num, + rnti, + rlc_am_mui.rrc_mui[mui_num], + mui_num); + break; + } + } + } + } + + if(release_total >= rrc_release_info.num_UEs) + break; + } + + pthread_mutex_unlock(&rrc_release_freelist); + } + + for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { + if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { + ra->crnti_harq_pid = harq_pid; + ra->state = MSGCRNTI_ACK; + break; + } + } } } - // decrease mcs until TBS falls below required length - while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { - mcs--; - TBS = get_TBS_DL(mcs, - nb_rb); - } - - // if we have decreased too much or we don't have enough RBs, increase MCS - while (TBS < sdu_length_total + header_length_total + ta_len && - ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { - mcs++; - TBS = get_TBS_DL(mcs, - nb_rb); - } - - LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d)\n", - eNB_UE_stats->dlsch_mcs1, - mcs); -#ifdef DEBUG_eNB_SCHEDULER - LOG_D(MAC, "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", - module_idP, - CC_id, - mcs, TBS, - nb_rb); - // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", - // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); -#endif - - if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { - padding = TBS - header_length_total - sdu_length_total - ta_len; - post_padding = 0; - } else { - padding = 0; - post_padding = 1; - } - - offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - num_sdus, //num_sdus - sdu_lengths, // - sdu_lcids, - 255, // no drx - ta_update, // timing advance - NULL, // contention res id - padding, - post_padding); - - //#ifdef DEBUG_eNB_SCHEDULER - if (ta_update != 31) { - LOG_D(MAC, - "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n", - module_idP, - frameP, - UE_id, - CC_id, - sdu_length_total, - num_sdus, - sdu_lengths[0], - sdu_lcids[0], - offset, - ta_update, - padding, - post_padding, - mcs, - TBS, - nb_rb, - header_length_total); - } - - //#endif -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); - - for (i = 0; i < 16; i++) { - LOG_T(MAC, "%x.", - dlsch_buffer[i]); - } - - LOG_T(MAC, "\n"); -#endif - // cycle through SDUs and place in dlsch_buffer - dlsch_pdu = &UE_list->DLSCH_pdu[CC_id][0][UE_id]; - memcpy(&dlsch_pdu->payload[0][offset], - dlsch_buffer, - sdu_length_total); - // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); - - // fill remainder of DLSCH with 0 - for (j = 0; j < (TBS - sdu_length_total - offset); j++) { - dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; - } - - trace_pdu(DIRECTION_DOWNLINK, - (uint8_t *) dlsch_pdu->payload[0], - TBS, - module_idP, - WS_C_RNTI, - UE_RNTI(module_idP, - UE_id), - eNB->frame, - eNB->subframe, - 0, - 0); - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, + T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), - T_BUFFER(dlsch_pdu->payload[0], - TBS)); - ue_template->nb_rb[harq_pid] = nb_rb; - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); - // store stats - eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; - eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; - eNB_UE_stats->rbs_used = nb_rb; - eNB_UE_stats->num_mac_sdu_tx = num_sdus; - eNB_UE_stats->total_rbs_used += nb_rb; - eNB_UE_stats->dlsch_mcs2 = mcs; - eNB_UE_stats->TBS = TBS; - eNB_UE_stats->overhead_bytes = TBS - sdu_length_total; - eNB_UE_stats->total_sdu_bytes += sdu_length_total; - eNB_UE_stats->total_pdu_bytes += TBS; - eNB_UE_stats->total_num_pdus += 1; + T_INT(DCCH), + T_INT(sdu_lengths[0])); + LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", + module_idP, + CC_id, + sdu_lengths[0]); + sdu_length_total = sdu_lengths[0]; + sdu_lcids[0] = DCCH; + eNB_UE_stats->lcid_sdu[0] = DCCH; + eNB_UE_stats->sdu_length_tx[DCCH] = sdu_lengths[0]; + eNB_UE_stats->num_pdu_tx[DCCH] += 1; + eNB_UE_stats->num_bytes_tx[DCCH] += sdu_lengths[0]; + header_length_last = 1 + 1 + (sdu_lengths[0] >= 128); + header_length_total += header_length_last; + num_sdus = 1; +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes :", + module_idP, + CC_id, + sdu_lengths[0]); - if (cc[CC_id].tdd_Config != NULL) { // TDD - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); + for (j = 0; j < sdu_lengths[0]; ++j) { + LOG_T(MAC, "%x ", + dlsch_buffer[j]); } - // do PUCCH power control - // this is the snr - // unit is not dBm, it's special from nfapi - // converting to dBm - snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; - target_snr = eNB->puCch10xSnr / 10; - // 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_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; - - if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case - (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) //frame wrap-around - if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { - ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; - ue_template->pucch_tpc_tx_frame = frameP; - ue_template->pucch_tpc_tx_subframe = subframeP; - - if (snr > target_snr + 4) { - tpc = 0; //-1 - } else if (snr < target_snr - 4) { - tpc = 2; //+1 - } else { - tpc = 1; //0 - } - - LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", - module_idP, - frameP, - subframeP, - harq_pid, - tpc, - snr, - target_snr); - } // Po_PUCCH has been updated - else { - tpc = 1; //0 - } // time to do TPC update - else { - tpc = 1; //0 - } - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1 - ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - //deactivate second codeword - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; - - if (cc[CC_id].tdd_Config != NULL) { //TDD - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - (ue_template->DAI - 1), - mcs); - } else { - LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - mcs); - } - - LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", - dl_req->number_pdu); - - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - ue_sched_ctrl->round[CC_id][harq_pid] = 0; - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer - - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); - - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } - } - - // Toggle NDI for next time - LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", - CC_id, - frameP, - subframeP, - UE_id, - rnti, - harq_pid, - ue_template->oldNDI[harq_pid]); - ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; - ue_template->oldmcs1[harq_pid] = mcs; - ue_template->oldmcs2[harq_pid] = 0; - AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); - AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, - "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(eNB, - dl_req, - TBS, - eNB->pdu_index[CC_id], - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(mcs), - 0, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, - (frameP * 10) + subframeP, - TBS, - eNB->pdu_index[CC_id], - dlsch_pdu->payload[0]); - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", - eNB->pdu_index[CC_id]); - eNB->pdu_index[CC_id]++; - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", - frameP, - subframeP, - UE_id, - rnti); - } - } else { // There is no data from RLC or MAC header, so don't schedule + LOG_T(MAC, "\n"); +#endif } } - if (cc[CC_id].tdd_Config != NULL) { // TDD - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); + // RLC data on DCCH1 + if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DCCH + 1, + TBS - ta_len - header_length_total - sdu_length_total - 3, + 0, + 0 + ); + // DCCH SDU + sdu_lengths[num_sdus] = 0; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + module_idP, frameP, CC_id, + TBS - ta_len - header_length_total - sdu_length_total - 3); + sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, DCCH + 1, + TBS, //not used + (char *) &dlsch_buffer[sdu_length_total], + 0, + 0 + ); + T(T_ENB_MAC_UE_DL_SDU, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(DCCH + 1), + T_INT(sdu_lengths[num_sdus])); + sdu_lcids[num_sdus] = DCCH1; + sdu_length_total += sdu_lengths[num_sdus]; + eNB_UE_stats->lcid_sdu[num_sdus] = DCCH1; + eNB_UE_stats->sdu_length_tx[DCCH1] = sdu_lengths[num_sdus]; + eNB_UE_stats->num_pdu_tx[DCCH1] += 1; + eNB_UE_stats->num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + num_sdus++; +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d][DCCH1] CC_id %d Got %d bytes :", + module_idP, + CC_id, + sdu_lengths[num_sdus]); + + for (j = 0; j < sdu_lengths[num_sdus]; ++j) { + LOG_T(MAC, "%x ", + dlsch_buffer[j]); + } + + LOG_T(MAC, "\n"); +#endif + } } - } // UE_id loop - } // CC_id loop + + // TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list). + for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { + // TODO: check if the lcid is active + LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + module_idP, + frameP, + lcid, + TBS, + TBS - ta_len - header_length_total - sdu_length_total - 3); + + if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 + ); + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", + module_idP, + frameP, + TBS - ta_len - header_length_total - sdu_length_total - 3, + lcid, + header_length_total); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS, //not used + (char *) &dlsch_buffer[sdu_length_total], + 0, + 0 + ); + T(T_ENB_MAC_UE_DL_SDU, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(lcid), + T_INT(sdu_lengths[num_sdus])); + LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", + module_idP, + sdu_lengths[num_sdus], + lcid); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + eNB_UE_stats->num_pdu_tx[lcid]++; + eNB_UE_stats->lcid_sdu[num_sdus] = lcid; + eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; + eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + num_sdus++; + ue_sched_ctrl->uplane_inactivity_timer = 0; + // reset RRC inactivity timer after uplane activity + ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); + + if (ue_contextP != NULL) { + ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; + } else { + LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", + module_idP, + CC_id, + rnti); + } + } // end if (rlc_status.bytes_in_buffer > 0) + } else { // no TBS left + break; // break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) + } + } + + /* Last header does not have length field */ + if (header_length_total) { + header_length_total -= header_length_last; + header_length_total++; + } + + // there is at least one SDU or TA command + // if (num_sdus > 0 ){ + if (ta_len + sdu_length_total + header_length_total > 0) { + // Now compute number of required RBs for total sdu length + // Assume RAH format 2 + mcs = eNB_UE_stats->dlsch_mcs1; + + if (mcs == 0) { + nb_rb = 4; // don't let the TBS get too small + } else { + nb_rb = min_rb_unit; + } + + TBS = get_TBS_DL(mcs, nb_rb); + + while (TBS < sdu_length_total + header_length_total + ta_len) { + nb_rb += min_rb_unit; // + + if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs + // (can happen if N_RB_DL is odd) + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_available_rb); + nb_rb = nb_available_rb; + break; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_rb); + } + + if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < N_RBG; ++j) { // for indicating the rballoc for each sub-band + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; + } + } else { + nb_rb_temp = nb_rb; + j = 0; + + while ((nb_rb_temp > 0) && (j < N_RBG)) { + if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; + + if ((j == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { + nb_rb_temp = nb_rb_temp - min_rb_unit + 1; + } else { + nb_rb_temp = nb_rb_temp - min_rb_unit; + } + } + + j++; + } + } + + // decrease mcs until TBS falls below required length + while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { + mcs--; + TBS = get_TBS_DL(mcs, + nb_rb); + } + + // if we have decreased too much or we don't have enough RBs, increase MCS + while (TBS < sdu_length_total + header_length_total + ta_len && + ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { + mcs++; + TBS = get_TBS_DL(mcs, + nb_rb); + } + + LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d)\n", + eNB_UE_stats->dlsch_mcs1, + mcs); +#ifdef DEBUG_eNB_SCHEDULER + LOG_D(MAC, "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", + module_idP, + CC_id, + mcs, TBS, + nb_rb); + // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", + // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); +#endif + + if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { + padding = TBS - header_length_total - sdu_length_total - ta_len; + post_padding = 0; + } else { + padding = 0; + post_padding = 1; + } + + offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, + 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, + post_padding); + + //#ifdef DEBUG_eNB_SCHEDULER + if (ta_update != 31) { + LOG_D(MAC, + "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n", + module_idP, + frameP, + UE_id, + CC_id, + sdu_length_total, + num_sdus, + sdu_lengths[0], + sdu_lcids[0], + offset, + ta_update, + padding, + post_padding, + mcs, + TBS, + nb_rb, + header_length_total); + } + + //#endif +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); + + for (int i = 0; i < 16; i++) { + LOG_T(MAC, "%x.", + dlsch_buffer[i]); + } + + LOG_T(MAC, "\n"); +#endif + // cycle through SDUs and place in dlsch_buffer + dlsch_pdu = &UE_list->DLSCH_pdu[CC_id][0][UE_id]; + memcpy(&dlsch_pdu->payload[0][offset], + dlsch_buffer, + sdu_length_total); + // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); + + // fill remainder of DLSCH with 0 + for (j = 0; j < (TBS - sdu_length_total - offset); j++) { + dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; + } + + trace_pdu(DIRECTION_DOWNLINK, + (uint8_t *) dlsch_pdu->payload[0], + TBS, + module_idP, + WS_C_RNTI, + UE_RNTI(module_idP, + UE_id), + eNB->frame, + eNB->subframe, + 0, + 0); + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_BUFFER(dlsch_pdu->payload[0], + TBS)); + ue_template->nb_rb[harq_pid] = nb_rb; + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_SCHEDULED, + rnti); + // store stats + eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; + eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; + eNB_UE_stats->rbs_used = nb_rb; + eNB_UE_stats->num_mac_sdu_tx = num_sdus; + eNB_UE_stats->total_rbs_used += nb_rb; + eNB_UE_stats->dlsch_mcs2 = mcs; + eNB_UE_stats->TBS = TBS; + eNB_UE_stats->overhead_bytes = TBS - sdu_length_total; + eNB_UE_stats->total_sdu_bytes += sdu_length_total; + eNB_UE_stats->total_pdu_bytes += TBS; + eNB_UE_stats->total_num_pdus += 1; + + if (cc[CC_id].tdd_Config != NULL) { // TDD + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + } + + // do PUCCH power control + // this is the snr + // unit is not dBm, it's special from nfapi + // converting to dBm + snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; + target_snr = eNB->puCch10xSnr / 10; + // 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_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; + + if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case + (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) //frame wrap-around + if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { + ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; + ue_template->pucch_tpc_tx_frame = frameP; + ue_template->pucch_tpc_tx_subframe = subframeP; + + if (snr > target_snr + 4) { + tpc = 0; //-1 + } else if (snr < target_snr - 4) { + tpc = 2; //+1 + } else { + tpc = 1; //0 + } + + LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", + module_idP, + frameP, + subframeP, + harq_pid, + tpc, + snr, + target_snr); + } // Po_PUCCH has been updated + else { + tpc = 1; //0 + } // time to do TPC update + else { + tpc = 1; //0 + } + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, + 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1 - ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + //deactivate second codeword + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; + + if (cc[CC_id].tdd_Config != NULL) { //TDD + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; + LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + (ue_template->DAI - 1), + mcs); + } else { + LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + mcs); + } + + LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", + dl_req->number_pdu); + + if (!CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, + rnti)) { + ue_sched_ctrl->round[CC_id][harq_pid] = 0; + dl_req->number_dci++; + dl_req->number_pdu++; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); + + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); + } + } + + // Toggle NDI for next time + LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", + CC_id, + frameP, + subframeP, + UE_id, + rnti, + harq_pid, + ue_template->oldNDI[harq_pid]); + ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; + ue_template->oldmcs1[harq_pid] = mcs; + ue_template->oldmcs2[harq_pid] = 0; + AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); + AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, + "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + fill_nfapi_dlsch_config(eNB, + dl_req, + TBS, + eNB->pdu_index[CC_id], + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + 0, // resource_block_coding, to be filled in later + getQm(mcs), + 0, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, + (frameP * 10) + subframeP, + TBS, + eNB->pdu_index[CC_id], + dlsch_pdu->payload[0]); + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", + eNB->pdu_index[CC_id]); + eNB->pdu_index[CC_id]++; + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + } else { + LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", + frameP, + subframeP, + UE_id, + rnti); + } + } else { // There is no data from RLC or MAC header, so don't schedule + } + } + + if (cc[CC_id].tdd_Config != NULL) { // TDD + set_ul_DAI(module_idP, + UE_id, + CC_id, + frameP, + subframeP); + } + } // UE_id loop fill_DLSCH_dci(module_idP, frameP, diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 476fb68584..23aa03ca8b 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -156,8 +156,11 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, int *mbsfn_flag); -void schedule_ue_spec(module_id_t module_idP, int slice_idxP, - frame_t frameP,sub_frame_t subframe, int *mbsfn_flag); +void schedule_ue_spec(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframe, + int *mbsfn_flag); void schedule_ue_spec_br(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);