diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 3b502167ef4d57bb2a0993791186129715d4bd50..fce11235a1d353bf72aa7d0c1cb0b235efc76efa 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1234,12 +1234,16 @@ schedule_ulsch(module_id_t module_idP, /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++, cc++) { - first_rb[CC_id] = 1; // leave out first RB for PUCCH - #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) first_rb[CC_id] = (emtc_active[CC_id] == 1) ? 7 : 1; #else - first_rb[CC_id] = 1; + /* Note: the size of PUCCH is arbitrary, to be done properly. */ + switch (RC.eNB[module_idP][CC_id]->frame_parms.N_RB_DL) { + case 25: first_rb[CC_id] = 1; break; // leave out first RB for PUCCH + case 50: first_rb[CC_id] = 2; break; // leave out first RB for PUCCH + case 100: first_rb[CC_id] = 3; break; // leave out first RB for PUCCH + default: LOG_E(MAC, "nb RBs not handled, todo.\n"); exit(1); + } #endif RA_t *ra_ptr = cc->ra; @@ -1351,6 +1355,7 @@ schedule_ulsch_rnti(module_id_t module_idP, if (sched_subframeP < subframeP) { sched_frame++; + sched_frame %= 1024; } /* NFAPI struct init */ @@ -1366,6 +1371,21 @@ schedule_ulsch_rnti(module_id_t module_idP, /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { n_rb_ul_tab[CC_id] = to_prb(cc[CC_id].ul_Bandwidth); // return total number of PRB + /* HACK: let's remove the PUCCH from available RBs + * we suppose PUCCH size is: + * - for 25 RBs: 1 RB (top and bottom of ressource grid) + * - for 50: 2 RBs + * - for 100: 3 RBs + * This is totally arbitrary and might even be wrong. + * We suppose 'first_rb[]' has been correctly populated by the caller, + * so we only remove the top part of the resource grid. + */ + switch (n_rb_ul_tab[CC_id]) { + case 25: n_rb_ul_tab[CC_id] -= 1; break; + case 50: n_rb_ul_tab[CC_id] -= 2; break; + case 100: n_rb_ul_tab[CC_id] -= 3; break; + default: LOG_E(MAC, "RBs setting not handled. Todo.\n"); exit(1); + } UE_list->first_rb_offset[CC_id][slice_idx] = cmin(n_rb_ul_tab[CC_id], sli->ul[slice_idx].first_rb); } @@ -1374,7 +1394,7 @@ schedule_ulsch_rnti(module_id_t module_idP, * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_subframeP, first_rb); + ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_frame, sched_subframeP, first_rb); for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { first_rb_slice[CC_id] = first_rb[CC_id] + UE_list->first_rb_offset[CC_id][slice_idx]; @@ -1467,7 +1487,7 @@ schedule_ulsch_rnti(module_id_t module_idP, /* New transmission */ if (round_index == 0) { /* Be sure that there are some free RBs */ - if (first_rb_slice[CC_id] >= n_rb_ul_tab[CC_id] - 1) { + if (first_rb_slice[CC_id] >= n_rb_ul_tab[CC_id]) { LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", module_idP, frameP, @@ -1903,7 +1923,20 @@ schedule_ulsch_rnti(module_id_t module_idP, sched_frame, sched_subframeP, cqi_req); - } // end of round > 0 + + /* HACK: RBs used by retransmission have to be reserved. + * The current mechanism uses the notion of 'first_rb', so + * we skip all RBs below the ones retransmitted. This is + * not correct. Imagine only RB 23 is retransmitted, then all + * RBs < 23 will be marked unusable for new transmissions (case where round == 0). + * Note also that this code works only if the preprocessor orders + * UEs with retransmission with higher priority than UEs with new + * transmission. + * All this should be cleaned up properly. + */ + if (first_rb_slice[CC_id] < UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]) + first_rb_slice[CC_id] = UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]; + } // end of round > 0 } // UE_is_to_be_scheduled } // loop over all active CC_ids } // loop over UE_ids diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 8943a21d60ae6d349610c63fab4991a76db11945..e902065ad1dbed1dead166628bd72a1c6854475b 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -711,8 +711,6 @@ int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP); void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]); -int maxround(module_id_t Mod_id, uint16_t rnti, int frame, - sub_frame_t subframe, uint8_t ul_flag); void swap_UEs(UE_list_t * listP, int nodeiP, int nodejP, int ul_flag); int prev(UE_list_t * listP, int nodeP, int ul_flag); void dump_ue_list(UE_list_t * listP, int ul_flag); @@ -730,11 +728,11 @@ void set_ul_DAI(int module_idP, void ulsch_scheduler_pre_processor(module_id_t module_idP, int slice_idx, int frameP, sub_frame_t subframeP, + int sched_frameP, unsigned char sched_subframeP, uint16_t * first_rb); void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP); -void sort_ue_ul(module_id_t module_idP, int slice_idx, int frameP, sub_frame_t subframeP, rnti_t *rntiTable); void assign_max_mcs_min_rb(module_id_t module_idP, int slice_idx, int frameP, sub_frame_t subframeP, uint16_t * first_rb); void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index b14b7eab65da3c23c9cb5f2031ab20b67ad63455..292eecbb2894ef88a9d5f36840e78d31df73af4f 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -56,6 +56,13 @@ extern RAN_CONTEXT_t RC; //#define ICIC 0 +void +sort_ue_ul(module_id_t module_idP, + int slice_idx, + int sched_frameP, + sub_frame_t sched_subframeP, + rnti_t *rntiTable); + /* this function checks that get_eNB_UE_stats returns * a non-NULL pointer for all the active CCs of an UE */ @@ -264,7 +271,7 @@ assign_rbs_required(module_id_t Mod_id, // 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) { + sub_frame_t subframe) { uint8_t round, round_max = 0, UE_id; int CC_id, harq_pid; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; @@ -284,6 +291,28 @@ maxround(module_id_t Mod_id, uint16_t rnti, int frame, return round_max; } +int +maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, + sub_frame_t sched_subframe) { + uint8_t round, round_max = 0, UE_id; + int CC_id, harq_pid; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + COMMON_channels_t *cc; + + for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { + cc = &RC.mac[Mod_id]->common_channels[CC_id]; + UE_id = find_UE_id(Mod_id, rnti); + harq_pid = subframe2harqpid(cc, sched_frame, sched_subframe); + round = UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; + + 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 // it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL) int maxcqi(module_id_t Mod_id, int32_t UE_id) { @@ -332,10 +361,10 @@ static int ue_dl_compare(const void *_a, const void *_b, void *_params) { int UE_id2 = *(const int *) _b; int rnti1 = UE_RNTI(params->Mod_idP, UE_id1); int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1); - int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP, 1); + int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP); int rnti2 = UE_RNTI(params->Mod_idP, UE_id2); int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2); - int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP, 1); + int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP); int cqi1 = maxcqi(params->Mod_idP, UE_id1); int cqi2 = maxcqi(params->Mod_idP, UE_id2); long lcgid1 = min_lcgidpriority(params->Mod_idP, UE_id1); @@ -1626,6 +1655,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int slice_idx, int frameP, sub_frame_t subframeP, + int sched_frameP, unsigned char sched_subframeP, uint16_t *first_rb) { int UE_id; @@ -1646,7 +1676,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, // sort ues LOG_D(MAC, "In ulsch_preprocessor: sort ue \n"); - sort_ue_ul(module_idP, slice_idx, frameP, subframeP, rntiTable); + sort_ue_ul(module_idP, slice_idx, sched_frameP, sched_subframeP, rntiTable); // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); assign_max_mcs_min_rb(module_idP, slice_idx, frameP, subframeP, first_rb); @@ -1741,7 +1771,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, CC_id = UE_list->ordered_ULCCids[n][UE_id]; UE_template = &UE_list->UE_template[CC_id][UE_id]; harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], - frameP, sched_subframeP); + sched_frameP, sched_subframeP); // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); @@ -1924,8 +1954,8 @@ assign_max_mcs_min_rb(module_id_t module_idP, struct sort_ue_ul_params { int module_idP; - int frameP; - int subframeP; + int sched_frameP; + int sched_subframeP; }; static int ue_ul_compare(const void *_a, const void *_b, void *_params) { @@ -1935,12 +1965,12 @@ static int ue_ul_compare(const void *_a, const void *_b, void *_params) { int UE_id2 = *(const int *) _b; int rnti1 = UE_RNTI(params->module_idP, UE_id1); int pCCid1 = UE_PCCID(params->module_idP, UE_id1); - int round1 = maxround(params->module_idP, rnti1, params->frameP, - params->subframeP, 1); + int round1 = maxround_ul(params->module_idP, rnti1, params->sched_frameP, + params->sched_subframeP); int rnti2 = UE_RNTI(params->module_idP, UE_id2); int pCCid2 = UE_PCCID(params->module_idP, UE_id2); - int round2 = maxround(params->module_idP, rnti2, params->frameP, - params->subframeP, 1); + int round2 = maxround_ul(params->module_idP, rnti2, params->sched_frameP, + params->sched_subframeP); if (round1 > round2) return -1; @@ -1984,14 +2014,14 @@ static int ue_ul_compare(const void *_a, const void *_b, void *_params) { void sort_ue_ul(module_id_t module_idP, int slice_idx, - int frameP, - sub_frame_t subframeP, + int sched_frameP, + sub_frame_t sched_subframeP, rnti_t *rntiTable) { int i; int list[MAX_MOBILES_PER_ENB]; int list_size = 0; - struct sort_ue_ul_params params = { module_idP, frameP, subframeP }; + struct sort_ue_ul_params params = { module_idP, sched_frameP, sched_subframeP }; UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {