eNB_scheduler_dlsch.c 74.9 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2
3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


nikaeinn's avatar
nikaeinn committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16
17
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
18
19
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20
21

  Contact Information
nikaeinn's avatar
nikaeinn committed
22
23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
nikaeinn's avatar
nikaeinn committed
27
28
29
30
31

*******************************************************************************/

/*! \file eNB_scheduler_dlsch.c
 * \brief procedures related to eNB for the DLSCH transport channel
32
 * \author  Navid Nikaein and Raymond Knopp
nikaeinn's avatar
nikaeinn committed
33
 * \date 2010 - 2014
34
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
35
 * \version 1.0
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 * @ingroup _mac

 */

#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/proto.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

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

62
63
#include "SIMULATION/TOOLS/defs.h" // for taus

64
65
66
67
68
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

#define ENABLE_MAC_PAYLOAD_DEBUG
knopp's avatar
   
knopp committed
69
//#define DEBUG_eNB_SCHEDULER 1
70

gauthier's avatar
gauthier committed
71

72

73
74
75
76
77
78
79
80
81
82
//------------------------------------------------------------------------------
void
add_ue_dlsch_info(
  module_id_t module_idP,
  int CC_id,
  int UE_id,
  sub_frame_t subframeP,
  UE_DLSCH_STATUS status
)
//------------------------------------------------------------------------------
83
{
84

85
86
87
88
  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;
89

90
  eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num++;
91
92
93

}

94
95
96
97
98
99
100
101
//------------------------------------------------------------------------------
int
schedule_next_dlue(
  module_id_t module_idP,
  int CC_id,
  sub_frame_t subframeP
)
//------------------------------------------------------------------------------
102
{
103

knopp's avatar
   
knopp committed
104
105
  int next_ue;
  UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list;
106

107
  for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) {
108
    if  (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) {
knopp's avatar
   
knopp committed
109
      return next_ue;
110
    }
111
  }
112
113

  for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) {
114
115
    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;
116
    }
knopp's avatar
   
knopp committed
117
118
119
  }

  return(-1);//next_ue;
120
121
122

}

123
124
125
//------------------------------------------------------------------------------
unsigned char
generate_dlsch_header(
126
127
128
129
130
131
132
133
134
  unsigned char* mac_header,
  unsigned char num_sdus,
  unsigned short *sdu_lengths,
  unsigned char *sdu_lcids,
  unsigned char drx_cmd,
  short timing_advance_cmd,
  unsigned char *ue_cont_res_id,
  unsigned char short_padding,
  unsigned short post_padding
135
136
)
//------------------------------------------------------------------------------
137
{
138
139
140
141
142
143
144
145
146
147

  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;

  ce_ptr = &mac_header_control_elements[0];

  // compute header components

  if ((short_padding == 1) || (short_padding == 2)) {
knopp's avatar
   
knopp committed
148
149
150
151
152
    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element=1;
    last_size=1;
153
  }
154

155
  if (short_padding == 2) {
knopp's avatar
   
knopp committed
156
157
158
159
160
161
    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;
162
163
164
  }

  if (drx_cmd != 255) {
knopp's avatar
   
knopp committed
165
166
167
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
168
    } else {
knopp's avatar
   
knopp committed
169
170
      first_element=1;
    }
171

knopp's avatar
   
knopp committed
172
173
174
175
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = DRX_CMD;
    last_size=1;
176
177
178
  }

  if (timing_advance_cmd != 0) {
knopp's avatar
   
knopp committed
179
180
181
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
182
    } else {
knopp's avatar
   
knopp committed
183
184
      first_element=1;
    }
185

knopp's avatar
   
knopp committed
186
187
188
189
190
191
    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;
knopp's avatar
   
knopp committed
192
    ((TIMING_ADVANCE_CMD *)ce_ptr)->TA=(timing_advance_cmd+31)&0x3f;
knopp's avatar
   
knopp committed
193
    LOG_D(MAC,"timing advance =%d (%d)\n",timing_advance_cmd,((TIMING_ADVANCE_CMD *)ce_ptr)->TA);
knopp's avatar
   
knopp committed
194
195
    ce_ptr+=sizeof(TIMING_ADVANCE_CMD);
    //msg("offset %d\n",ce_ptr-mac_header_control_elements);
196
197
198
  }

  if (ue_cont_res_id) {
knopp's avatar
   
knopp committed
199
200
201
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
202
203
204
205
      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);
knopp's avatar
   
knopp committed
206
207
      */
      mac_header_ptr++;
208
    } else {
knopp's avatar
   
knopp committed
209
210
      first_element=1;
    }
211

knopp's avatar
   
knopp committed
212
213
214
215
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = UE_CONT_RES;
    last_size=1;
216

knopp's avatar
   
knopp committed
217
    LOG_T(MAC,"[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n",
218
219
220
221
222
223
224
          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]);

knopp's avatar
   
knopp committed
225
226
227
    memcpy(ce_ptr,ue_cont_res_id,6);
    ce_ptr+=6;
    // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
228
229
230
231
  }

  //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

232
  for (i=0; i<num_sdus; i++) {
knopp's avatar
   
knopp committed
233
    LOG_T(MAC,"[eNB] Generate DLSCH header num sdu %d len sdu %d\n",num_sdus, sdu_lengths[i]);
234

knopp's avatar
   
knopp committed
235
236
237
    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,
238
239
240
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
knopp's avatar
   
knopp committed
241
242
243
      */
      mac_header_ptr+=last_size;
      //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
244
    } else {
knopp's avatar
   
knopp committed
245
246
      first_element=1;
    }
247

knopp's avatar
   
knopp committed
248
249
250
251
252
253
254
    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;
255
    } else {
knopp's avatar
   
knopp committed
256
257
258
259
260
261
262
263
      ((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;
264
#ifdef DEBUG_HEADER_PARSING
knopp's avatar
   
knopp committed
265
      LOG_D(MAC,"[eNB] generate long sdu, size %x (MSB %x, LSB %x)\n",
266
267
268
            sdu_lengths[i],
            ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB,
            ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB);
269
#endif
knopp's avatar
   
knopp committed
270
    }
271
  }
272

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  /*

    printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

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


    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));
    }
knopp's avatar
   
knopp committed
289
  */
290
  if (post_padding>0) {// we have lots of padding at the end of the packet
knopp's avatar
   
knopp committed
291
292
293
294
295
296
297
    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++;
298
  } else { // no end of packet padding
knopp's avatar
   
knopp committed
299
300
    // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
    mac_header_ptr++;
301
302
303
304
305
  }

  //msg("After subheaders %d\n",(uint8_t*)mac_header_ptr - mac_header);

  if ((ce_ptr-mac_header_control_elements) > 0) {
knopp's avatar
   
knopp committed
306
307
308
    // 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);
309
  }
310

311
312
313
314
315
316
  //msg("After CEs %d\n",(uint8_t*)mac_header_ptr - mac_header);

  return((unsigned char*)mac_header_ptr - mac_header);

}

317
318
319
320
321
322
323
324
325
326
327
//------------------------------------------------------------------------------
void
set_ul_DAI(
  int module_idP,
  int UE_idP,
  int CC_idP,
  int frameP,
  int subframeP,
  LTE_DL_FRAME_PARMS*  frame_parms[MAX_NUM_CCs]
)
//------------------------------------------------------------------------------
328
329
{

knopp's avatar
   
knopp committed
330
331
332
  eNB_MAC_INST         *eNB      = &eNB_mac_inst[module_idP];
  UE_list_t            *UE_list  = &eNB->UE_list;
  unsigned char         DAI;
333

knopp's avatar
   
knopp committed
334
335
  if (frame_parms[CC_idP]->frame_type == TDD) {
    DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI-1)&3;
336
    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);
knopp's avatar
   
knopp committed
337
    // Save DAI for Format 0 DCI
338

knopp's avatar
   
knopp committed
339
340
341
342
    switch (frame_parms[CC_idP]->tdd_config) {
    case 0:
      //      if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6))
      break;
343

knopp's avatar
   
knopp committed
344
345
346
    case 1:
      switch (subframeP) {
      case 1:
347
348
349
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI;
        break;

knopp's avatar
   
knopp committed
350
      case 4:
351
352
353
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI;
        break;

knopp's avatar
   
knopp committed
354
      case 6:
355
356
357
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

knopp's avatar
   
knopp committed
358
      case 9:
359
360
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;
knopp's avatar
   
knopp committed
361
      }
362

knopp's avatar
   
knopp committed
363
364
    case 2:
      //      if ((subframeP==3)||(subframeP==8))
365
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
366
      break;
367

knopp's avatar
   
knopp committed
368
    case 3:
369

knopp's avatar
   
knopp committed
370
371
372
373
      //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;
      //}
374
      switch (subframeP) {
knopp's avatar
   
knopp committed
375
376
377
      case 5:
      case 6:
      case 1:
378
379
380
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

knopp's avatar
   
knopp committed
381
382
      case 7:
      case 8:
383
384
385
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;

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

knopp's avatar
   
knopp committed
391
      default:
392
        break;
knopp's avatar
   
knopp committed
393
      }
394

knopp's avatar
   
knopp committed
395
      break;
396

knopp's avatar
   
knopp committed
397
398
    case 4:
      //      if ((subframeP==8)||(subframeP==9))
399
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
400
      break;
401

knopp's avatar
   
knopp committed
402
403
    case 5:
      //      if (subframeP==8)
404
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
405
      break;
406

knopp's avatar
   
knopp committed
407
408
    case 6:
      //      if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9))
409
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
410
      break;
411

knopp's avatar
   
knopp committed
412
413
414
415
416
417
    default:
      break;
    }
  }
}

418

419
420
421
//------------------------------------------------------------------------------
void
schedule_ue_spec(
422
423
424
  module_id_t   module_idP,
  frame_t       frameP,
  sub_frame_t   subframeP,
425
  int*          mbsfn_flag
426
427
)
//------------------------------------------------------------------------------
428
{
knopp's avatar
   
knopp committed
429

430
  uint8_t               CC_id;
knopp's avatar
   
knopp committed
431
  int                   UE_id;
432
  int                   N_RBG[MAX_NUM_CCs];
433
434
435
436
  unsigned char         aggregation;
  mac_rlc_status_resp_t rlc_status;
  unsigned char         header_len_dcch=0, header_len_dcch_tmp=0,header_len_dtch=0,header_len_dtch_tmp=0, ta_len=0;
  unsigned char         sdu_lcids[11],offset,num_sdus=0;
437
  uint16_t              nb_rb,nb_rb_temp,total_nb_available_rb[MAX_NUM_CCs],nb_available_rb;
438
  uint16_t              TBS,j,sdu_lengths[11],rnti,padding=0,post_padding=0;
439
440
441
442
443
  unsigned char         dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
  unsigned char         round            = 0;
  unsigned char         harq_pid         = 0;
  void                 *DLSCH_dci        = NULL;
  LTE_eNB_UE_stats     *eNB_UE_stats     = NULL;
444
  uint16_t              sdu_length_total = 0;
445
446
447
  //  uint8_t               dl_pow_off[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  //  unsigned char         rballoc_sub_UE[MAX_NUM_CCs][NUMBER_OF_UE_MAX][N_RBG_MAX];
  //  uint16_t              pre_nb_available_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
448
  int                   mcs;
449
  uint16_t              min_rb_unit[MAX_NUM_CCs];
knopp's avatar
   
knopp committed
450
451
  eNB_MAC_INST         *eNB      = &eNB_mac_inst[module_idP];
  UE_list_t            *UE_list  = &eNB->UE_list;
452
  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs];
nikaeinn's avatar
nikaeinn committed
453
  int                   continue_flag=0;
knopp's avatar
knopp committed
454
455
456
  int32_t                 normalized_rx_power, target_rx_power;
  int32_t                 tpc=1;
  static int32_t          tpc_accumulated=0;
457
  UE_sched_ctrl           *ue_sched_ctl;
458
  int i;
nikaeinn's avatar
nikaeinn committed
459

460
  if (UE_list->head==-1) {
461
    return;
462
  }
463

464
  start_meas(&eNB->schedule_dlsch);
gauthier's avatar
gauthier committed
465
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
466
467
468
469

  //weight = get_ue_weight(module_idP,UE_id);
  aggregation = 1; // set to the maximum aggregation level

470
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
471
    min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id);
472
    frame_parms[CC_id] = mac_xface->get_lte_frame_parms(module_idP,CC_id);
473
474
475
476
477
478
    // get number of PRBs less those used by common channels
    total_nb_available_rb[CC_id] = frame_parms[CC_id]->N_RB_DL;
    for (i=0;i<frame_parms[CC_id]->N_RB_DL;i++)
      if (eNB->common_channels[CC_id].vrb_map[i]!=0)
	total_nb_available_rb[CC_id]--;

479
480
    N_RBG[CC_id] = frame_parms[CC_id]->N_RBG;

481
    // store the global enb stats:
482
483
484
485
486
    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;
knopp's avatar
   
knopp committed
487
  }
488

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

gauthier's avatar
gauthier committed
491
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
knopp's avatar
   
knopp committed
492
  start_meas(&eNB->schedule_dlsch_preprocessor);
493
  dlsch_scheduler_pre_processor(module_idP,
494
495
496
497
                                frameP,
                                subframeP,
                                N_RBG,
                                mbsfn_flag);
knopp's avatar
   
knopp committed
498
  stop_meas(&eNB->schedule_dlsch_preprocessor);
gauthier's avatar
gauthier committed
499
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
knopp's avatar
   
knopp committed
500

501
502

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
503
    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id);
504

knopp's avatar
   
knopp committed
505
506
    if (mbsfn_flag[CC_id]>0)
      continue;
507
508

    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
509
      continue_flag=0; // reset the flag to allow allocation for the remaining UEs
knopp's avatar
   
knopp committed
510
      rnti = UE_RNTI(module_idP,UE_id);
511
      eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
512
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
513

514
      if (rnti==NOT_A_RNTI) {
515
516
517
        LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_list->num_UEs);
        // mac_xface->macphy_exit("Cannot find rnti for UE_id");
        continue_flag=1;
518
      }
519

520
      if (eNB_UE_stats==NULL) {
521
522
523
        LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
        //  mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n");
        continue_flag=1;
524
      }
525

526
527
528
      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||  // no RBs allocated 
	  CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti)
	  ) {
529
        LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
530
              module_idP, frameP, UE_id, CC_id);
531
532
533
534
        //if(mac_xface->get_transmission_mode(module_idP,rnti)==5)
        continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5
        // else
        //  break;
535
      }
536

knopp's avatar
   
knopp committed
537
      if (frame_parms[CC_id]->frame_type == TDD)  {
538
539
540
541
542
543
544
        set_ue_dai (subframeP,
                    frame_parms[CC_id]->tdd_config,
                    UE_id,
                    CC_id,
                    UE_list);
        // update UL DAI after DLSCH scheduling
        set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP,frame_parms);
knopp's avatar
   
knopp committed
545
546
      }

547
548
549
550
551
552
553
      if (continue_flag == 1 ) {
        add_ue_dlsch_info(module_idP,
                          CC_id,
                          UE_id,
                          subframeP,
                          S_DL_NONE);
        continue;
nikaeinn's avatar
nikaeinn committed
554
      }
555

556
557
558
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
      harq_pid = ue_sched_ctl->harq_pid[CC_id];
      round = ue_sched_ctl->round[CC_id];
559
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
560
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(module_idP,rnti);
561
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; 
562
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
563

564
565
      sdu_length_total=0;
      num_sdus=0;
566
567
568
569
570

      /*
      DevCheck(((eNB_UE_stats->DL_cqi[0] < MIN_CQI_VALUE) || (eNB_UE_stats->DL_cqi[0] > MAX_CQI_VALUE)),
      eNB_UE_stats->DL_cqi[0], MIN_CQI_VALUE, MAX_CQI_VALUE);
      */
571
      eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->DL_cqi[0]];
572
      eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
573

574

575
#ifdef EXMIMO
576

577
      if (mac_xface->get_transmission_mode(module_idP,CC_id, rnti)==5) {
578
        eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,16);
579
      }
580

581
#endif
582

583
      // store stats
knopp's avatar
   
knopp committed
584
      UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->DL_cqi[0];
585

586
      // initializing the rb allocation indicator for each UE
587
588
      for(j=0; j<frame_parms[CC_id]->N_RBG; j++) {
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
589
590
      }

591
      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",
592
593
            module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb,
            eNB_UE_stats->DL_cqi[0], eNB_UE_stats->dlsch_mcs1,
594
	    UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status);
595
596


597
598
      // Note this code is for a specific DCI format
      DLSCH_dci = (void *)UE_list->UE_template[CC_id][UE_id].DLSCH_DCI[harq_pid];
599
600


601
602
      /* process retransmission  */

603
      if (round > 0) {
604
605
606
607

        if (frame_parms[CC_id]->frame_type == TDD) {
          UE_list->UE_template[CC_id][UE_id].DAI++;
          update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI);
608
609
          LOG_D(MAC,"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);
610
611
612
613
614
615
616
        }

        // get freq_allocation
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];

        if (nb_rb <= nb_available_rb) {

617
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
618
            for(j=0; j<frame_parms[CC_id]->N_RBG; j++) { // for indicating the rballoc for each sub-band
619
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
620
            }
621
622
623
624
625
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

            while((nb_rb_temp > 0) && (j<frame_parms[CC_id]->N_RBG)) {
626
627
              if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
                UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
628
629
630

                if((j == frame_parms[CC_id]->N_RBG-1) &&
                    ((frame_parms[CC_id]->N_RB_DL == 25)||
631
                     (frame_parms[CC_id]->N_RB_DL == 50))) {
632
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
633
                } else {
634
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
635
                }
636
637
638
639
640
641
642
643
644
645
646
              }

              j = j+1;
            }
          }

          nb_available_rb -= nb_rb;
          aggregation = process_ue_cqi(module_idP,UE_id);


          PHY_vars_eNB_g[module_idP][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
647
          PHY_vars_eNB_g[module_idP][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
648

649
          for(j=0; j<frame_parms[CC_id]->N_RBG; j++) {
650
            PHY_vars_eNB_g[module_idP][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
651
          }
652
653
654
655
656
657
658
659
660
661
662
663

          switch (mac_xface->get_transmission_mode(module_idP,CC_id,rnti)) {
          case 1:
          case 2:
          default:
            switch (frame_parms[CC_id]->N_RB_DL) {
            case 6:
              if (frame_parms[CC_id]->frame_type == TDD) {
                //        ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->rv       = round&3;
                ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->dai      = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
664
665
                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),
666
                      ((DCI1_1_5MHz_TDD_t*)DLSCH_dci)->mcs);
667
668
669
670
              } else {
                //        ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->rv       = round&3;
671
672
                LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n",
                      module_idP,CC_id,harq_pid,round,((DCI1_1_5MHz_FDD_t*)DLSCH_dci)->mcs);
673
674
675
676
677
678
679
680
681
682
683

              }

              break;

            case 25:
              if (frame_parms[CC_id]->frame_type == TDD) {
                //        ((DCI1_5MHz_TDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_5MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_5MHz_TDD_t*)DLSCH_dci)->rv       = round&3;
                ((DCI1_5MHz_TDD_t*)DLSCH_dci)->dai      = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
684
685
                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),
686
                      ((DCI1_5MHz_TDD_t*)DLSCH_dci)->mcs);
687
688
689
690
              } else {
                //        ((DCI1_5MHz_FDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_5MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_5MHz_FDD_t*)DLSCH_dci)->rv       = round&3;
691
692
                LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n",
                      module_idP,CC_id,harq_pid,round,((DCI1_5MHz_FDD_t*)DLSCH_dci)->mcs);
693
694
695
696
697
698
699
700
701
702
703

              }

              break;

            case 50:
              if (frame_parms[CC_id]->frame_type == TDD) {
                //        ((DCI1_10MHz_TDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_10MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_10MHz_TDD_t*)DLSCH_dci)->rv       = round&3;
                ((DCI1_10MHz_TDD_t*)DLSCH_dci)->dai      = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
704
705
                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),
706
                      ((DCI1_10MHz_TDD_t*)DLSCH_dci)->mcs);
707
708
709
710
              } else {
                //        ((DCI1_10MHz_FDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_10MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_10MHz_FDD_t*)DLSCH_dci)->rv       = round&3;
711
712
                LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n",
                      module_idP,CC_id,harq_pid,round,((DCI1_10MHz_FDD_t*)DLSCH_dci)->mcs);
713
714
715
716
717
718
719
720
721
722
723

              }

              break;

            case 100:
              if (frame_parms[CC_id]->frame_type == TDD) {
                //        ((DCI1_20MHz_TDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_20MHz_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_20MHz_TDD_t*)DLSCH_dci)->rv       = round&3;
                ((DCI1_20MHz_TDD_t*)DLSCH_dci)->dai      = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
724
725
                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),
726
                      ((DCI1_20MHz_TDD_t*)DLSCH_dci)->mcs);
727
728
729
730
              } else {
                //        ((DCI1_20MHz_FDD_t*)DLSCH_dci)->ndi      = 0;
                ((DCI1_20MHz_FDD_t*)DLSCH_dci)->harq_pid = harq_pid;
                ((DCI1_20MHz_FDD_t*)DLSCH_dci)->rv       = round&3;
731
732
                LOG_D(MAC,"[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n",
                      module_idP,CC_id,harq_pid,round,((DCI1_20MHz_FDD_t*)DLSCH_dci)->mcs);
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

              }

              break;
            }

            break;

          case 4:
            //    if (nb_rb>10) {
            ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->ndi1 = 0;
            ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
            ((DCI2_5MHz_2A_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
            // }
            //else {
            //  ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->ndi1 = 0;
            // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
            // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->rv1 = round&3;
            // ((DCI2_5MHz_2A_L10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
            // }
            break;

          case 5:
            // if(nb_rb>10){
            //((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->mcs = eNB_UE_stats->DL_cqi[0]<<1;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi = 0;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv = round&3;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;

763
764
            if(ue_sched_ctl->dl_pow_off[CC_id] == 2) {
              ue_sched_ctl->dl_pow_off[CC_id] = 1;
765
            }
766

767
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = ue_sched_ctl->dl_pow_off[CC_id];
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
            // }
            break;

          case 6:
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->ndi = 0;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->harq_pid = harq_pid;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->rv = round&3;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dai = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3;
            ((DCI1E_5MHz_2A_M10PRB_TDD_t*)DLSCH_dci)->dl_power_off = 1;//dl_pow_off[UE_id];
            break;
          }

          add_ue_dlsch_info(module_idP,
                            CC_id,
                            UE_id,
                            subframeP,
                            S_DL_SCHEDULED);

          //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 {
793
794
          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);
795
796
797
798
799
800
801
802
803
804
805
        }
      } else { /* This is a potentially new SDU opportunity */

        rlc_status.bytes_in_buffer = 0;
        // Now check RLC information to compute number of required RBs
        // get maximum TBS size for RLC request
        //TBS = mac_xface->get_TBS(eNB_UE_stats->DL_cqi[0]<<1,nb_available_rb);
        TBS = mac_xface->get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
        // check first for RLC data on DCCH
        // add the length for  all the control elements (timing adv, drx, etc) : header + payload

806
        ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
807
808
809
810
811
812

        header_len_dcch = 2; // 2 bytes DCCH SDU subheader

        if ( TBS-ta_len-header_len_dcch > 0 ) {
          rlc_status = mac_rlc_status_ind(
                         module_idP,
813
                         rnti,
814
			 module_idP,
815
816
817
818
819
820
821
822
823
                         frameP,
                         ENB_FLAG_YES,
                         MBMS_FLAG_NO,
                         DCCH,
                         (TBS-ta_len-header_len_dcch)); // transport block set size

          sdu_lengths[0]=0;

          if (rlc_status.bytes_in_buffer > 0) {  // There is DCCH to transmit
824
825
            LOG_D(MAC,"[eNB %d] Frame %d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
                  module_idP,frameP,CC_id,TBS-header_len_dcch);
826
827
            sdu_lengths[0] += mac_rlc_data_req(
                                module_idP,
828
                                rnti,
829
				module_idP,
830
831
832
833
834
835
                                frameP,
                                ENB_FLAG_YES,
                                MBMS_FLAG_NO,
                                DCCH,
                                (char *)&dlsch_buffer[sdu_lengths[0]]);

836
            LOG_D(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",module_idP,CC_id,sdu_lengths[0]);
837
838
839
840
841
            sdu_length_total = sdu_lengths[0];
            sdu_lcids[0] = DCCH;
            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];
            num_sdus = 1;
842
#ifdef DEBUG_eNB_SCHEDULER
843
            LOG_T(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[0]);
844

845
            for (j=0; j<sdu_lengths[0]; j++) {
846
              LOG_T(MAC,"%x ",dlsch_buffer[j]);
847
            }
848
849
850
851
852
853
854
855
856
857
858
859
860

            LOG_T(MAC,"\n");
#endif
          } else {
            header_len_dcch = 0;
            sdu_length_total = 0;
          }
        }

        // check for DCCH1 and update header information (assume 2 byte sub-header)
        if (TBS-ta_len-header_len_dcch-sdu_length_total > 0 ) {
          rlc_status = mac_rlc_status_ind(
                         module_idP,
861
                         rnti,
862
			 module_idP,
863
864
865
866
867
868
869
870
                         frameP,
                         ENB_FLAG_YES,
                         MBMS_FLAG_NO,
                         DCCH+1,
                         (TBS-ta_len-header_len_dcch-sdu_length_total)); // transport block set size less allocations for timing advance and
          // DCCH SDU

          if (rlc_status.bytes_in_buffer > 0) {
871
872
            LOG_D(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
                  module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total);
873
874
            sdu_lengths[num_sdus] += mac_rlc_data_req(
                                       module_idP,
875
                                       rnti,
876
				       module_idP,
877
878
879
880
881
882
883
884
885
886
887
888
                                       frameP,
                                       ENB_FLAG_YES,
                                       MBMS_FLAG_NO,
                                       DCCH+1,
                                       (char *)&dlsch_buffer[sdu_lengths[0]]);

            sdu_lcids[num_sdus] = DCCH1;
            sdu_length_total += sdu_lengths[num_sdus];
            header_len_dcch += 2;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1]+=1;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1]+=sdu_lengths[num_sdus];
            num_sdus++;
889
            LOG_D(MAC,"[eNB %d] CC_id %d Got %d bytes for DCCH from RLC\n",module_idP,CC_id,sdu_lengths[0]);
890
891
892
893
894
895
896
897
          }
        }

        // check for DTCH and update header information
        // here we should loop over all possible DTCH

        header_len_dtch = 3; // 3 bytes DTCH SDU subheader

898
899
        LOG_D(MAC,"[eNB %d], Frame %d, DTCH->DLSCH, CC_id %d, Checking RLC status (rab %d, tbs %d, len %d)\n",
              module_idP,frameP,CC_id,DTCH,TBS,
900
901
902
903
904
              TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch);

        if (TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch > 0 ) {
          rlc_status = mac_rlc_status_ind(
                         module_idP,
905
                         rnti,
906
			 module_idP,
907
908
909
910
911
912
913
914
                         frameP,
                         ENB_FLAG_YES,
                         MBMS_FLAG_NO,
                         DTCH,
                         TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch);

          if (rlc_status.bytes_in_buffer > 0) {

915
916
            LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB], Frame %d, DTCH->DLSCH, CC_id %d, Requesting %d bytes from RLC (hdr len dtch %d)\n",
                  module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total-header_len_dtch,header_len_dtch);
917
918
            sdu_lengths[num_sdus] = mac_rlc_data_req(
                                      module_idP,
919
                                      rnti,
920
				      module_idP,
921
922
923
924
925
926
                                      frameP,
                                      ENB_FLAG_YES,
                                      MBMS_FLAG_NO,
                                      DTCH,
                                      (char*)&dlsch_buffer[sdu_length_total]);

927
928
            LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] CC_id %d Got %d bytes for DTCH %d \n",
                  module_idP,CC_id,sdu_lengths[num_sdus],DTCH);
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
            sdu_lcids[num_sdus] = DTCH;
            sdu_length_total += sdu_lengths[num_sdus];
            UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DTCH]+=1;
            UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DTCH]+=sdu_lengths[num_sdus];

            if (sdu_lengths[num_sdus] < 128) {
              header_len_dtch=2;
            }

            num_sdus++;
          } else {
            header_len_dtch = 0;
          }
        }

        // there is a payload
        if (((sdu_length_total + header_len_dcch + header_len_dtch )> 0)) {

          // Now compute number of required RBs for total sdu length
          // Assume RAH format 2
          // adjust  header lengths
          header_len_dcch_tmp = header_len_dcch;
          header_len_dtch_tmp = header_len_dtch;

          if (header_len_dtch==0) {
            header_len_dcch = (header_len_dcch >0) ? 1 : header_len_dcch;  // remove length field
          } else {
            header_len_dtch = (header_len_dtch > 0) ? 1 :header_len_dtch;     // remove length field for the last SDU
          }


          mcs = eNB_UE_stats->dlsch_mcs1;

962
963
964
965
966
          if (mcs==0) {
            nb_rb = 4;  // don't let the TBS get too small
          } else {
            nb_rb=min_rb_unit[CC_id];
          }
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982

          TBS = mac_xface->get_TBS_DL(mcs,nb_rb);

          while (TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len))  {
            nb_rb += min_rb_unit[CC_id];  //

            if (nb_rb>nb_available_rb) { // if we've gone beyond the maximum number of RBs
              // (can happen if N_RB_DL is odd)
              TBS = mac_xface->get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
              nb_rb = nb_available_rb;
              break;
            }

            TBS = mac_xface->get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rb);
          }

983
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
984
            for(j=0; j<frame_parms[CC_id]->N_RBG; j++) { // for indicating the rballoc for each sub-band
985
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
986
987
988
989
990
991
            }
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

            while((nb_rb_temp > 0) && (j<frame_parms[CC_id]->N_RBG)) {
992
993
              if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
                UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
994
995
996

                if ((j == frame_parms[CC_id]->N_RBG-1) &&
                    ((frame_parms[CC_id]->N_RB_DL == 25)||
997
                     (frame_parms[CC_id]->N_RB_DL == 50))) {
998
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
999
                } else {
1000
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
1001
                }
1002
1003
1004
1005
1006
1007
1008
              }

              j = j+1;
            }
          }

          PHY_vars_eNB_g[module_idP][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
1009
          PHY_vars_eNB_g[module_idP][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
1010

1011
          for(j=0; j<frame_parms[CC_id]->N_RBG; j++) {
1012
1013
            PHY_vars_eNB_g[module_idP][CC_id]->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];

1014
          }
1015
1016
1017
1018
1019
1020
1021
1022

          // decrease mcs until TBS falls below required length
          while ((TBS > (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && (mcs>0)) {
            mcs--;
            TBS = mac_xface->get_TBS_DL(mcs,nb_rb);
          }

          // if we have decreased too much or we don't have enough RBs, increase MCS
1023
1024
          while ((TBS < (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && ((( ue_sched_ctl->dl_pow_off[CC_id]>0) && (mcs<28))
                 || ( (ue_sched_ctl->dl_pow_off[CC_id]==0) && (mcs<=15)))) {
1025
1026
1027
1028
1029
1030
1031
            mcs++;
            TBS = mac_xface->get_TBS_DL(mcs,nb_rb);
          }

          LOG_D(MAC,"dlsch_mcs before and after the rate matching = (%d, %d)\n",eNB_UE_stats->dlsch_mcs1, mcs);

#ifdef DEBUG_eNB_SCHEDULER
1032
1033
          LOG_D(MAC,"[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n",
                module_idP,CC_id,mcs,TBS,nb_rb);
1034
1035
          // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
          //  TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
1036
#endif
1037
1038
1039
1040
1041
1042
1043
1044

          if ((TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len) <= 2) {
            padding = (TBS - header_len_dcch - header_len_dtch - sdu_length_total - ta_len);
            post_padding = 0;
          } else {
            padding = 0;

            // adjust the header len
1045
            if (header_len_dtch==0) {
1046
              header_len_dcch = header_len_dcch_tmp;
1047
            } else { //if (( header_len_dcch==0)&&((header_len_dtch==1)||(header_len_dtch==2)))
1048
              header_len_dtch = header_len_dtch_tmp;
1049
            }
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

            post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len ; // 1 is for the postpadding header
          }


          offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
                                         // offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0],
                                         num_sdus,              //num_sdus
                                         sdu_lengths,  //
                                         sdu_lcids,
                                         255,                                   // no drx
1061
                                         ue_sched_ctl->ta_update, // timing advance
1062
1063
1064
                                         NULL,                                  // contention res id
                                         padding,
                                         post_padding);