bugfixes for UL scheduling
- size of PUCCH has been fixed to:
- 2 RBs for N_RB_UL = 25 (1 RB at top of resource grid, 1 RB at bottom)
- 4 RBs for N_RB_UL = 50
- 6 RBs for N_RB_UL = 100
this is arbitrary and will need some rework at some point.
This may be also wrong. PUCCH size actually depends on DL traffic
(if the ack/nack is not done in PUSCH) and scheduling request
configurations.
- add sched_frame %= 1024 at one needed place
- reserve RBs for retransmission
this was not done so new transmissions were scheduled in the same
RBs. Since the code works with the notion of 'first_rb' only, it
was decided to skip all RBs lower than those retransmitted. This
works but is not correct (imagine we have to retransmit RB 23, then
all RBs < 23 will not be used for new transmission). The work to
fix this properly is complex, a lot has to change, so let's do it
this simple way for now.
- sort_ue_ul was not correct
- add the function maxround_ul to use the correct 'round' (the one
from DL was used, which is totally wrong)
- be sure to use the correct frame/subframe to get the correct HARQ pid
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user