eNB_scheduler_dlsch.c 78.4 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
 */
nikaeinn's avatar
nikaeinn committed
21
22
23

/*! \file eNB_scheduler_dlsch.c
 * \brief procedures related to eNB for the DLSCH transport channel
24
 * \author  Navid Nikaein and Raymond Knopp
nikaeinn's avatar
nikaeinn committed
25
 * \date 2010 - 2014
26
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
27
 * \version 1.0
28
29
30
31
32
 * @ingroup _mac

 */


33
34
35
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "LAYER2/MAC/mac_extern.h"
36
37
38
39
40
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
Cedric Roux's avatar
Cedric Roux committed
41
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
42

43
#include "RRC/LTE/rrc_extern.h"
44
45
46
47
48
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

49
50
51
#include "SIMULATION/TOOLS/sim.h"	// for taus

#include "assertions.h"
52

53
#if defined(ENABLE_ITTI)
54
#include "intertask_interface.h"
55
56
#endif

57
58
59
60
61
62
#include "ENB_APP/flexran_agent_defs.h"
#include "flexran_agent_ran_api.h"
#include "header.pb-c.h"
#include "flexran.pb-c.h"
#include <dlfcn.h>

Cedric Roux's avatar
Cedric Roux committed
63
64
#include "T.h"

65
#define ENABLE_MAC_PAYLOAD_DEBUG
knopp's avatar
   
knopp committed
66
//#define DEBUG_eNB_SCHEDULER 1
67

68
extern RAN_CONTEXT_t RC;
69
extern uint8_t nfapi_mode;
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

// number of active slices for  past and current time
int n_active_slices = 1;
int n_active_slices_current = 1;

// RB share for each slice for past and current time
float avg_slice_percentage=0.25;
float slice_percentage[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
float slice_percentage_current[MAX_NUM_SLICES] = {1.0, 0.0, 0.0, 0.0};
float total_slice_percentage = 0;
float total_slice_percentage_current = 0;

// MAX MCS for each slice for past and current time
int slice_maxmcs[MAX_NUM_SLICES] = { 28, 28, 28, 28 };
int slice_maxmcs_current[MAX_NUM_SLICES] = { 28, 28, 28, 28 };

int update_dl_scheduler[MAX_NUM_SLICES] = { 1, 1, 1, 1 };
int update_dl_scheduler_current[MAX_NUM_SLICES] = { 1, 1, 1, 1 };

// name of available scheduler
char *dl_scheduler_type[MAX_NUM_SLICES] =
  { "schedule_ue_spec",
    "schedule_ue_spec",
    "schedule_ue_spec",
    "schedule_ue_spec"
  };

98
99
100
101
// The lists of criteria that enforce the sorting policies of the slices
uint32_t sorting_policy[MAX_NUM_SLICES] = {0x01234, 0x01234, 0x01234, 0x01234};
uint32_t sorting_policy_current[MAX_NUM_SLICES] = {0x01234, 0x01234, 0x01234, 0x01234};

102
103
104
// pointer to the slice specific scheduler
slice_scheduler_dl slice_sched_dl[MAX_NUM_SLICES] = {0};

105
106
//------------------------------------------------------------------------------
void
107
108
109
add_ue_dlsch_info(module_id_t module_idP,
		  int CC_id,
		  int UE_id, sub_frame_t subframeP, UE_DLSCH_STATUS status)
110
//------------------------------------------------------------------------------
111
{
112
  //LOG_D(MAC, "%s(module_idP:%d, CC_id:%d, UE_id:%d, subframeP:%d, status:%d) serving_num:%d rnti:%x\n", __FUNCTION__, module_idP, CC_id, UE_id, subframeP, status, eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num, UE_RNTI(module_idP,UE_id));
113

knopp's avatar
knopp committed
114
115
116
117
118
  eNB_dlsch_info[module_idP][CC_id][UE_id].rnti =
    UE_RNTI(module_idP, UE_id);
  //  eNB_dlsch_info[module_idP][CC_id][ue_mod_idP].weight           = weight;
  eNB_dlsch_info[module_idP][CC_id][UE_id].subframe = subframeP;
  eNB_dlsch_info[module_idP][CC_id][UE_id].status = status;
119

knopp's avatar
knopp committed
120
  eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num++;
121
122
123

}

124
125
//------------------------------------------------------------------------------
int
126
127
schedule_next_dlue(module_id_t module_idP, int CC_id,
		   sub_frame_t subframeP)
128
//------------------------------------------------------------------------------
129
{
130

knopp's avatar
knopp committed
131
132
  int next_ue;
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
133

knopp's avatar
knopp committed
134
135
136
137
138
  for (next_ue = UE_list->head; next_ue >= 0;
       next_ue = UE_list->next[next_ue]) {
    if (eNB_dlsch_info[module_idP][CC_id][next_ue].status ==
	S_DL_WAITING) {
      return next_ue;
139
    }
knopp's avatar
knopp committed
140
  }
141

knopp's avatar
knopp committed
142
143
144
145
  for (next_ue = UE_list->head; next_ue >= 0;
       next_ue = UE_list->next[next_ue]) {
    if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_BUFFERED) {
      eNB_dlsch_info[module_idP][CC_id][next_ue].status = S_DL_WAITING;
146
    }
knopp's avatar
knopp committed
147
  }
knopp's avatar
   
knopp committed
148

knopp's avatar
knopp committed
149
  return (-1);		//next_ue;
150
151
152

}

153
//------------------------------------------------------------------------------
154
int
155
156
157
158
159
160
161
162
163
generate_dlsch_header(unsigned char *mac_header,
		      unsigned char num_sdus,
		      unsigned short *sdu_lengths,
		      unsigned char *sdu_lcids,
		      unsigned char drx_cmd,
		      unsigned short timing_advance_cmd,
		      unsigned char *ue_cont_res_id,
		      unsigned char short_padding,
		      unsigned short post_padding)
164
//------------------------------------------------------------------------------
165
{
166

knopp's avatar
knopp committed
167
168
169
  SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *) mac_header;
  uint8_t first_element = 0, last_size = 0, i;
  uint8_t mac_header_control_elements[16], *ce_ptr;
170

knopp's avatar
knopp committed
171
  ce_ptr = &mac_header_control_elements[0];
172

knopp's avatar
knopp committed
173
  // compute header components
174

knopp's avatar
knopp committed
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  if ((short_padding == 1) || (short_padding == 2)) {
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element = 1;
    last_size = 1;
  }

  if (short_padding == 2) {
    mac_header_ptr->E = 1;
    mac_header_ptr++;
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    last_size = 1;
  }
191

knopp's avatar
knopp committed
192
193
194
195
196
197
  if (drx_cmd != 255) {
    if (first_element > 0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
    } else {
      first_element = 1;
198
    }
199

knopp's avatar
knopp committed
200
201
202
203
204
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = DRX_CMD;
    last_size = 1;
  }
205

knopp's avatar
knopp committed
206
207
208
209
210
211
  if (timing_advance_cmd != 31) {
    if (first_element > 0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
    } else {
      first_element = 1;
knopp's avatar
   
knopp committed
212
    }
213

knopp's avatar
knopp committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = TIMING_ADV_CMD;
    last_size = 1;
    //    msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
    ((TIMING_ADVANCE_CMD *) ce_ptr)->R = 0;
    AssertFatal(timing_advance_cmd < 64,
		"timing_advance_cmd %d > 63\n", timing_advance_cmd);
    ((TIMING_ADVANCE_CMD *) ce_ptr)->TA = timing_advance_cmd;	//(timing_advance_cmd+31)&0x3f;
    LOG_D(MAC, "timing advance =%d (%d)\n", timing_advance_cmd,
	  ((TIMING_ADVANCE_CMD *) ce_ptr)->TA);
    ce_ptr += sizeof(TIMING_ADVANCE_CMD);
    //msg("offset %d\n",ce_ptr-mac_header_control_elements);
  }
228

knopp's avatar
knopp committed
229
230
231
232
233
234
235
236
237
238
239
240
  if (ue_cont_res_id) {
    if (first_element > 0) {
      mac_header_ptr->E = 1;
      /*
	printf("[eNB][MAC] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
      */
      mac_header_ptr++;
    } else {
      first_element = 1;
knopp's avatar
   
knopp committed
241
    }
242

knopp's avatar
knopp committed
243
244
245
246
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = UE_CONT_RES;
    last_size = 1;
247

knopp's avatar
knopp committed
248
249
250
251
    LOG_T(MAC,
	  "[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n",
	  ue_cont_res_id[0], ue_cont_res_id[1], ue_cont_res_id[2],
	  ue_cont_res_id[3], ue_cont_res_id[4], ue_cont_res_id[5]);
252

knopp's avatar
knopp committed
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
    memcpy(ce_ptr, ue_cont_res_id, 6);
    ce_ptr += 6;
    // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
  }
  //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

  for (i = 0; i < num_sdus; i++) {
    LOG_T(MAC, "[eNB] Generate DLSCH header num sdu %d len sdu %d\n",
	  num_sdus, sdu_lengths[i]);

    if (first_element > 0) {
      mac_header_ptr->E = 1;
      /*msg("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
      */
      mac_header_ptr += last_size;
      //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
    } else {
      first_element = 1;
knopp's avatar
   
knopp committed
274
    }
275

knopp's avatar
knopp committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
    if (sdu_lengths[i] < 128) {
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->R = 0;
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->E = 0;
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->F = 0;
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L = (unsigned char) sdu_lengths[i];
      last_size = 2;
    } else {
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->R = 0;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->E = 0;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->F = 1;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_MSB = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_LSB = (unsigned short) sdu_lengths[i] & 0xff;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->padding = 0x00;
      last_size = 3;
292
#ifdef DEBUG_HEADER_PARSING
knopp's avatar
knopp committed
293
294
295
296
297
      LOG_D(MAC,
	    "[eNB] generate long sdu, size %x (MSB %x, LSB %x)\n",
	    sdu_lengths[i],
	    ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_MSB,
	    ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_LSB);
298
#endif
knopp's avatar
   
knopp committed
299
    }
knopp's avatar
knopp committed
300
  }
301

knopp's avatar
knopp committed
302
  /*
303

knopp's avatar
knopp committed
304
    printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
305

knopp's avatar
knopp committed
306
307
308
309
    printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
    ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
    ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
    ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
310
311


knopp's avatar
knopp committed
312
313
314
315
316
    if (((SCH_SUBHEADER_FIXED*)mac_header_ptr)->LCID < UE_CONT_RES) {
    if (((SCH_SUBHEADER_SHORT*)mac_header_ptr)->F == 0)
    printf("F = 0, sdu len (L field) %d\n",(((SCH_SUBHEADER_SHORT*)mac_header_ptr)->L));
    else
    printf("F = 1, sdu len (L field) %d\n",(((SCH_SUBHEADER_LONG*)mac_header_ptr)->L));
317
    }
knopp's avatar
knopp committed
318
319
320
321
322
323
324
325
326
327
328
329
330
  */
  if (post_padding > 0) {	// we have lots of padding at the end of the packet
    mac_header_ptr->E = 1;
    mac_header_ptr += last_size;
    // add a padding element
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    mac_header_ptr++;
  } else {			// no end of packet padding
    // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
    mac_header_ptr++;
  }
331

knopp's avatar
knopp committed
332
  //msg("After subheaders %d\n",(uint8_t*)mac_header_ptr - mac_header);
333

knopp's avatar
knopp committed
334
335
336
337
338
339
340
341
342
343
  if ((ce_ptr - mac_header_control_elements) > 0) {
    // printf("Copying %d bytes for control elements\n",ce_ptr-mac_header_control_elements);
    memcpy((void *) mac_header_ptr, mac_header_control_elements,
	   ce_ptr - mac_header_control_elements);
    mac_header_ptr +=
      (unsigned char) (ce_ptr - mac_header_control_elements);
  }
  //msg("After CEs %d\n",(uint8_t*)mac_header_ptr - mac_header);

  return ((unsigned char *) mac_header_ptr - mac_header);
344
345
}

346
347
//------------------------------------------------------------------------------
void
348
349
set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP,
	   int subframeP)
350
//------------------------------------------------------------------------------
351
352
{

knopp's avatar
knopp committed
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  UE_list_t *UE_list = &eNB->UE_list;
  unsigned char DAI;
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
  if (cc->tdd_Config != NULL) {	//TDD
    DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI - 1) & 3;
    LOG_D(MAC,
	  "[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n",
	  module_idP, CC_idP, frameP, subframeP, DAI, UE_idP);
    // Save DAI for Format 0 DCI

    switch (cc->tdd_Config->subframeAssignment) {
    case 0:
      //      if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6))
      break;
368

knopp's avatar
knopp committed
369
370
    case 1:
      switch (subframeP) {
371
      case 0:
knopp's avatar
knopp committed
372
373
374
      case 1:
	UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI;
	break;
375

knopp's avatar
knopp committed
376
      case 4:
377
378
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI;
        break;
379

380
      case 5:
knopp's avatar
knopp committed
381
      case 6:
382
383
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;
384

knopp's avatar
knopp committed
385
      case 9:
386
387
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;
knopp's avatar
knopp committed
388
      }
389

knopp's avatar
knopp committed
390
391
392
393
    case 2:
      //      if ((subframeP==3)||(subframeP==8))
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
      break;
394

knopp's avatar
knopp committed
395
    case 3:
396

knopp's avatar
knopp committed
397
398
399
400
401
402
403
404
405
406
      //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) {
      //  LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1);
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI;
      //}
      switch (subframeP) {
      case 5:
      case 6:
      case 1:
	UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
	break;
407

knopp's avatar
knopp committed
408
409
410
411
      case 7:
      case 8:
	UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
	break;
412

knopp's avatar
knopp committed
413
414
415
416
      case 9:
      case 0:
	UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI;
	break;
417

knopp's avatar
knopp committed
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
      default:
	break;
      }

      break;

    case 4:
      //      if ((subframeP==8)||(subframeP==9))
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
      break;

    case 5:
      //      if (subframeP==8)
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
      break;

    case 6:
      //      if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9))
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
      break;

    default:
      break;
knopp's avatar
   
knopp committed
441
    }
knopp's avatar
knopp committed
442
  }
knopp's avatar
   
knopp committed
443
444
}

445
446
//------------------------------------------------------------------------------
void
447
schedule_dlsch(module_id_t module_idP,
448
449
450
451
	        frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag)
//------------------------------------------------------------------------------{
{

452
  int i = 0;
453
454
455
456
457
458
459
460
461
462
463

  total_slice_percentage=0;
  avg_slice_percentage=1.0/n_active_slices;

  // reset the slice percentage for inactive slices
  for (i = n_active_slices; i< MAX_NUM_SLICES; i++) {
    slice_percentage[i]=0;
  }
  for (i = 0; i < n_active_slices; i++) {
    if (slice_percentage[i] < 0 ){
      LOG_W(MAC, "[eNB %d] frame %d subframe %d:invalid slice %d percentage %f. resetting to zero",
464
	    module_idP, frameP, subframeP, i, slice_percentage[i]);
465
466
467
468
469
470
471
472
473
474
      slice_percentage[i]=0;
    }
    total_slice_percentage+=slice_percentage[i];
  }

  for (i = 0; i < n_active_slices; i++) {

    // Load any updated functions
    if (update_dl_scheduler[i] > 0 ) {
      slice_sched_dl[i] = dlsym(NULL, dl_scheduler_type[i]);
475
      update_dl_scheduler[i] = 0 ;
476
477
478
479
480
481
482
483
484
485
      update_dl_scheduler_current[i] = 0;
      LOG_N(MAC,"update dl scheduler slice %d\n", i);
    }

    if (total_slice_percentage <= 1.0){ // the new total RB share is within the range

      // check if the number of slices has changed, and log
      if (n_active_slices_current != n_active_slices ){
	if ((n_active_slices > 0) && (n_active_slices <= MAX_NUM_SLICES)) {
	  LOG_N(MAC,"[eNB %d]frame %d subframe %d: number of active DL slices has changed: %d-->%d\n",
486
		module_idP, frameP, subframeP, n_active_slices_current, n_active_slices);
487
488
489
490
491
492
493
494
495
496
497
498

	  n_active_slices_current = n_active_slices;

	} else {
	  LOG_W(MAC,"invalid number of DL slices %d, revert to the previous value %d\n",n_active_slices, n_active_slices_current);
	  n_active_slices = n_active_slices_current;
	}
      }

      // check if the slice rb share has changed, and log the console
      if (slice_percentage_current[i] != slice_percentage[i]){ // new slice percentage
	LOG_N(MAC,"[eNB %d][SLICE %d][DL] frame %d subframe %d: total percentage %f-->%f, slice RB percentage has changed: %f-->%f\n",
499
	      module_idP, i, frameP, subframeP, total_slice_percentage_current, total_slice_percentage, slice_percentage_current[i], slice_percentage[i]);
500
501
502
503
504
505
506
507
508
	total_slice_percentage_current= total_slice_percentage;
	slice_percentage_current[i] = slice_percentage[i];

      }

      // check if the slice max MCS, and log the console
      if (slice_maxmcs_current[i] != slice_maxmcs[i]){
	if ((slice_maxmcs[i] >= 0) && (slice_maxmcs[i] < 29)){
	  LOG_N(MAC,"[eNB %d][SLICE %d][DL] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
509
		module_idP, i, frameP, subframeP, slice_maxmcs_current[i], slice_maxmcs[i]);
510
511
	  slice_maxmcs_current[i] = slice_maxmcs[i];
	} else {
512
	  LOG_W(MAC,"[eNB %d][SLICE %d][DL] invalid slice max mcs %d, revert the previous value %d\n",module_idP, i, slice_maxmcs[i],slice_maxmcs_current[i]);
513
514
515
516
517
518
519
	  slice_maxmcs[i]= slice_maxmcs_current[i];
	}
      }

      // check if a new scheduler, and log the console
      if (update_dl_scheduler_current[i] != update_dl_scheduler[i]){
	LOG_N(MAC,"[eNB %d][SLICE %d][DL] frame %d subframe %d: DL scheduler for this slice is updated: %s \n",
520
	      module_idP, i, frameP, subframeP, dl_scheduler_type[i]);
521
522
523
524
525
526
527
528
	update_dl_scheduler_current[i] = update_dl_scheduler[i];
      }

    } else {
      // here we can correct the values, e.g. reduce proportionally

      if (n_active_slices == n_active_slices_current){
	LOG_W(MAC,"[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
529
	      module_idP, i, total_slice_percentage_current, total_slice_percentage);
530
531
532
533
534
535
	if (slice_percentage[i] >= avg_slice_percentage){
	  slice_percentage[i]-=0.1;
	  total_slice_percentage-=0.1;
	}
      } else {
	LOG_W(MAC,"[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), revert the number of slice to its previous value (%d->%d)\n",
536
	      module_idP, i, total_slice_percentage_current, total_slice_percentage,
537
538
539
540
541
542
	      n_active_slices, n_active_slices_current );
	n_active_slices = n_active_slices_current;
	slice_percentage[i] = slice_percentage_current[i];
      }
    }

543
544
545
546
547
548
549
    // Check for new sorting policy
    if (sorting_policy_current[i] != sorting_policy[i]) {
      LOG_N(MAC,"[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
            module_idP, i, frameP, subframeP, sorting_policy_current[i], sorting_policy[i]);
      sorting_policy_current[i] = sorting_policy[i];
    }

550
    // Run each enabled slice-specific schedulers one by one
551
    slice_sched_dl[i](module_idP, i, frameP, subframeP, mbsfn_flag/*, dl_info*/);
552
553
554
  }

}
555

556
557
// changes to pre-processor for eMTC

558
559
//------------------------------------------------------------------------------
void
560
schedule_ue_spec(module_id_t module_idP,slice_id_t slice_idP,
561
		 frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag)
562
//------------------------------------------------------------------------------
563
{
564
  int CC_id;
knopp's avatar
knopp committed
565
  int UE_id;
566
  int aggregation;
knopp's avatar
knopp committed
567
  mac_rlc_status_resp_t rlc_status;
568
569
570
571
572
573
  int ta_len = 0;
  unsigned char sdu_lcids[NB_RB_MAX];
  int lcid, offset, num_sdus = 0;
  int nb_rb, nb_rb_temp, nb_available_rb;
  uint16_t sdu_lengths[NB_RB_MAX];
  int TBS, j, rnti, padding = 0, post_padding = 0;
knopp's avatar
knopp committed
574
  unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
575
576
  int round = 0;
  int harq_pid = 0;
knopp's avatar
knopp committed
577
  eNB_UE_STATS *eNB_UE_stats = NULL;
578
  int sdu_length_total = 0;
knopp's avatar
knopp committed
579
580
581
582
583
584

  eNB_MAC_INST *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc = eNB->common_channels;
  UE_list_t *UE_list = &eNB->UE_list;
  int continue_flag = 0;
  int32_t normalized_rx_power, target_rx_power;
585
  int tpc = 1;
knopp's avatar
knopp committed
586
587
588
589
590
591
592
593
594
595
596
  UE_sched_ctrl *ue_sched_ctl;
  int mcs;
  int i;
  int min_rb_unit[MAX_NUM_CCs];
  int N_RB_DL[MAX_NUM_CCs];
  int total_nb_available_rb[MAX_NUM_CCs];
  int N_RBG[MAX_NUM_CCs];
  nfapi_dl_config_request_body_t *dl_req;
  nfapi_dl_config_request_pdu_t *dl_config_pdu;
  int tdd_sfa;
  int ta_update;
597
598
  int header_length_last;
  int header_length_total;
nikaeinn's avatar
nikaeinn committed
599

600
#if 0
knopp's avatar
knopp committed
601
602
603
  if (UE_list->head == -1) {
    return;
  }
604
#endif
605

knopp's avatar
knopp committed
606
607
608
  start_meas(&eNB->schedule_dlsch);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
    (VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
609
610


knopp's avatar
knopp committed
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  // for TDD: check that we have to act here, otherwise return
  if (cc[0].tdd_Config) {
    tdd_sfa = cc[0].tdd_Config->subframeAssignment;
    switch (subframeP) {
    case 0:
      // always continue
      break;
    case 1:
      return;
      break;
    case 2:
      return;
      break;
    case 3:
      if ((tdd_sfa != 2) && (tdd_sfa != 5))
	return;
      break;
    case 4:
      if ((tdd_sfa != 1) && (tdd_sfa != 2) && (tdd_sfa != 4)
	  && (tdd_sfa != 5))
631
	return;
knopp's avatar
knopp committed
632
633
634
635
636
      break;
    case 5:
      break;
    case 6:
    case 7:
637
      if ((tdd_sfa != 3) && (tdd_sfa != 4) && (tdd_sfa != 5))
knopp's avatar
knopp committed
638
639
640
641
642
643
644
645
	return;
      break;
    case 8:
      if ((tdd_sfa != 2) && (tdd_sfa != 3) && (tdd_sfa != 4)
	  && (tdd_sfa != 5))
	return;
      break;
    case 9:
646
      if (tdd_sfa == 0)
knopp's avatar
knopp committed
647
648
	return;
      break;
Cedric Roux's avatar
Cedric Roux committed
649

650
    }
knopp's avatar
knopp committed
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
  }
  //weight = get_ue_weight(module_idP,UE_id);
  aggregation = 2;
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.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 (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(cc[CC_id].mib->message.dl_Bandwidth);

    // 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[CC_id];
    eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id];
    eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0;
    eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0;
  }
672

673
  /// CALLING Pre_Processor for downlink scheduling (Returns estimation of RBs required by each UE and the allocation on sub-band)
674

675
676
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
      (VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN);
knopp's avatar
   
knopp committed
677
  start_meas(&eNB->schedule_dlsch_preprocessor);
678
  dlsch_scheduler_pre_processor(module_idP,
679
                                slice_idP,
680
681
682
                                frameP,
                                subframeP,
                                N_RBG,
Xu Bo's avatar
Xu Bo committed
683
                                mbsfn_flag);
knopp's avatar
   
knopp committed
684
  stop_meas(&eNB->schedule_dlsch_preprocessor);
knopp's avatar
knopp committed
685
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
686
      (VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT);
687

knopp's avatar
knopp committed
688
689
  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id);
690

knopp's avatar
knopp committed
691
    dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
692

knopp's avatar
knopp committed
693
    if (mbsfn_flag[CC_id] > 0)
knopp's avatar
   
knopp committed
694
      continue;
695

knopp's avatar
knopp committed
696
697
698
699
    for (UE_id = UE_list->head; UE_id >= 0;
	 UE_id = UE_list->next[UE_id]) {
      continue_flag = 0;	// reset the flag to allow allocation for the remaining UEs
      rnti = UE_RNTI(module_idP, UE_id);
700
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
701
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
702

703

knopp's avatar
knopp committed
704
705
706
707
      if (rnti == NOT_A_RNTI) {
	LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n",
	      UE_id, UE_list->num_UEs);
	continue_flag = 1;
708
      }
709

knopp's avatar
knopp committed
710
      if (eNB_UE_stats == NULL) {
711
712
          LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n");
          continue_flag = 1;
713
      }
714
      if (!ue_slice_membership(UE_id, slice_idP))
715
                  continue;
716

knopp's avatar
knopp committed
717
718
      if (continue_flag != 1) {
	switch (get_tmode(module_idP, CC_id, UE_id)) {
719
720
721
	case 1:
	case 2:
	case 7:
knopp's avatar
knopp committed
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
	  aggregation =
	    get_aggregation(get_bw_index(module_idP, CC_id),
			    ue_sched_ctl->dl_cqi[CC_id],
			    format1);
	  break;
	case 3:
	  aggregation =
	    get_aggregation(get_bw_index(module_idP, CC_id),
			    ue_sched_ctl->dl_cqi[CC_id],
			    format2A);
	  break;
	default:
	  LOG_W(MAC, "Unsupported transmission mode %d\n",
		get_tmode(module_idP, CC_id, UE_id));
	  aggregation = 2;
737
	}
knopp's avatar
knopp committed
738
739
      }
      /* if (continue_flag != 1 */
Cedric Roux's avatar
Cedric Roux committed
740
      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||	// no RBs allocated
knopp's avatar
knopp committed
741
742
743
744
745
746
747
	  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
      }
knopp's avatar
   
knopp committed
748

knopp's avatar
knopp committed
749
750
751
752
753
754
755
756
757
      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);
      }
758

knopp's avatar
knopp committed
759
760
761
762
763
      if (continue_flag == 1) {
	add_ue_dlsch_info(module_idP,
			  CC_id, UE_id, subframeP, S_DL_NONE);
	continue;
      }
764
765
#warning RK->CR This old API call has to be revisited for FAPI, or logic must be changed
#if 0
knopp's avatar
knopp committed
766
767
768
769
770
      /* add "fake" DCI to have CCE_allocation_infeasible work properly for next allocations */
      /* if we don't add it, next allocations may succeed but overall allocations may fail */
      /* will be removed at the end of this function */
      add_ue_spec_dci(&eNB->common_channels[CC_id].DCI_pdu, &(char[]) {
	  0}, rnti, 1, aggregation, 1, format1, 0);
771
#endif
Cedric Roux's avatar
Cedric Roux committed
772

knopp's avatar
knopp committed
773
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
774

775
      harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
776

knopp's avatar
knopp committed
777
      round = ue_sched_ctl->round[CC_id][harq_pid];
778

knopp's avatar
knopp committed
779
780
781
782
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti      = rnti;
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = mac_eNB_get_rrc_status(module_idP, rnti);
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid   = harq_pid;
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
783
784


knopp's avatar
knopp committed
785
      if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED) continue;
786

787
      header_length_total = 0;
knopp's avatar
knopp committed
788
789
      sdu_length_total = 0;
      num_sdus = 0;
790

knopp's avatar
knopp committed
791
792
793
794
795
      /*
	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) {
nikaeinn's avatar
nikaeinn committed
796
		  eNB_UE_stats->dlsch_mcs1 = 10;//cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]];
knopp's avatar
knopp committed
797
      }
nikaeinn's avatar
nikaeinn committed
798
799
      else { // this operation is also done in the preprocessor
		  eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, slice_maxmcs[slice_idP]);  //cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
knopp's avatar
knopp committed
800
      }
801
802
803



knopp's avatar
knopp committed
804
805
      // store stats
      //UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
806

knopp's avatar
knopp committed
807
808
809
810
811
812
813
814
815
816
817
818
      // initializing the rb allocation indicator for each UE
      for (j = 0; j < N_RBG[CC_id]; j++) {
	UE_list->UE_template[CC_id][UE_id].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,
	    nb_available_rb, ue_sched_ctl->dl_cqi[CC_id],
	    eNB_UE_stats->dlsch_mcs1,
	    UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status);

Cedric Roux's avatar
Cedric Roux committed
819

knopp's avatar
knopp committed
820
821
822
823

      /* process retransmission  */

      if (round != 8) {
824

knopp's avatar
knopp committed
825
826
827
828
829
830
831
832
833
	// get freq_allocation
	nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
	TBS = get_TBS_DL(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid],
			 nb_rb);

	if (nb_rb <= nb_available_rb) {
	  if (cc[CC_id].tdd_Config != NULL) {
	    UE_list->UE_template[CC_id][UE_id].DAI++;
	    update_ul_dci(module_idP, CC_id, rnti,
834
			  UE_list->UE_template[CC_id][UE_id].DAI, subframeP);
835
	    LOG_D(MAC,
knopp's avatar
knopp committed
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
		  "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n",
		  CC_id, subframeP, UE_id,
		  UE_list->UE_template[CC_id][UE_id].DAI);
	  }

	  if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
	    for (j = 0; j < N_RBG[CC_id]; j++) {	// for indicating the rballoc for each sub-band
	      UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->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_ctl->rballoc_sub_UE[CC_id][j] == 1) {
		if (UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j])
		  printf("WARN: rballoc_subband not free for retrans?\n");
		UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->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;
859
		} else {
knopp's avatar
knopp committed
860
		  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
861
		}
knopp's avatar
knopp committed
862
	      }
863

knopp's avatar
knopp committed
864
865
866
	      j = j + 1;
	    }
	  }
867

knopp's avatar
knopp committed
868
869
870
871
	  nb_available_rb -= nb_rb;
	  /*
	    eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
	    eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
872

knopp's avatar
knopp committed
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
	    for(j=0; j<N_RBG[CC_id]; j++) {
	    eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
	    }
	  */

	  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_ctl->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;	// dont adjust power when retransmitting
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid];
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round & 3;
904

knopp's avatar
knopp committed
905
906
907
908
909
910
911
912
913
914
915
916
	    if (cc[CC_id].tdd_Config != NULL) {	//TDD
	      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].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,
		    (UE_list->UE_template[CC_id][UE_id].DAI - 1),
		    UE_list->UE_template[CC_id][UE_id].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,
		    UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]);
917

knopp's avatar
knopp committed
918
919
920
921
922
923
	    }
	    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;
Cedric Roux's avatar
Cedric Roux committed
924

knopp's avatar
knopp committed
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
	      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_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), round & 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_list->UE_template[CC_id][UE_id].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);

	      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);
970

knopp's avatar
knopp committed
971
972
973
974
975
976
977
978
979
980
981
982
983
	  //eNB_UE_stats->dlsch_trials[round]++;
	  UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission += 1;
	  UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = nb_rb;
	  UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx += nb_rb;
	  UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;
	  UE_list->eNB_UE_stats[CC_id][UE_id].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;
984

knopp's avatar
knopp committed
985
986
	// Now check RLC information to compute number of required RBs
	// get maximum TBS size for RLC request
987
	TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_available_rb);
988

knopp's avatar
knopp committed
989
	// add the length for  all the control elements (timing adv, drx, etc) : header + payload
990

knopp's avatar
knopp committed
991
992
993
994
995
996
997
998
999
	if (ue_sched_ctl->ta_timer == 0) {
	  ta_update = ue_sched_ctl->ta_update;
	  /* if we send TA then set timer to not send it for a while */
	  if (ta_update != 31) ue_sched_ctl->ta_timer = 20;
	  /* reset ta_update */
	  ue_sched_ctl->ta_update = 31;
	} else {
	  ta_update = 31;
	}
1000

knopp's avatar
knopp committed
1001
1002
	ta_len = (ta_update != 31) ? 2 : 0;

1003
1004
1005
	// 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,
1006
                                          TBS - ta_len - header_length_total - sdu_length_total - 3
1007
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1008
1009
1010
                                                    ,0, 0
#endif
                          );
knopp's avatar
knopp committed
1011
1012
1013

	  sdu_lengths[0] = 0;

1014
1015
	  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",
knopp's avatar
knopp committed
1016
		  module_idP, frameP, subframeP, CC_id,
1017
1018
1019
1020
		  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
1021
					      (char *)&dlsch_buffer[0]
1022
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1023
1024
1025
                          ,0, 0
#endif
                          );
1026

1027
            pthread_mutex_lock(&rrc_release_freelist);
Wu Jing's avatar
Wu Jing committed
1028
            if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)){
1029
1030
              uint16_t release_total = 0;
              for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
Wu Jing's avatar
Wu Jing committed
1031
1032
1033
1034
1035
1036
                if(rrc_release_info.RRC_release_ctrl[release_num].flag > 0){
                  release_total++;
                }else{
                  continue;
                }

1037
                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 1){
Wu Jing's avatar
Wu Jing committed
1038
1039
1040
1041
1042
1043
                  if(rrc_release_info.RRC_release_ctrl[release_num].rnti == rnti){
                    for(uint16_t mui_num = 0;mui_num < rlc_am_mui.rrc_mui_num;mui_num++){
                      if(rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]){
                        rrc_release_info.RRC_release_ctrl[release_num].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;
1044
1045
                      }
                    }
1046
1047
1048
                  }
                }
                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 2){
Wu Jing's avatar
Wu Jing committed
1049
1050
1051
                  if(rrc_release_info.RRC_release_ctrl[release_num].rnti == rnti){
                    for(uint16_t mui_num = 0;mui_num < rlc_am_mui.rrc_mui_num;mui_num++){
                      if(rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]){
1052
1053
1054
                        rrc_release_info.RRC_release_ctrl[release_num].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;
Wu Jing's avatar
Wu Jing committed
1055
                      }
1056
                    }
Wu Jing's avatar
Wu Jing committed
1057
                  }
1058
1059
1060
1061
1062
1063
                }
                if(release_total >= rrc_release_info.num_UEs)
                  break;
              }
            }
            pthread_mutex_unlock(&rrc_release_freelist);
Xu Bo's avatar
Xu Bo committed
1064
1065
1066

            RA_t *ra = &eNB->common_channels[CC_id].ra[0];
            for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++) {
Wu Jing's avatar
Wu Jing committed
1067
1068
1069
1070
1071
1072
1073
1074
              if((ra[ra_ii].rnti == rnti) && (ra[ra_ii].state == MSGCRNTI)){
                for(uint16_t mui_num = 0;mui_num < rlc_am_mui.rrc_mui_num;mui_num++){
                  if(ra[ra_ii].crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]){
                    ra[ra_ii].crnti_harq_pid = harq_pid;
                    ra[ra_ii].state = MSGCRNTI_ACK;
                    break;
                  }
                }
Xu Bo's avatar
Xu Bo committed
1075
1076
              }
            }
1077

knopp's avatar
knopp committed
1078
1079
1080
1081
1082
	    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]));

1083
	    LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",
knopp's avatar
knopp committed
1084
		  module_idP, CC_id, sdu_lengths[0]);
1085

knopp's avatar
knopp committed
1086
1087
	    sdu_length_total = sdu_lengths[0];
	    sdu_lcids[0] = DCCH;
shahab's avatar
shahab committed
1088
1089
            UE_list->eNB_UE_stats[CC_id][UE_id].lcid_sdu[0] = DCCH;
            UE_list->eNB_UE_stats[CC_id][UE_id].sdu_length_tx[DCCH] = sdu_lengths[0];
knopp's avatar
knopp committed
1090
1091
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH] += 1;
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH] += sdu_lengths[0];
1092
1093
1094
1095

            header_length_last = 1 + 1 + (sdu_lengths[0] >= 128);
            header_length_total += header_length_last;

knopp's avatar
knopp committed
1096
	    num_sdus = 1;
1097

1098
#ifdef DEBUG_eNB_SCHEDULER
knopp's avatar
knopp committed
1099
1100
1101
	    LOG_T(MAC,
		  "[eNB %d][DCCH] CC_id %d Got %d bytes :",
		  module_idP, CC_id, sdu_lengths[0]);
1102

knopp's avatar
knopp committed
1103
1104
1105
	    for (j = 0; j < sdu_lengths[0]; j++) {
	      LOG_T(MAC, "%x ", dlsch_buffer[j]);
	    }
1106

knopp's avatar
knopp committed
1107
	    LOG_T(MAC, "\n");
1108
#endif
knopp's avatar
knopp committed
1109
1110
	  }
	}
1111
1112
1113
1114

	// 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,
1115
                                          TBS - ta_len - header_length_total - sdu_length_total - 3
1116
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1117
1118
1119
                                                    ,0, 0
#endif
                                         );
1120

knopp's avatar
knopp committed
1121
1122
1123
1124
	  // DCCH SDU
	  sdu_lengths[num_sdus] = 0;

	  if (rlc_status.bytes_in_buffer > 0) {
1125
	    LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
knopp's avatar
knopp committed
1126
		  module_idP, frameP, CC_id,
1127
1128
1129
1130
		  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
1131
						      (char *)&dlsch_buffer[sdu_length_total]
1132
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1133
1134
1135
                          ,0, 0
#endif
	    );
knopp's avatar
knopp committed
1136
1137
1138
1139
1140
1141
1142
1143

	    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];
shahab's avatar
shahab committed
1144
1145
            UE_list->eNB_UE_stats[CC_id][UE_id].lcid_sdu[num_sdus] = DCCH1;
            UE_list->eNB_UE_stats[CC_id][UE_id].sdu_length_tx[DCCH1] = sdu_lengths[num_sdus];
1146
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1;
knopp's avatar
knopp committed
1147
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus];
1148
1149
1150
1151

            header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128);
            header_length_total += header_length_last;

knopp's avatar
knopp committed
1152
	    num_sdus++;
1153

nikaeinn's avatar
nikaeinn committed
1154
#ifdef DEBUG_eNB_SCHEDULER
knopp's avatar
knopp committed
1155
1156
1157
	    LOG_T(MAC,
		  "[eNB %d][DCCH1] CC_id %d Got %d bytes :",
		  module_idP, CC_id, sdu_lengths[num_sdus]);
1158

knopp's avatar
knopp committed
1159
1160
1161
	    for (j = 0; j < sdu_lengths[num_sdus]; j++) {
	      LOG_T(MAC, "%x ", dlsch_buffer[j]);
	    }
1162

knopp's avatar
knopp committed
1163
	    LOG_T(MAC, "\n");
nikaeinn's avatar
nikaeinn committed
1164
#endif
1165

knopp's avatar
knopp committed
1166
1167
	  }
	}
1168
1169

	// TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list).