eNB_scheduler_dlsch.c 51.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * 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
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 * @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"

54
55
#include "SIMULATION/TOOLS/defs.h" // for taus

56
57
58
59
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

Cedric Roux's avatar
Cedric Roux committed
60
61
#include "T.h"

62
#define ENABLE_MAC_PAYLOAD_DEBUG
knopp's avatar
   
knopp committed
63
//#define DEBUG_eNB_SCHEDULER 1
64

65
extern RAN_CONTEXT_t RC;
66

67
68
69
70
71
72
73
74
75
76
//------------------------------------------------------------------------------
void
add_ue_dlsch_info(
  module_id_t module_idP,
  int CC_id,
  int UE_id,
  sub_frame_t subframeP,
  UE_DLSCH_STATUS status
)
//------------------------------------------------------------------------------
77
{
78

79
80
81
82
  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;
83

84
  eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num++;
85
86
87

}

88
89
90
91
92
93
94
95
//------------------------------------------------------------------------------
int
schedule_next_dlue(
  module_id_t module_idP,
  int CC_id,
  sub_frame_t subframeP
)
//------------------------------------------------------------------------------
96
{
97

knopp's avatar
   
knopp committed
98
  int next_ue;
99
  UE_list_t *UE_list=&RC.mac[module_idP]->UE_list;
100

101
  for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) {
102
    if  (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) {
knopp's avatar
   
knopp committed
103
      return next_ue;
104
    }
105
  }
106
107

  for (next_ue=UE_list->head; next_ue>=0; next_ue=UE_list->next[next_ue] ) {
108
109
    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;
110
    }
knopp's avatar
   
knopp committed
111
112
113
  }

  return(-1);//next_ue;
114
115
116

}

117
118
119
//------------------------------------------------------------------------------
unsigned char
generate_dlsch_header(
120
121
122
123
124
125
126
127
128
  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
129
130
)
//------------------------------------------------------------------------------
131
{
132
133
134
135
136
137
138
139
140
141

  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
142
143
144
145
146
    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element=1;
    last_size=1;
147
  }
148

149
  if (short_padding == 2) {
knopp's avatar
   
knopp committed
150
151
152
153
154
155
    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;
156
157
158
  }

  if (drx_cmd != 255) {
knopp's avatar
   
knopp committed
159
160
161
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
162
    } else {
knopp's avatar
   
knopp committed
163
164
      first_element=1;
    }
165

knopp's avatar
   
knopp committed
166
167
168
169
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = DRX_CMD;
    last_size=1;
170
171
172
  }

  if (timing_advance_cmd != 0) {
knopp's avatar
   
knopp committed
173
174
175
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
176
    } else {
knopp's avatar
   
knopp committed
177
178
      first_element=1;
    }
179

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

  if (ue_cont_res_id) {
knopp's avatar
   
knopp committed
193
194
195
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
196
197
198
199
      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
200
201
      */
      mac_header_ptr++;
202
    } else {
knopp's avatar
   
knopp committed
203
204
      first_element=1;
    }
205

knopp's avatar
   
knopp committed
206
207
208
209
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = UE_CONT_RES;
    last_size=1;
210

knopp's avatar
   
knopp committed
211
    LOG_T(MAC,"[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n",
212
213
214
215
216
217
218
          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
219
220
221
    memcpy(ce_ptr,ue_cont_res_id,6);
    ce_ptr+=6;
    // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
222
223
224
225
  }

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

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

knopp's avatar
   
knopp committed
229
230
231
    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,
232
233
234
      ((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
235
236
237
      */
      mac_header_ptr+=last_size;
      //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
238
    } else {
knopp's avatar
   
knopp committed
239
240
      first_element=1;
    }
241

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

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  /*

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

  //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
300
301
302
    // 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);
303
  }
304

305
306
307
308
309
310
  //msg("After CEs %d\n",(uint8_t*)mac_header_ptr - mac_header);

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

}

311
312
313
314
315
316
317
//------------------------------------------------------------------------------
void
set_ul_DAI(
  int module_idP,
  int UE_idP,
  int CC_idP,
  int frameP,
knopp's avatar
knopp committed
318
319
  int subframeP
) 
320
//------------------------------------------------------------------------------
321
322
{

323
  eNB_MAC_INST         *eNB      = RC.mac[module_idP];
knopp's avatar
   
knopp committed
324
325
  UE_list_t            *UE_list  = &eNB->UE_list;
  unsigned char         DAI;
knopp's avatar
knopp committed
326
327
  COMMON_channels_t    *cc       = &eNB->common_channels[CC_idP];
  if (cc->tdd_Config != NULL) {  //TDD
knopp's avatar
   
knopp committed
328
    DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI-1)&3;
329
    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
330
    // Save DAI for Format 0 DCI
331

knopp's avatar
knopp committed
332
    switch (cc->tdd_Config->subframeAssignment) {
knopp's avatar
   
knopp committed
333
334
335
    case 0:
      //      if ((subframeP==0)||(subframeP==1)||(subframeP==5)||(subframeP==6))
      break;
336

knopp's avatar
   
knopp committed
337
338
339
    case 1:
      switch (subframeP) {
      case 1:
340
341
342
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI;
        break;

knopp's avatar
   
knopp committed
343
      case 4:
344
345
346
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI;
        break;

knopp's avatar
   
knopp committed
347
      case 6:
348
349
350
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

knopp's avatar
   
knopp committed
351
      case 9:
352
353
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;
knopp's avatar
   
knopp committed
354
      }
355

knopp's avatar
   
knopp committed
356
357
    case 2:
      //      if ((subframeP==3)||(subframeP==8))
358
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
359
      break;
360

knopp's avatar
   
knopp committed
361
    case 3:
362

knopp's avatar
   
knopp committed
363
364
365
366
      //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;
      //}
367
      switch (subframeP) {
knopp's avatar
   
knopp committed
368
369
370
      case 5:
      case 6:
      case 1:
371
372
373
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

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

knopp's avatar
   
knopp committed
379
380
      case 9:
      case 0:
381
382
383
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI;
        break;

knopp's avatar
   
knopp committed
384
      default:
385
        break;
knopp's avatar
   
knopp committed
386
      }
387

knopp's avatar
   
knopp committed
388
      break;
389

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

knopp's avatar
   
knopp committed
395
396
    case 5:
      //      if (subframeP==8)
397
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
398
      break;
399

knopp's avatar
   
knopp committed
400
401
    case 6:
      //      if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9))
402
      //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
knopp's avatar
   
knopp committed
403
      break;
404

knopp's avatar
   
knopp committed
405
406
407
408
409
410
    default:
      break;
    }
  }
}

411

412
413
// changes to pre-processor for eMTC

414
415
416
//------------------------------------------------------------------------------
void
schedule_ue_spec(
417
418
419
  module_id_t   module_idP,
  frame_t       frameP,
  sub_frame_t   subframeP,
420
  int*          mbsfn_flag
421
422
)
//------------------------------------------------------------------------------
423
{
knopp's avatar
   
knopp committed
424

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  uint8_t                        CC_id;
  int                            UE_id;
  unsigned char                  aggregation;
  mac_rlc_status_resp_t          rlc_status;
  unsigned char                  header_len_dcch=0, header_len_dcch_tmp=0; 
  unsigned char                  header_len_dtch=0, header_len_dtch_tmp=0, header_len_dtch_last=0; 
  unsigned char                  ta_len=0;
  unsigned char                  sdu_lcids[NB_RB_MAX],lcid,offset,num_sdus=0;
  uint16_t                       nb_rb,nb_rb_temp,nb_available_rb;
  uint16_t                       TBS,j,sdu_lengths[NB_RB_MAX],rnti,padding=0,post_padding=0;
  unsigned char                  dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
  unsigned char                  round             = 0;
  unsigned char                  harq_pid          = 0;
  eNB_UE_STATS                   *eNB_UE_stats     = NULL;
  uint16_t                       sdu_length_total = 0;

  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;
  int32_t                        tpc=1;
  static int32_t                 tpc_accumulated=0;
  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_pdu_t  *dl_config_pdu;
  nfapi_tx_request_pdu_t         *TX_req;
nikaeinn's avatar
nikaeinn committed
457

458
#if 0
459
  if (UE_list->head==-1) {
460
    return;
461
  }
462
#endif
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

  //weight = get_ue_weight(module_idP,UE_id);
468
  aggregation = 2; 
469
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
knopp committed
470
    N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.dl_Bandwidth);
471
    min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id);
472
    // get number of PRBs less those used by common channels
knopp's avatar
knopp committed
473
474
475
    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)
476
477
	total_nb_available_rb[CC_id]--;

knopp's avatar
knopp committed
478
    N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth);
479

480
    // store the global enb stats:
knopp's avatar
knopp committed
481
482
    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];
483
    eNB->eNB_stats[CC_id].total_available_prbs +=  total_nb_available_rb[CC_id];
knopp's avatar
knopp committed
484
485
    eNB->eNB_stats[CC_id].dlsch_bytes_tx        = 0;
    eNB->eNB_stats[CC_id].dlsch_pdus_tx         = 0;
knopp's avatar
   
knopp committed
486
  }
487

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

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

500
501

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

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

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

513

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

519
      if (eNB_UE_stats==NULL) {
520
521
        LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
        continue_flag=1;
522
      }
523
524

      if (continue_flag != 1){
525
        switch(get_tmode(module_idP,CC_id,UE_id)){
526
527
528
529
        case 1:
        case 2:
        case 7:
	  aggregation = get_aggregation(get_bw_index(module_idP,CC_id), 
530
531
					eNB_UE_stats->dl_cqi,
					format1);
532
533
534
	  break;
        case 3:
	  aggregation = get_aggregation(get_bw_index(module_idP,CC_id), 
535
536
					eNB_UE_stats->dl_cqi,
					format2A);
537
538
	  break;
        default:
539
	  LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id));
540
541
542
543
	  aggregation = 2;
        }
      } /* if (continue_flag != 1 */

544
545
546
      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)
	  ) {
547
        LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
548
              module_idP, frameP, UE_id, CC_id);
549
        continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5
550
      }
551

knopp's avatar
knopp committed
552
      if (cc[CC_id].tdd_Config != NULL) { //TDD
553
554
555
        set_ue_dai (subframeP,
                    UE_id,
                    CC_id,
knopp's avatar
knopp committed
556
		    cc[CC_id].tdd_Config->subframeAssignment,
557
558
                    UE_list);
        // update UL DAI after DLSCH scheduling
knopp's avatar
knopp committed
559
        set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
knopp's avatar
   
knopp committed
560
561
      }

562
563
564
565
566
567
568
      if (continue_flag == 1 ) {
        add_ue_dlsch_info(module_idP,
                          CC_id,
                          UE_id,
                          subframeP,
                          S_DL_NONE);
        continue;
nikaeinn's avatar
nikaeinn committed
569
      }
570

571
572
573
      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];
574
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
575
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(module_idP,rnti);
576
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; 
577
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
578

579
580
      sdu_length_total=0;
      num_sdus=0;
581
582

      /*
583
584
      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);
585
      */
586
      eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->dl_cqi];
587
      eNB_UE_stats->dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;//cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
588

589

590
      // store stats
591
      UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
592

593
      // initializing the rb allocation indicator for each UE
knopp's avatar
knopp committed
594
      for(j=0; j<N_RBG[CC_id]; j++) {
595
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
596
597
      }

598
      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",
599
            module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb,
600
            eNB_UE_stats->dl_cqi, eNB_UE_stats->dlsch_mcs1,
601
	    UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status);
602
603
604



605
606
      /* process retransmission  */

607
      if (round > 0) {
608
609
610
611
        // get freq_allocation
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];

        if (nb_rb <= nb_available_rb) {
612
          if (cc[CC_id].tdd_Config != NULL) {
613
614
615
616
            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);
            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);
          }
617

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

knopp's avatar
knopp committed
626
            while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) {
627
628
              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];
629

knopp's avatar
knopp committed
630
631
632
                if((j == N_RBG[CC_id]-1) &&
                    ((N_RB_DL[CC_id] == 25)||
                     (N_RB_DL[CC_id] == 50))) {
633
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
634
                } else {
635
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
636
                }
637
638
639
640
641
642
643
              }

              j = j+1;
            }
          }

          nb_available_rb -= nb_rb;
knopp's avatar
knopp committed
644
645
646
	  /*
          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];
647

knopp's avatar
knopp committed
648
649
          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];
650
          }
knopp's avatar
knopp committed
651
	  */
652

653
          switch (get_tmode(module_idP,CC_id,UE_id)) {
654
655
          case 1:
          case 2:
Xiwen JIANG's avatar
Xiwen JIANG committed
656
          case 7:
657
          default:
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
	    dl_config_pdu                                                         = &eNB->DL_req[CC_id].dl_config_pdu_list[eNB->DL_req[CC_id].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                                               = 2+sizeof(nfapi_dl_config_dci_dl_pdu);
	    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),eNB_UE_stats->dl_cqi,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;

	    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]);
	      
	    }
	    if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,
					   dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
					   rnti)) {
	      eNB->DL_req[CC_id].number_dci++;
	      eNB->DL_req[CC_id].number_pdu++;
691

692
693
694
695
696
	    }
	    else {
	      // No TX request for retransmission (check if null request for FAPI)
	    }
	  }
697

698
699
700
701
702
703
704
705
706
707
708
709
710
	  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 {
711
712
          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);
713
714
        }
      } else { /* This is a potentially new SDU opportunity */
715
	
716
717
718
        rlc_status.bytes_in_buffer = 0;
        // Now check RLC information to compute number of required RBs
        // get maximum TBS size for RLC request
719
        TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
720
721
722
        // check first for RLC data on DCCH
        // add the length for  all the control elements (timing adv, drx, etc) : header + payload

723
        ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
724
725
726
727
728
729

        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,
730
                         rnti,
731
			 module_idP,
732
                         frameP,
733
			 subframeP,
734
735
736
737
738
739
740
741
                         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
742
743
            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);
knopp's avatar
knopp committed
744
745
746
747
748
749
750
751
            sdu_lengths[0] = mac_rlc_data_req(
					      module_idP,
					      rnti,
					      module_idP,
					      frameP,
					      ENB_FLAG_YES,
					      MBMS_FLAG_NO,
					      DCCH,
752
						  TBS, //not used
knopp's avatar
knopp committed
753
					      (char *)&dlsch_buffer[0]);
754

Cedric Roux's avatar
Cedric Roux committed
755
756
757
            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]));

758
            LOG_D(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",module_idP,CC_id,sdu_lengths[0]);
759
760
761
762
763
            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;
764
#ifdef DEBUG_eNB_SCHEDULER
765
            LOG_T(MAC,"[eNB %d][DCCH] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[0]);
766

767
            for (j=0; j<sdu_lengths[0]; j++) {
768
              LOG_T(MAC,"%x ",dlsch_buffer[j]);
769
            }
770
771
772
773
774
775
776
777

            LOG_T(MAC,"\n");
#endif
          } else {
            header_len_dcch = 0;
            sdu_length_total = 0;
          }
        }
knopp's avatar
knopp committed
778
	
779
780
781
782
        // 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,
783
                         rnti,
784
			 module_idP,
785
                         frameP,
786
						 subframeP,
787
788
789
790
791
                         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
knopp's avatar
knopp committed
792
	  sdu_lengths[num_sdus] = 0;
793
794

          if (rlc_status.bytes_in_buffer > 0) {
knopp's avatar
knopp committed
795
            LOG_I(MAC,"[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
796
                  module_idP,frameP,CC_id,TBS-header_len_dcch-sdu_length_total);
797
798
            sdu_lengths[num_sdus] += mac_rlc_data_req(
                                       module_idP,
799
                                       rnti,
800
				       module_idP,
801
802
803
804
                                       frameP,
                                       ENB_FLAG_YES,
                                       MBMS_FLAG_NO,
                                       DCCH+1,
805
									   TBS, //not used
knopp's avatar
knopp committed
806
                                       (char *)&dlsch_buffer[sdu_length_total]);
807

Cedric Roux's avatar
Cedric Roux committed
808
809
810
            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]));

811
812
813
814
815
            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];
816
	    num_sdus++;
nikaeinn's avatar
nikaeinn committed
817
818
#ifdef DEBUG_eNB_SCHEDULER
            LOG_T(MAC,"[eNB %d][DCCH1] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[num_sdus]);
819

nikaeinn's avatar
nikaeinn committed
820
821
            for (j=0; j<sdu_lengths[num_sdus]; j++) {
              LOG_T(MAC,"%x ",dlsch_buffer[j]);
822
823
            }

nikaeinn's avatar
nikaeinn committed
824
825
            LOG_T(MAC,"\n");
#endif
826

827
	  }
828
829
        }

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
	// assume the max dtch header size, and adjust it later
	header_len_dtch=0;
	header_len_dtch_last=0; // the header length of the last mac sdu
	// lcid has to be sorted before the actual allocation (similar struct as ue_list).
	for (lcid=NB_RB_MAX-1; lcid>=DTCH ; lcid--){
	  // TBD: check if the lcid is active
	  
	  header_len_dtch+=3; 
	  header_len_dtch_last=3;
	  LOG_D(MAC,"[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n",
		module_idP,frameP,lcid,TBS,
		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 ) { // NN: > 2 ? 
	    rlc_status = mac_rlc_status_ind(module_idP,
					    rnti,
					    module_idP,
					    frameP,
848
						subframeP,
849
850
851
852
853
854
855
856
					    ENB_FLAG_YES,
					    MBMS_FLAG_NO,
					    lcid,
					    TBS-ta_len-header_len_dcch-sdu_length_total-header_len_dtch);
	   

	    if (rlc_status.bytes_in_buffer > 0) {
	      
857
	      LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n",
858
		    module_idP,frameP,TBS-header_len_dcch-sdu_length_total-header_len_dtch,lcid, header_len_dtch);
859
860
861
862
863
864
865
	      sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
						       rnti,
						       module_idP,
						       frameP,
						       ENB_FLAG_YES,
						       MBMS_FLAG_NO,
						       lcid,
866
							   TBS,	//not used
867
						       (char*)&dlsch_buffer[sdu_length_total]);
Aikaterini Trilyraki's avatar
Aikaterini Trilyraki committed
868
869
870
	      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(lcid), T_INT(sdu_lengths[num_sdus]));

871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
	      LOG_D(MAC,"[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",module_idP,sdu_lengths[num_sdus],lcid);
	      sdu_lcids[num_sdus] = lcid;
	      sdu_length_total += sdu_lengths[num_sdus];
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid]+=1;
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid]+=sdu_lengths[num_sdus];
	      if (sdu_lengths[num_sdus] < 128) {
		header_len_dtch--;
		header_len_dtch_last--;
	      }
	      num_sdus++;
	    } // no data for this LCID
	    else {
	      header_len_dtch-=3;
	    }
	  } // no TBS left
	  else {
	    header_len_dtch-=3;
	    break; 
	  }
	}
	if (header_len_dtch == 0 )
	  header_len_dtch_last= 0;
	// there is at least one SDU 
	// if (num_sdus > 0 ){
	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 : 0;//header_len_dcch;  // remove length field
	  } else {
	    header_len_dtch_last-=1; // now use it to find how many bytes has to be removed for the last MAC SDU 
	    header_len_dtch = (header_len_dtch > 0) ? header_len_dtch - header_len_dtch_last  :header_len_dtch;     // remove length field for the last SDU
	  }
908
909
910

          mcs = eNB_UE_stats->dlsch_mcs1;

911
912
913
914
915
          if (mcs==0) {
            nb_rb = 4;  // don't let the TBS get too small
          } else {
            nb_rb=min_rb_unit[CC_id];
          }
916

917
          TBS = get_TBS_DL(mcs,nb_rb);
918
919
920
921
922
923

          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)
924
              TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
925
926
927
928
              nb_rb = nb_available_rb;
              break;
            }

929
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rb);
930
931
          }

932
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
knopp's avatar
knopp committed
933
            for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band
934
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
935
936
937
938
939
            }
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

knopp's avatar
knopp committed
940
            while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) {
941
942
              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];
943

knopp's avatar
knopp committed
944
945
946
                if ((j == N_RBG[CC_id]-1) &&
                    ((N_RB_DL[CC_id] == 25)||
                     (N_RB_DL[CC_id] == 50))) {
947
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
948
                } else {
949
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
950
                }
951
952
953
954
955
              }

              j = j+1;
            }
          }
knopp's avatar
knopp committed
956
	  /*
957
958
          RC.eNB[module_idP][CC_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
          RC.eNB[module_idP][CC_id]->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];
959

knopp's avatar
knopp committed
960
          for(j=0; j<N_RBG[CC_id]; j++) {
961
            RC.eNB[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];
962

963
          }
knopp's avatar
knopp committed
964
	  */
965
966
967
          // decrease mcs until TBS falls below required length
          while ((TBS > (sdu_length_total + header_len_dcch + header_len_dtch + ta_len)) && (mcs>0)) {
            mcs--;
968
            TBS = get_TBS_DL(mcs,nb_rb);
969
970
971
          }

          // if we have decreased too much or we don't have enough RBs, increase MCS
972
973
          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)))) {
974
            mcs++;
975
            TBS = get_TBS_DL(mcs,nb_rb);
976
977
978
979
980
          }

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

#ifdef DEBUG_eNB_SCHEDULER
981
982
          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);
983
984
          // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
          //  TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
985
#endif
986
987
988
989
990
991
992
993

          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
994
            if (header_len_dtch==0) {
995
              header_len_dcch = header_len_dcch_tmp;
996
            } else { //if (( header_len_dcch==0)&&((header_len_dtch==1)||(header_len_dtch==2)))
997
              header_len_dtch = header_len_dtch_tmp;