pre_processor.c 65.8 KB
Newer Older
1
2
3
4
5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21
22

/*! \file pre_processor.c
23
 * \brief eNB scheduler preprocessing fuction prior to scheduling
24
 * \author Navid Nikaein and Ankit Bhamri
nikaeinn's avatar
nikaeinn committed
25
 * \date 2013 - 2014
26
 * \email navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
27
 * \version 1.0
28
29
30
31
 * @ingroup _mac

 */

32
33
34
#define _GNU_SOURCE
#include <stdlib.h>

35
#include "assertions.h"
36
37
38
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "LAYER2/MAC/mac_extern.h"
39
#include "UTIL/LOG/log.h"
40
#include "UTIL/LOG/vcd_signal_dumper.h"
41
42
43
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
44
#include "RRC/LTE/rrc_extern.h"
45
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
46
#include "rlc.h"
Cedric Roux's avatar
Cedric Roux committed
47
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
48

49
#include "common/ran_context.h"
50

51
extern RAN_CONTEXT_t RC;
gauthier's avatar
gauthier committed
52

53
54
55
56
#define DEBUG_eNB_SCHEDULER 1
#define DEBUG_HEADER_PARSING 1
//#define DEBUG_PACKET_TRACE 1

57
extern float slice_percentage[MAX_NUM_SLICES];
58
extern float slice_percentage_uplink[MAX_NUM_SLICES];
59
extern uint32_t sorting_policy[MAX_NUM_SLICES];
60

nikaeinn's avatar
nikaeinn committed
61
62
63
64
extern int slice_maxmcs[MAX_NUM_SLICES];
extern int slice_maxmcs_uplink[MAX_NUM_SLICES];


65
66
//#define ICIC 0

67
/* this function checks that get_eNB_UE_stats returns
Cedric Roux's avatar
Cedric Roux committed
68
 * a non-NULL pointer for all the active CCs of an UE
69
 */
70
/*
71
int phy_stats_exist(module_id_t Mod_id, int rnti)
72
73
{
  int CC_id;
Cedric Roux's avatar
Cedric Roux committed
74
75
  int i;
  int UE_id          = find_UE_id(Mod_id, rnti);
76
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
Cedric Roux's avatar
Cedric Roux committed
77
78
79
80
81
82
83
84
85
86
87
88
  if (UE_id == -1) {
    LOG_W(MAC, "[eNB %d] UE %x not found, should be there (in phy_stats_exist)\n",
	  Mod_id, rnti);
    return 0;
  }
  if (UE_list->numactiveCCs[UE_id] == 0) {
    LOG_W(MAC, "[eNB %d] UE %x has no active CC (in phy_stats_exist)\n",
	  Mod_id, rnti);
    return 0;
  }
  for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) {
    CC_id = UE_list->ordered_CCids[i][UE_id];
89
90
    if (mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti) == NULL)
      return 0;
91
  }
92
93
  return 1;
}
94
*/
95

96
// This function stores the downlink buffer for all the logical channels
97
void
98
store_dlsch_buffer(module_id_t Mod_id, slice_id_t slice_id, frame_t frameP,
99
		   sub_frame_t subframeP)
100
{
Cedric Roux's avatar
Cedric Roux committed
101

102
103
104
105
106
    int UE_id, i;
    rnti_t rnti;
    mac_rlc_status_resp_t rlc_status;
    UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
    UE_TEMPLATE *UE_template;
knopp's avatar
   
knopp committed
107

108
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
109
110
	if (UE_list->active[UE_id] != TRUE)
	    continue;
111

112
	if (!ue_slice_membership(UE_id, slice_id))
113
114
	    continue;

115
116
	UE_template =
	    &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id];
117

118
119
120
	// clear logical channel interface variables
	UE_template->dl_buffer_total = 0;
	UE_template->dl_pdus_total = 0;
121

122
123
124
125
126
127
	for (i = 0; i < MAX_NUM_LCID; i++) {
	    UE_template->dl_buffer_info[i] = 0;
	    UE_template->dl_pdus_in_buffer[i] = 0;
	    UE_template->dl_buffer_head_sdu_creation_time[i] = 0;
	    UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] = 0;
	}
128

129

130
131
	rnti = UE_RNTI(Mod_id, UE_id);

132
        for (i = 0; i < MAX_NUM_LCID; i++) {    // loop over all the logical channels
133
134
135

	    rlc_status =
		mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP,
136
				   ENB_FLAG_YES, MBMS_FLAG_NO, i, 0
137
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
138
139
140
141
                   ,0, 0
#endif
                   );

142
143
144
145
146
147
148
149
150
151
152
153
154
155
	    UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer;	//storing the dlsch buffer for each logical channel
	    UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
	    UE_template->dl_buffer_head_sdu_creation_time[i] =
		rlc_status.head_sdu_creation_time;
	    UE_template->dl_buffer_head_sdu_creation_time_max =
		cmax(UE_template->dl_buffer_head_sdu_creation_time_max,
		     rlc_status.head_sdu_creation_time);
	    UE_template->dl_buffer_head_sdu_remaining_size_to_send[i] =
		rlc_status.head_sdu_remaining_size_to_send;
	    UE_template->dl_buffer_head_sdu_is_segmented[i] =
		rlc_status.head_sdu_is_segmented;
	    UE_template->dl_buffer_total += UE_template->dl_buffer_info[i];	//storing the total dlsch buffer
	    UE_template->dl_pdus_total +=
		UE_template->dl_pdus_in_buffer[i];
156

Cedric Roux's avatar
Cedric Roux committed
157
#ifdef DEBUG_eNB_SCHEDULER
158

159
160
161
162
163
	    /* note for dl_buffer_head_sdu_remaining_size_to_send[i] :
	     * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent
	     */
	    if (UE_template->dl_buffer_info[i] > 0)
		LOG_D(MAC,
164
165
		      "[eNB %d][SLICE %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n",
		      Mod_id, slice_id, frameP, subframeP, UE_id,
166
167
168
169
170
171
		      i, UE_template->dl_pdus_in_buffer[i],
		      UE_template->dl_buffer_info[i],
		      UE_template->dl_buffer_head_sdu_creation_time[i],
		      UE_template->
		      dl_buffer_head_sdu_remaining_size_to_send[i],
		      UE_template->dl_buffer_head_sdu_is_segmented[i]);
172

Cedric Roux's avatar
Cedric Roux committed
173
#endif
174

175
	}
176

177
178
179
180
181
182
183
	//#ifdef DEBUG_eNB_SCHEDULER
	if (UE_template->dl_buffer_total > 0)
	    LOG_D(MAC,
		  "[eNB %d] Frame %d Subframe %d : RLC status for UE %d : total DL buffer size %d and total number of pdu %d \n",
		  Mod_id, frameP, subframeP, UE_id,
		  UE_template->dl_buffer_total,
		  UE_template->dl_pdus_total);
184

185
186
	//#endif
    }
187
188
}

189

190
// This function returns the estimated number of RBs required by each UE for downlink scheduling
191
192
void
assign_rbs_required(module_id_t Mod_id,
193
			slice_id_t slice_id,
194
195
196
		    frame_t frameP,
		    sub_frame_t subframe,
		    uint16_t
197
198
		    nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB],
		    int min_rb_unit[NFAPI_CC_MAX])
199
{
200

201
    uint16_t TBS = 0;
202

203
204
205
206
    int UE_id, n, i, j, CC_id, pCCid, tmp;
    UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
    eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j;
    int N_RB_DL;
207

208
    // clear rb allocations across all CC_id
209
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
210
211
	if (UE_list->active[UE_id] != TRUE)
	    continue;
212
	if (!ue_slice_membership(UE_id, slice_id))
213
	    continue;
214
	pCCid = UE_PCCID(Mod_id, UE_id);
215

216
217
218
219
	//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 = &UE_list->eNB_UE_stats[CC_id][UE_id];
knopp's avatar
knopp committed
220

nikaeinn's avatar
nikaeinn committed
221
222
	    eNB_UE_stats->dlsch_mcs1 =cmin(cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]],
									   slice_maxmcs[slice_id]);
223

224
	}
225

226
227
228
229
230
231
	// provide the list of CCs sorted according to MCS
	for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) {
	    eNB_UE_stats_i =
		&UE_list->eNB_UE_stats[UE_list->
				       ordered_CCids[i][UE_id]][UE_id];
	    for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) {
232
		DevAssert(j < NFAPI_CC_MAX);
233
234
235
236
237
238
239
240
241
242
243
244
		eNB_UE_stats_j =
		    &UE_list->
		    eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id];
		if (eNB_UE_stats_j->dlsch_mcs1 >
		    eNB_UE_stats_i->dlsch_mcs1) {
		    tmp = UE_list->ordered_CCids[i][UE_id];
		    UE_list->ordered_CCids[i][UE_id] =
			UE_list->ordered_CCids[j][UE_id];
		    UE_list->ordered_CCids[j][UE_id] = tmp;
		}
	    }
	}
245

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
	if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) {
	    LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id);

	    for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) {
		CC_id = UE_list->ordered_CCids[i][UE_id];
		eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];

		if (eNB_UE_stats->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 =
		    get_TBS_DL(eNB_UE_stats->dlsch_mcs1,
			       nb_rbs_required[CC_id][UE_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->dlsch_mcs1, TBS);

		N_RB_DL =
		    to_prb(RC.mac[Mod_id]->common_channels[CC_id].
			   mib->message.dl_Bandwidth);

274
		UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_id]= flexran_nb_rbs_allowed_slice(slice_percentage[slice_id],N_RB_DL);
275

276
277
278
279
280
281
		/* 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];

282
		    if (nb_rbs_required[CC_id][UE_id] > UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_id]) {
283
			TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_id]);
284
			nb_rbs_required[CC_id][UE_id] = UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_id];
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
			break;
		    }

		    TBS =
			get_TBS_DL(eNB_UE_stats->dlsch_mcs1,
				   nb_rbs_required[CC_id][UE_id]);
		}		// end of while

		LOG_D(MAC,
		      "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d,  nb_required RB %d (TBS %d, mcs %d)\n",
		      Mod_id, frameP, UE_id, CC_id, min_rb_unit[CC_id],
		      nb_rbs_required[CC_id][UE_id], TBS,
		      eNB_UE_stats->dlsch_mcs1);
	    }
	}
knopp's avatar
   
knopp committed
300
301
    }
}
gauthier's avatar
gauthier committed
302
303


knopp's avatar
   
knopp committed
304
// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes
gauthier's avatar
gauthier committed
305

306
307
308
int
maxround(module_id_t Mod_id, uint16_t rnti, int frame,
	 sub_frame_t subframe, uint8_t ul_flag)
309
{
gauthier's avatar
gauthier committed
310

311
312
313
314
    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;
gauthier's avatar
gauthier committed
315

knopp's avatar
knopp committed
316
    for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) {
317

318
	cc = &RC.mac[Mod_id]->common_channels[CC_id];
319

320
	UE_id = find_UE_id(Mod_id, rnti);
321
322

	harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frame ,subframe);
323

324
325
326
327
	round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid];
	if (round > round_max) {
	    round_max = round;
	}
328
    }
329

330
    return round_max;
knopp's avatar
   
knopp committed
331
}
gauthier's avatar
gauthier committed
332

knopp's avatar
   
knopp committed
333
// This function scans all CC_ids for a particular UE to find the maximum DL CQI
Cedric Roux's avatar
Cedric Roux committed
334
// it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL)
335
int maxcqi(module_id_t Mod_id, int32_t UE_id)
336
{
337
338
339
    UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
    int CC_id, n;
    int CQI = 0;
gauthier's avatar
gauthier committed
340

341
342
    for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) {
	CC_id = UE_list->ordered_CCids[n][UE_id];
343

344
345
346
	if (UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id] > CQI) {
	    CQI = UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id];
	}
347
    }
gauthier's avatar
gauthier committed
348

349
    return CQI;
knopp's avatar
   
knopp committed
350
}
gauthier's avatar
gauthier committed
351

352
struct sort_ue_dl_params {
353
354
355
    int Mod_idP;
    int frameP;
    int subframeP;
356
    int slice_id;
357
};
gauthier's avatar
gauthier committed
358

359
360
static int ue_dl_compare(const void *_a, const void *_b, void *_params)
{
361
362
363
    struct sort_ue_dl_params *params = _params;
    UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list;

364
365
	int i;
	int slice_id = params->slice_id;
366
367
368
369
370
    int UE_id1 = *(const int *) _a;
    int UE_id2 = *(const int *) _b;

    int rnti1 = UE_RNTI(params->Mod_idP, UE_id1);
    int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1);
371
    int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP, 1);
372
373
374

    int rnti2 = UE_RNTI(params->Mod_idP, UE_id2);
    int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2);
375
    int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP, 1);
376
377
378
379

    int cqi1 = maxcqi(params->Mod_idP, UE_id1);
    int cqi2 = maxcqi(params->Mod_idP, UE_id2);

380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
  for (i = 0; i < CR_NUM; ++i) {
    switch (UE_list->sorting_criteria[slice_id][i]) {

      case CR_ROUND :
        if (round1 > round2)
          return -1;
        if (round1 < round2)
          return 1;
        break;

      case CR_SRB12 :
        if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] +
            UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] >
            UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] +
            UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])
          return -1;
        if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] +
            UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] <
            UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] +
            UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2])
          return 1;
        break;

      case CR_HOL :
        if (UE_list-> UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max >
            UE_list-> UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max)
          return -1;
        if (UE_list-> UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max <
            UE_list-> UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max)
          return 1;
        break;

      case CR_LC :
        if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total >
            UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total)
          return -1;
        if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total <
            UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total)
          return 1;
        break;

      case CR_CQI :
        if (cqi1 > cqi2)
          return -1;
        if (cqi1 < cqi2)
          return 1;

      default :
        break;
    }
  }
431
432

    return 0;
433
#if 0
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
    /* The above order derives from the following.  */
    if (round2 > round1) {	// Check first if one of the UEs has an active HARQ process which needs service and swap order
	swap_UEs(UE_list, UE_id1, UE_id2, 0);
    } else if (round2 == round1) {
	// RK->NN : I guess this is for fairness in the scheduling. This doesn't make sense unless all UEs have the same configuration of logical channels.  This should be done on the sum of all information that has to be sent.  And still it wouldn't ensure fairness.  It should be based on throughput seen by each UE or maybe using the head_sdu_creation_time, i.e. swap UEs if one is waiting longer for service.
	//  for(j=0;j<MAX_NUM_LCID;j++){
	//    if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] <
	//      eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){

	// 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);
	}
    }
462
463
#endif
}
gauthier's avatar
gauthier committed
464

465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
void decode_sorting_policy(module_id_t Mod_idP, slice_id_t slice_id) {
	int i;

	UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list;
	uint32_t policy = sorting_policy[slice_id];
	uint32_t mask = 0x0000000F;
    uint16_t criterion;

	for(i = 0; i < CR_NUM; ++i) {
		criterion = (uint16_t)(policy >> 4*(CR_NUM - 1 - i) & mask);
        if (criterion >= CR_NUM) {
          LOG_W(MAC, "Invalid criterion in slice %d policy, revert to default policy \n", slice_id);
          sorting_policy[slice_id] = 0x1234;
          break;
        }
      UE_list->sorting_criteria[slice_id][i] = criterion;
	}
}


knopp's avatar
   
knopp committed
485
// This fuction sorts the UE in order their dlsch buffer and CQI
486
void sort_UEs(module_id_t Mod_idP, slice_id_t slice_id, int frameP, sub_frame_t subframeP)
487
{
488
    int i;
489
    int list[MAX_MOBILES_PER_ENB];
490
491
    int list_size = 0;
    int rnti;
492
    struct sort_ue_dl_params params = { Mod_idP, frameP, subframeP, slice_id };
493

494
    UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list;
495

496
	for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
497

498
499
500
501
		if (UE_list->active[i] == FALSE)
			continue;
		if ((rnti = UE_RNTI(Mod_idP, i)) == NOT_A_RNTI)
			continue;
502
#if 0
503
504
		if (UE_list->UE_sched_ctrl[i].ul_out_of_sync == 1)
			continue;
505
#endif
506
507
		if (!ue_slice_membership(i, slice_id))
			continue;
508

509
510
511
		list[list_size] = i;
		list_size++;
	}
512

513
	decode_sorting_policy(Mod_idP, slice_id);
514

515
	qsort_r(list, list_size, sizeof(int), ue_dl_compare, &params);
516

517
518
519
520
521
522
523
524
	if (list_size) {
		for (i = 0; i < list_size - 1; i++)
			UE_list->next[list[i]] = list[i + 1];
		UE_list->next[list[list_size - 1]] = -1;
		UE_list->head = list[0];
	} else {
		UE_list->head = -1;
	}
525
526

#if 0
gauthier's avatar
gauthier committed
527
528


529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
    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 = &RC.mac[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.
		//  for(j=0;j<MAX_NUM_LCID;j++){
		//    if (eNB_mac_inst[Mod_id][pCC_id1].UE_template[UE_id1].dl_buffer_info[j] <
		//      eNB_mac_inst[Mod_id][pCC_id2].UE_template[UE_id2].dl_buffer_info[j]){

		// 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);
		}
	    }
	}
knopp's avatar
   
knopp committed
595
    }
596
#endif
597
598
}

599
600
601
602
void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
                                              slice_id_t slice_id,
                                              frame_t frameP,
                                              sub_frame_t subframeP,
603
604
605
606
607
                                              int N_RBG[NFAPI_CC_MAX],
                                              int min_rb_unit[NFAPI_CC_MAX],
                                              uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX],
                                              uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX],
                                              uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) {
knopp's avatar
   
knopp committed
608
609


610
611
  int UE_id, CC_id;
  int ii, r1;
knopp's avatar
   
knopp committed
612

613
614
  rnti_t rnti;
  uint8_t harq_pid, round, transmission_mode;
615
616
617
618
619
  uint8_t total_rbs_used[NFAPI_CC_MAX];
  uint8_t total_ue_count[NFAPI_CC_MAX];
  uint16_t average_rbs_per_user[NFAPI_CC_MAX];
  uint16_t nb_rbs_required_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
  uint16_t nb_rbs_required_remaining_1[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
620

knopp's avatar
knopp committed
621
  int N_RB_DL;
622
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
623
  UE_sched_ctrl *ue_sched_ctl;
624
  COMMON_channels_t *cc;
625

knopp's avatar
knopp committed
626
  for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) {
627
628
629
    total_ue_count[CC_id] = 0;
    total_rbs_used[CC_id] = 0;
    average_rbs_per_user[CC_id] = 0;
630
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) {
631
632
633
      nb_rbs_required_remaining[CC_id][UE_id] = 0;
    }
  }
knopp's avatar
   
knopp committed
634

635
636
637
  // loop over all active UEs
  for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
    rnti = UE_RNTI(Mod_id, UE_id);
638

639
640
    if (rnti == NOT_A_RNTI)
      continue;
641
#if 0
642
643
    if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
      continue;
644
#endif
645
646
    if (!ue_slice_membership(UE_id, slice_id))
      continue;
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
    for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) {
      CC_id = UE_list->ordered_CCids[ii][UE_id];
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
      cc = &RC.mac[Mod_id]->common_channels[CC_id];
      // TODO Can we use subframe2harqpid() here?
      if (cc->tdd_Config)
        harq_pid = ((frameP * 10) + subframeP) % 10;
      else
        harq_pid = ((frameP * 10) + subframeP) & 7;
      round = ue_sched_ctl->round[CC_id][harq_pid];

      average_rbs_per_user[CC_id] = 0;

      if (round != 8) {
        nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
        total_rbs_used[CC_id] += nb_rbs_required[CC_id][UE_id];
      }

      //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id];
      if (nb_rbs_required[CC_id][UE_id] > 0) {
        total_ue_count[CC_id] = total_ue_count[CC_id] + 1;
      }
    }
  }
672

673
674
675
  // loop over all active UEs and calculate avg rb per user based on total active UEs
  for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
    rnti = UE_RNTI(Mod_id, UE_id);
676

677
678
679
680
681
682
    if (rnti == NOT_A_RNTI)
      continue;
    if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
      continue;
    if (!ue_slice_membership(UE_id, slice_id))
      continue;
683

684
685
    for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) {
      CC_id = UE_list->ordered_CCids[ii][UE_id];
knopp's avatar
   
knopp committed
686

687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
      // hypothetical assignment
      /*
       * If schedule is enabled and if the priority of the UEs is modified
       * The average rbs per logical channel per user will depend on the level of
       * priority. Concerning the hypothetical assignement, we should assign more
       * rbs to prioritized users. Maybe, we can do a mapping between the
       * average rbs per user and the level of priority or multiply the average rbs
       * per user by a coefficient which represents the degree of priority.
       */

      N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - total_rbs_used[CC_id];

      // recalculate based on the what is left after retransmission
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
      ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_id] =
              flexran_nb_rbs_allowed_slice(slice_percentage[slice_id], N_RB_DL);

      if (total_ue_count[CC_id] == 0) {
        average_rbs_per_user[CC_id] = 0;
      } else if ((min_rb_unit[CC_id] * total_ue_count[CC_id]) <=
                 (ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_id])) {
        average_rbs_per_user[CC_id] =
                (uint16_t) floor(ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_id] / total_ue_count[CC_id]);
      } else {
        // consider the total number of use that can be scheduled UE
        average_rbs_per_user[CC_id] = min_rb_unit[CC_id];
      }
714
    }
715
  }
knopp's avatar
   
knopp committed
716

717
718
719
720
  // note: nb_rbs_required is assigned according to total_buffer_dl
  // extend nb_rbs_required to capture per LCID RB required
  for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
    rnti = UE_RNTI(Mod_id, UE_id);
knopp's avatar
   
knopp committed
721

722
723
    if (rnti == NOT_A_RNTI)
      continue;
724
#if 0
725
726
    if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
      continue;
727
#endif
728
729
    if (!ue_slice_membership(UE_id, slice_id))
      continue;
knopp's avatar
   
knopp committed
730

731
732
733
734
    for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) {
      CC_id = UE_list->ordered_CCids[ii][UE_id];
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
      cc = &RC.mac[Mod_id]->common_channels[CC_id];
735
      harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
736
737
738
739
      round = ue_sched_ctl->round[CC_id][harq_pid];

      // control channel or retransmission
      /* TODO: do we have to check for retransmission? */
740
      if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) {
741
742
743
744
745
746
        nb_rbs_required_remaining_1[CC_id][UE_id] =
                nb_rbs_required[CC_id][UE_id];
      } else {
        nb_rbs_required_remaining_1[CC_id][UE_id] =
                cmin(average_rbs_per_user[CC_id], nb_rbs_required[CC_id][UE_id]);
      }
747
    }
748
  }
749

750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
  //Allocation to UEs is done in 2 rounds,
  // 1st stage: average number of RBs allocated to each UE
  // 2nd stage: remaining RBs are allocated to high priority UEs
  for (r1 = 0; r1 < 2; r1++) {

    for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
      for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) {
        CC_id = UE_list->ordered_CCids[ii][UE_id];

        if (r1 == 0) {
          nb_rbs_required_remaining[CC_id][UE_id] =
                  nb_rbs_required_remaining_1[CC_id][UE_id];
        } else {    // rb required based only on the buffer - rb allocated in the 1st round + extra reaming rb form the 1st round
          nb_rbs_required_remaining[CC_id][UE_id] =
                  nb_rbs_required[CC_id][UE_id] -
                  nb_rbs_required_remaining_1[CC_id][UE_id] +
                  nb_rbs_required_remaining[CC_id][UE_id];
          if (nb_rbs_required_remaining[CC_id][UE_id] < 0)
            abort();
        }
770

771
772
773
774
775
776
777
778
779
780
781
782
783
        if (nb_rbs_required[CC_id][UE_id] > 0)
          LOG_D(MAC,
                "round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d,  pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n",
                r1, CC_id, UE_id,
                nb_rbs_required_remaining[CC_id][UE_id],
                nb_rbs_required_remaining_1[CC_id][UE_id],
                nb_rbs_required[CC_id][UE_id],
                UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id],
                N_RBG[CC_id],
                min_rb_unit[CC_id]);

      }
    }
knopp's avatar
   
knopp committed
784

785
    for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
knopp's avatar
   
knopp committed
786

787
      for (ii = 0; ii < UE_num_active_CC(UE_list, UE_id); ii++) {
Xu Bo's avatar
Xu Bo committed
788

789
790
791
792
793
        CC_id = UE_list->ordered_CCids[ii][UE_id];
        // if there are UEs with traffic
        if (total_ue_count[CC_id] > 0) {
          // ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
          // round = ue_sched_ctl->round[CC_id][harq_pid];
Xu Bo's avatar
Xu Bo committed
794

795
          rnti = UE_RNTI(Mod_id, UE_id);
796

797
798
799
          // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
          if (rnti == NOT_A_RNTI)
            continue;
800
#if 0
801
802
          if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1)
            continue;
803
#endif
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
          if (!ue_slice_membership(UE_id, slice_id))
            continue;

          transmission_mode = get_tmode(Mod_id, CC_id, UE_id);
          // mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
          // rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
          /* 1st allocate for the retx */

          // retransmission in data channels
          // control channel in the 1st transmission
          // data channel for all TM
          LOG_T(MAC,
                "calling dlsch_scheduler_pre_processor_allocate .. \n ");
          dlsch_scheduler_pre_processor_allocate(Mod_id, UE_id,
                                                 CC_id,
                                                 N_RBG[CC_id],
                                                 transmission_mode,
                                                 min_rb_unit
                                                 [CC_id],
823
                                                 to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth),
824
825
826
827
                                                 nb_rbs_required,
                                                 nb_rbs_required_remaining,
                                                 rballoc_sub,
                                                 MIMO_mode_indicator);
828

829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
#ifdef TM5
          // data chanel TM5: to be revisited
          if ((round == 0) &&
          (transmission_mode == 5) &&
          (ue_sched_ctl->dl_pow_off[CC_id] != 1)) {

          for (j = 0; j < N_RBG[CC_id]; j += 2) {

              if ((((j == (N_RBG[CC_id] - 1))
                && (rballoc_sub[CC_id][j] == 0)
                && (ue_sched_ctl->
                    rballoc_sub_UE[CC_id][j] == 0))
               || ((j < (N_RBG[CC_id] - 1))
                   && (rballoc_sub[CC_id][j + 1] == 0)
                   &&
                   (ue_sched_ctl->rballoc_sub_UE
                    [CC_id][j + 1] == 0)))
              && (nb_rbs_required_remaining[CC_id][UE_id]
                  > 0)) {

              for (ii = UE_list->next[UE_id + 1]; ii >= 0;
                   ii = UE_list->next[ii]) {

                  UE_id2 = ii;
                  rnti2 = UE_RNTI(Mod_id, UE_id2);
                  ue_sched_ctl2 =
                  &UE_list->UE_sched_ctrl[UE_id2];
                  round2 = ue_sched_ctl2->round[CC_id];
                  if (rnti2 == NOT_A_RNTI)
                  continue;
                  if (UE_list->
                  UE_sched_ctrl
                  [UE_id2].ul_out_of_sync == 1)
                  continue;

                  eNB_UE_stats2 =
                  UE_list->
                  eNB_UE_stats[CC_id][UE_id2];
                  //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0);

                  if ((mac_eNB_get_rrc_status
                   (Mod_id,
                    rnti2) >= RRC_RECONFIGURED)
                  && (round2 == 0)
                  &&
                  (get_tmode(Mod_id, CC_id, UE_id2)
                   == 5)
                  && (ue_sched_ctl->
                      dl_pow_off[CC_id] != 1)) {

                  if ((((j == (N_RBG[CC_id] - 1))
                        &&
                        (ue_sched_ctl->rballoc_sub_UE
                         [CC_id][j] == 0))
                       || ((j < (N_RBG[CC_id] - 1))
                       &&
                       (ue_sched_ctl->
                        rballoc_sub_UE[CC_id][j +
                                  1]
                        == 0)))
                      &&
                      (nb_rbs_required_remaining
                       [CC_id]
                       [UE_id2] > 0)) {

                      if ((((eNB_UE_stats2->
                         DL_pmi_single ^
                         eNB_UE_stats1->
                         DL_pmi_single)
                        << (14 - j)) & 0xc000) == 0x4000) {	//MU-MIMO only for 25 RBs configuration

                      rballoc_sub[CC_id][j] = 1;
                      ue_sched_ctl->
                          rballoc_sub_UE[CC_id]
                          [j] = 1;
                      ue_sched_ctl2->
                          rballoc_sub_UE[CC_id]
                          [j] = 1;
                      MIMO_mode_indicator[CC_id]
                          [j] = 0;

                      if (j < N_RBG[CC_id] - 1) {
                          rballoc_sub[CC_id][j +
                                     1] =
                          1;
                          ue_sched_ctl->
                          rballoc_sub_UE
                          [CC_id][j + 1] = 1;
                          ue_sched_ctl2->rballoc_sub_UE
                          [CC_id][j + 1] = 1;
                          MIMO_mode_indicator
                          [CC_id][j + 1]
                          = 0;
                      }

                      ue_sched_ctl->
                          dl_pow_off[CC_id]
                          = 0;
                      ue_sched_ctl2->
                          dl_pow_off[CC_id]
                          = 0;


                      if ((j == N_RBG[CC_id] - 1)
                          && ((N_RB_DL == 25)
                          || (N_RB_DL ==
                              50))) {

                          nb_rbs_required_remaining
                          [CC_id][UE_id] =
                          nb_rbs_required_remaining
                          [CC_id][UE_id] -
                          min_rb_unit[CC_id]
                          + 1;
                          ue_sched_ctl->pre_nb_available_rbs
                          [CC_id] =
                          ue_sched_ctl->pre_nb_available_rbs
                          [CC_id] +
                          min_rb_unit[CC_id]
                          - 1;
                          nb_rbs_required_remaining
                          [CC_id][UE_id2] =
                          nb_rbs_required_remaining
                          [CC_id][UE_id2] -
                          min_rb_unit[CC_id]
                          + 1;
                          ue_sched_ctl2->pre_nb_available_rbs
                          [CC_id] =
                          ue_sched_ctl2->pre_nb_available_rbs
                          [CC_id] +
                          min_rb_unit[CC_id]
                          - 1;
                      } else {

                          nb_rbs_required_remaining
                          [CC_id][UE_id] =
                          nb_rbs_required_remaining
                          [CC_id][UE_id] - 4;
                          ue_sched_ctl->pre_nb_available_rbs
                          [CC_id] =
                          ue_sched_ctl->pre_nb_available_rbs
                          [CC_id] + 4;
                          nb_rbs_required_remaining
                          [CC_id][UE_id2] =
                          nb_rbs_required_remaining
                          [CC_id][UE_id2] -
                          4;
                          ue_sched_ctl2->pre_nb_available_rbs
                          [CC_id] =
                          ue_sched_ctl2->pre_nb_available_rbs
                          [CC_id] + 4;
                      }

                      break;
                      }
                  }
                  }
              }
              }
          }
          }
#endif
        } // total_ue_count
      } // CC
    } // UE
  } // end of for for r1 and r2
}
996

997
998
999
1000
1001
1002
// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
void
dlsch_scheduler_pre_processor(module_id_t Mod_id,
                              slice_id_t slice_id,
                              frame_t frameP,
                              sub_frame_t subframeP,
1003
                              int N_RBG[NFAPI_CC_MAX],
1004
                              int *mbsfn_flag) {
knopp's avatar
   
knopp committed
1005

1006
1007
1008
  int UE_id;
  uint8_t CC_id;
  uint16_t i, j;
1009

1010
1011
  uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX];
  uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]; // If TM5 is revisited, we can move this inside accounting
1012

1013
1014
  int min_rb_unit[NFAPI_CC_MAX];
  uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
1015

1016
1017
1018
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
  UE_sched_ctrl *ue_sched_ctl;
//  int rrc_status = RRC_IDLE;
1019

1020
1021
1022
1023
1024
1025
1026
1027
1028
#ifdef TM5
  int harq_pid1 = 0;
  int round1 = 0, round2 = 0;
  int UE_id2;
  uint16_t i1, i2, i3;
  rnti_t rnti1, rnti2;
  LTE_eNB_UE_stats *eNB_UE_stats1 = NULL;
  LTE_eNB_UE_stats *eNB_UE_stats2 = NULL;
  UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2;
1029
#endif
1030

knopp's avatar
knopp committed
1031
  for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) {
1032

1033
1034
    if (mbsfn_flag[CC_id] > 0)    // If this CC is allocated for MBSFN skip it here
      continue;
1035

1036
    min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id);
1037

1038
    for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) {
1039
1040
      if (UE_list->active[UE_id] != TRUE)
        continue;
1041

1042
1043
      if (!ue_slice_membership(UE_id, slice_id))
        continue;
1044

1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
      // Initialize scheduling information for all active UEs
      dlsch_scheduler_pre_processor_reset(Mod_id,
                                          UE_id,
                                          CC_id,
                                          frameP,
                                          subframeP,
                                          N_RBG[CC_id],
                                          nb_rbs_required,
                                          rballoc_sub,
                                          MIMO_mode_indicator);
1055

1056
    }
1057
  }
1058

1059
1060
  // Store the DLSCH buffer for each logical channel
  store_dlsch_buffer(Mod_id, slice_id, frameP, subframeP);
1061

1062
1063
  // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
  assign_rbs_required(Mod_id, slice_id, frameP, subframeP, nb_rbs_required, min_rb_unit);
1064

1065
1066
  // Sorts the user on the basis of dlsch logical channel buffer and CQI
  sort_UEs(Mod_id, slice_id, frameP, subframeP);
1067

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  // This function does the main allocation of the number of RBs
  dlsch_scheduler_pre_processor_accounting(Mod_id,
                                           slice_id,
                                           frameP,
                                           subframeP,
                                           N_RBG,
                                           min_rb_unit,
                                           rballoc_sub,
                                           MIMO_mode_indicator,
                                           nb_rbs_required);
1078
1079


1080
#ifdef TM5
1081
  // This has to be revisited!!!!
knopp's avatar
knopp committed
1082
  for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) {
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
  i1 = 0;
  i2 = 0;
  i3 = 0;

  for (j = 0; j < N_RBG[CC_id]; j++) {
      if (MIMO_mode_indicator[CC_id][j] == 2) {
      i1 = i1 + 1;
      } else if (MIMO_mode_indicator[CC_id][j] == 1) {
      i2 = i2 + 1;
      } else if (MIMO_mode_indicator[CC_id][j] == 0) {
      i3 = i3 + 1;
      }
  }
1096

1097
1098
1099
1100
1101
  if ((i1 < N_RBG[CC_id]) && (i2 > 0) && (i3 == 0)) {
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions =
      PHY_vars_eNB_g[Mod_id][CC_id]->
      check_for_SUMIMO_transmissions + 1;
  }
1102

1103
1104
1105
1106
1107
  if (i3 == N_RBG[CC_id] && i1 == 0 && i2 == 0) {
      PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions =
      PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions +
      1;
  }
1108

1109
1110
1111
1112
1113
  if ((i1 < N_RBG[CC_id]) && (i3 > 0)) {
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions =
      PHY_vars_eNB_g[Mod_id][CC_id]->
      check_for_MUMIMO_transmissions + 1;
  }
1114

1115
1116
1117
  PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions =
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions +
      1;
1118

1119
  }
1120
1121
#endif

1122
  for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
1123

1124
1125
1126
1127
    ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
    for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) {
      CC_id = UE_list->ordered_CCids[i][UE_id];
      //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];
1128

1129
1130
1131
1132
      if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) {
        LOG_D(MAC, "******************DL Scheduling Information for UE%d ************************\n", UE_id);
        LOG_D(MAC, "dl power offset UE%d = %d \n", UE_id, ue_sched_ctl->dl_pow_off[CC_id]);
        LOG_D(MAC, "***********RB Alloc for every subband for UE%d ***********\n", UE_id);
1133

1134
1135
1136
1137
1138
1139
1140
1141
1142
        for (j = 0; j < N_RBG[CC_id]; j++) {
          //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[UE_id] = rballoc_sub_UE[CC_id][UE_id][UE_id];
          LOG_D(MAC, "RB Alloc for UE%d and Subband%d = %d\n", UE_id, j, ue_sched_ctl->rballoc_sub_UE[CC_id][j]);
        }

        //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
        LOG_D(MAC, "[eNB %d][SLICE %d]Total RBs allocated for UE%d = %d\n",
              Mod_id, slice_id, UE_id, ue_sched_ctl->pre_nb_available_rbs[CC_id]);
      }
knopp's avatar
   
knopp committed
1143
    }
1144
  }
1145
1146
}

Cedric Roux's avatar
Cedric Roux committed
1147
#define SF0_LIMIT 1
1148

1149
1150
void
dlsch_scheduler_pre_processor_reset(int module_idP,
1151
1152
1153
1154
1155
                                    int UE_id,
                                    uint8_t CC_id,
                                    int frameP,
                                    int subframeP,
                                    int N_RBG,
1156
1157
                                    uint16_t nb_rbs_required[NFAPI_CC_MAX]
                                    [MAX_MOBILES_PER_ENB],
1158
                                    unsigned char
1159
                                    rballoc_sub[NFAPI_CC_MAX]
1160
1161
                                    [N_RBG_MAX],
                                    unsigned char
1162
                                    MIMO_mode_indicator[NFAPI_CC_MAX]
1163
                                    [N_RBG_MAX])
1164
{
1165
1166
1167
1168
1169
1170
1171
1172
1173
  int i, j;
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
  UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  rnti_t rnti = UE_RNTI(module_idP, UE_id);

  uint8_t *vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map;
  int N_RB_DL =
          to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth);
  int RBGsize = N_RB_DL / N_RBG, RBGsize_last;
Cedric Roux's avatar
Cedric Roux committed
1174
#ifdef SF0_LIMIT
1175
  int sf0_upper = -1, sf0_lower = -1;
1176
#endif
1177

1178

1179
1180
  LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti);
  // initialize harq_pid and round
1181

1182
1183
  if (ue_sched_ctl->ta_timer)
    ue_sched_ctl->ta_timer--;
1184

1185
1186
    /*
       eNB_UE_stats *eNB_UE_stats;
1187

1188
1189
       if (eNB_UE_stats == NULL)
       return;
1190
1191


1192
1193
1194
1195
1196
       mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,
       frameP,subframeP,
       &ue_sched_ctl->harq_pid[CC_id],
       &ue_sched_ctl->round[CC_id],
       openair_harq_DL);
1197

1198
       if (ue_sched_ctl->ta_timer == 0) {
1199

1200
       // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ...
1201

1202
1203
1204
1205
1206
       ue_sched_ctl->ta_timer = 20;  // wait 20 subframes before taking TA measurement from PHY
       switch (N_RB_DL) {
       case 6:
       ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update;
       break;
1207

1208
1209
1210
       case 15:
       ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2;
       break;
Cedric Roux's avatar
Cedric Roux committed
1211

1212
1213
1214
       case 25:
       ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4;
       break;
1215

1216
1217
1218
       case 50:
       ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8;
       break;