eNB_scheduler_dlsch.c 56.1 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
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

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) {
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
    }
111 112 113
  }

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

}

117 118 119
//------------------------------------------------------------------------------
unsigned char
generate_dlsch_header(
120 121 122 123 124
  unsigned char* mac_header,
  unsigned char num_sdus,
  unsigned short *sdu_lengths,
  unsigned char *sdu_lcids,
  unsigned char drx_cmd,
125
  unsigned short timing_advance_cmd,
126 127 128
  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)) {
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) {
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) {
159 160 161
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
162
    } else {
163 164
      first_element=1;
    }
165

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) {
173 174 175
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
176
    } else {
177 178
      first_element=1;
    }
179

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;
186 187
    AssertFatal(timing_advance_cmd < 64,"timing_advance_cmd %d > 63\n",timing_advance_cmd);
    ((TIMING_ADVANCE_CMD *)ce_ptr)->TA=timing_advance_cmd;//(timing_advance_cmd+31)&0x3f;
188
    LOG_D(MAC,"timing advance =%d (%d)\n",timing_advance_cmd,((TIMING_ADVANCE_CMD *)ce_ptr)->TA);
189 190
    ce_ptr+=sizeof(TIMING_ADVANCE_CMD);
    //msg("offset %d\n",ce_ptr-mac_header_control_elements);
191 192 193
  }

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

207 208 209 210
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = UE_CONT_RES;
    last_size=1;
211

212
    LOG_T(MAC,"[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n",
213 214 215 216 217 218 219
          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]);

220 221 222
    memcpy(ce_ptr,ue_cont_res_id,6);
    ce_ptr+=6;
    // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
223 224 225 226
  }

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

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

230 231 232
    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,
233 234 235
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
236 237 238
      */
      mac_header_ptr+=last_size;
      //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
239
    } else {
240 241
      first_element=1;
    }
242

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

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

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

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

  if ((ce_ptr-mac_header_control_elements) > 0) {
301 302 303
    // 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);
304
  }
305

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

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

}

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

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

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

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

344
      case 4:
345 346 347
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI;
        break;

348
      case 6:
349 350 351
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
        break;

352
      case 9:
353 354
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;
355
      }
356

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

362
    case 3:
363

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

375 376
      case 7:
      case 8:
377 378 379
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
        break;

380 381
      case 9:
      case 0:
382 383 384
        UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI;
        break;

385
      default:
386
        break;
387
      }
388

389
      break;
390

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

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

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

406 407 408 409 410 411
    default:
      break;
    }
  }
}

412

413 414
// changes to pre-processor for eMTC

415 416 417
//------------------------------------------------------------------------------
void
schedule_ue_spec(
418 419 420
  module_id_t   module_idP,
  frame_t       frameP,
  sub_frame_t   subframeP,
421
  int*          mbsfn_flag
422 423
)
//------------------------------------------------------------------------------
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
  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];
456
  nfapi_dl_config_request_body_t *dl_req;
457 458
  nfapi_dl_config_request_pdu_t  *dl_config_pdu;
  nfapi_tx_request_pdu_t         *TX_req;
459
  int                            tdd_sfa;
460

461
#if 0
462
  if (UE_list->head==-1) {
463
    return;
464
  }
465
#endif
466

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

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504

  // for TDD: check that we have to act here, otherwise return
  if (cc[0].tdd_Config) {
    tdd_sfa = cc[0].tdd_Config->subframeAssignment;
    switch (subframeP) {
    case 0:
      // always continue
       break;
    case 1:
      return;
	break;
    case 2:
      return;
      break;
    case 3:
      if ((tdd_sfa!=2) && (tdd_sfa!=5)) return;
      break;
    case 4:
      if ((tdd_sfa!=1)&&(tdd_sfa!=2)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return;
      break;
    case 5:
      break;
    case 6:
    case 7:
      if ((tdd_sfa!=1)&&(tdd_sfa!=2)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return;
      break;
    case 8:
      if ((tdd_sfa!=2)&&(tdd_sfa!=3)&&(tdd_sfa!=4)&&(tdd_sfa!=5)) return;
      break;
    case 9:
      if ((tdd_sfa!=1)&&(tdd_sfa!=3)&&(tdd_sfa!=4)&&(tdd_sfa!=6)) return;
      break;
   
    }
  }
505
  //weight = get_ue_weight(module_idP,UE_id);
506
  aggregation = 2; 
507
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
knopp committed
508
    N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.dl_Bandwidth);
509
    min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id);
510
    // get number of PRBs less those used by common channels
knopp's avatar
knopp committed
511 512 513
    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)
514 515
	total_nb_available_rb[CC_id]--;

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

518
    // store the global enb stats:
knopp's avatar
knopp committed
519 520
    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];
521
    eNB->eNB_stats[CC_id].total_available_prbs +=  total_nb_available_rb[CC_id];
knopp's avatar
knopp committed
522 523
    eNB->eNB_stats[CC_id].dlsch_bytes_tx        = 0;
    eNB->eNB_stats[CC_id].dlsch_pdus_tx         = 0;
524
  }
525

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

gauthier's avatar
gauthier committed
528
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_IN);
529
  start_meas(&eNB->schedule_dlsch_preprocessor);
530
  dlsch_scheduler_pre_processor(module_idP,
531 532 533 534
                                frameP,
                                subframeP,
                                N_RBG,
                                mbsfn_flag);
535
  stop_meas(&eNB->schedule_dlsch_preprocessor);
gauthier's avatar
gauthier committed
536
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
537

538 539

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

542 543
    dl_req        = &eNB->DL_req[CC_id].dl_config_request_body;

544 545
    if (mbsfn_flag[CC_id]>0)
      continue;
546 547

    for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) {
548
      continue_flag=0; // reset the flag to allow allocation for the remaining UEs
549
      rnti = UE_RNTI(module_idP,UE_id);
550
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
551
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
552

553

554
      if (rnti==NOT_A_RNTI) {
555 556
        LOG_D(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_list->num_UEs);
        continue_flag=1;
557
      }
558

559
      if (eNB_UE_stats==NULL) {
560 561
        LOG_D(MAC,"[eNB] Cannot find eNB_UE_stats\n");
        continue_flag=1;
562
      }
563 564

      if (continue_flag != 1){
565
        switch(get_tmode(module_idP,CC_id,UE_id)){
566 567 568 569
        case 1:
        case 2:
        case 7:
	  aggregation = get_aggregation(get_bw_index(module_idP,CC_id), 
570 571
					eNB_UE_stats->dl_cqi,
					format1);
572 573 574
	  break;
        case 3:
	  aggregation = get_aggregation(get_bw_index(module_idP,CC_id), 
575 576
					eNB_UE_stats->dl_cqi,
					format2A);
577 578
	  break;
        default:
579
	  LOG_W(MAC,"Unsupported transmission mode %d\n", get_tmode(module_idP,CC_id,UE_id));
580 581 582 583
	  aggregation = 2;
        }
      } /* if (continue_flag != 1 */

584 585 586
      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)
	  ) {
587
        LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
588
              module_idP, frameP, UE_id, CC_id);
589
        continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5
590
      }
591

knopp's avatar
knopp committed
592
      if (cc[CC_id].tdd_Config != NULL) { //TDD
593 594 595
        set_ue_dai (subframeP,
                    UE_id,
                    CC_id,
knopp's avatar
knopp committed
596
		    cc[CC_id].tdd_Config->subframeAssignment,
597 598
                    UE_list);
        // update UL DAI after DLSCH scheduling
knopp's avatar
knopp committed
599
        set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP);
600 601
      }

602 603 604 605 606 607 608
      if (continue_flag == 1 ) {
        add_ue_dlsch_info(module_idP,
                          CC_id,
                          UE_id,
                          subframeP,
                          S_DL_NONE);
        continue;
609
      }
610

611
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
612 613 614 615 616 617

      if (cc->tdd_Config) harq_pid = ((frameP*10)+subframeP)%10;
      else harq_pid = ((frameP*10)+subframeP)&7;

      round = ue_sched_ctl->round[CC_id][harq_pid];

618
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti= rnti;
619
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status=mac_eNB_get_rrc_status(module_idP,rnti);
620
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; 
621
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
622

623 624
      sdu_length_total=0;
      num_sdus=0;
625 626

      /*
627 628
      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);
629
      */
630
      eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[eNB_UE_stats->dl_cqi];
631
      eNB_UE_stats->dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;//cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
632

633

634
      // store stats
635
      UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
636

637
      // initializing the rb allocation indicator for each UE
knopp's avatar
knopp committed
638
      for(j=0; j<N_RBG[CC_id]; j++) {
639
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
640 641
      }

642
      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",
643
            module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb,
644
            eNB_UE_stats->dl_cqi, eNB_UE_stats->dlsch_mcs1,
645
	    UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status);
646 647 648



649 650
      /* process retransmission  */

651
      if (round != 8) {
652

653 654
        // get freq_allocation
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
655
	TBS = get_TBS_DL(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid],nb_rb);
656 657

        if (nb_rb <= nb_available_rb) {
658
          if (cc[CC_id].tdd_Config != NULL) {
659 660 661 662
            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);
          }
663

664
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
knopp's avatar
knopp committed
665
            for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band
666
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
667
            }
668 669 670 671
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

knopp's avatar
knopp committed
672
            while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) {
673 674
              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];
675

knopp's avatar
knopp committed
676 677 678
                if((j == N_RBG[CC_id]-1) &&
                    ((N_RB_DL[CC_id] == 25)||
                     (N_RB_DL[CC_id] == 50))) {
679
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
680
                } else {
681
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
682
                }
683 684 685 686 687 688 689
              }

              j = j+1;
            }
          }

          nb_available_rb -= nb_rb;
knopp's avatar
knopp committed
690 691 692
	  /*
          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];
693

knopp's avatar
knopp committed
694 695
          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];
696
          }
knopp's avatar
knopp committed
697
	  */
698

699
          switch (get_tmode(module_idP,CC_id,UE_id)) {
700 701
          case 1:
          case 2:
Xiwen JIANG's avatar
Xiwen JIANG committed
702
          case 7:
703
          default:
704
	    dl_config_pdu                                                         = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
705 706
	    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; 
707
	    dl_config_pdu->pdu_size                                               = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
708
	    dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                      = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
	    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)) {
736 737
	      dl_req->number_dci++;
	      dl_req->number_pdu++;
738
	      dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
739

740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
	      fill_nfapi_dlsch_config(eNB,dl_req,
				      TBS,
				      eNB->pdu_index[CC_id],
				      rnti,
				      0, // type 0 allocation from 7.1.6 in 36.213
				      0, // virtual_resource_block_assignment_flag, unused here
				      0,          // resource_block_coding, to be filled in later
				      getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]),
				      round&3   , // redundancy version
				      1, // transport blocks
				      0, // transport block to codeword swap flag
				      cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme
				      1, // number of layers
				      1, // number of subbands
			     //			     uint8_t codebook_index,
				      4, // UE category capacity
				      UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 
				      0, // delta_power_offset for TM5
				      0, // ngap
				      0, // nprb
				      cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode
				      0, //number of PRBs treated as one subband, not used here
				      0 // number of beamforming vectors, not used here
				      );

knopp's avatar
knopp committed
765
	      LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n",eNB->pdu_index[CC_id],round);
766

767 768 769
	      eNB->pdu_index[CC_id]++;
	      program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
	      // No TX request for retransmission (check if null request for FAPI)
770 771
	    }
	    else {
772 773
	      LOG_W(MAC,"Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n",
		    frameP,subframeP,UE_id,rnti);
774 775
	    }
	  }
776

777 778 779 780 781 782 783 784 785 786 787 788 789
	  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 {
790 791
          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);
792 793
        }
      } else { /* This is a potentially new SDU opportunity */
794
	
795 796 797
        rlc_status.bytes_in_buffer = 0;
        // Now check RLC information to compute number of required RBs
        // get maximum TBS size for RLC request
798
        TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
799 800 801
        // check first for RLC data on DCCH
        // add the length for  all the control elements (timing adv, drx, etc) : header + payload

802
        ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0;
803 804 805 806 807 808

        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,
809
                         rnti,
810
			 module_idP,
811
                         frameP,
812
			 subframeP,
813 814 815 816 817 818 819 820
                         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
821 822
            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
823 824 825 826 827 828 829 830
            sdu_lengths[0] = mac_rlc_data_req(
					      module_idP,
					      rnti,
					      module_idP,
					      frameP,
					      ENB_FLAG_YES,
					      MBMS_FLAG_NO,
					      DCCH,
831
					      TBS, //not used
knopp's avatar
knopp committed
832
					      (char *)&dlsch_buffer[0]);
833

Cedric Roux's avatar
Cedric Roux committed
834 835 836
            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]));

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

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

            LOG_T(MAC,"\n");
#endif
          } else {
            header_len_dcch = 0;
            sdu_length_total = 0;
          }
        }
knopp's avatar
knopp committed
857
	
858 859 860 861
        // 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,
862
                         rnti,
863
			 module_idP,
864
                         frameP,
865
						 subframeP,
866 867 868 869 870
                         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
871
	  sdu_lengths[num_sdus] = 0;
872 873

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

Cedric Roux's avatar
Cedric Roux committed
887 888 889
            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]));

890 891 892 893 894
            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];
895
	    num_sdus++;
nikaeinn's avatar
nikaeinn committed
896 897
#ifdef DEBUG_eNB_SCHEDULER
            LOG_T(MAC,"[eNB %d][DCCH1] CC_id %d Got %d bytes :",module_idP,CC_id,sdu_lengths[num_sdus]);
898

nikaeinn's avatar
nikaeinn committed
899 900
            for (j=0; j<sdu_lengths[num_sdus]; j++) {
              LOG_T(MAC,"%x ",dlsch_buffer[j]);
901 902
            }

nikaeinn's avatar
nikaeinn committed
903 904
            LOG_T(MAC,"\n");
#endif
905

906
	  }
907 908
        }

909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
	// 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,
927
						subframeP,
928 929 930 931 932 933 934 935
					    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) {
	      
936
	      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",
937
		    module_idP,frameP,TBS-header_len_dcch-sdu_length_total-header_len_dtch,lcid, header_len_dtch);
938 939 940 941 942 943 944
	      sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
						       rnti,
						       module_idP,
						       frameP,
						       ENB_FLAG_YES,
						       MBMS_FLAG_NO,
						       lcid,
945
							   TBS,	//not used
946
						       (char*)&dlsch_buffer[sdu_length_total]);
Aikaterini Trilyraki's avatar
Aikaterini Trilyraki committed
947 948 949
	      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]));

950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
	      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
	  }
987 988 989

          mcs = eNB_UE_stats->dlsch_mcs1;

990 991 992 993 994
          if (mcs==0) {
            nb_rb = 4;  // don't let the TBS get too small
          } else {
            nb_rb=min_rb_unit[CC_id];
          }
995

996
          TBS = get_TBS_DL(mcs,nb_rb);
997 998 999 1000 1001 1002

          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)
1003
              TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_available_rb);
1004 1005 1006 1007
              nb_rb = nb_available_rb;
              break;
            }

1008
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1,nb_rb);
1009 1010
          }

1011
          if(nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
knopp's avatar
knopp committed
1012
            for(j=0; j<N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band
1013
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
1014 1015 1016 1017 1018
            }
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

knopp's avatar
knopp committed
1019
            while((nb_rb_temp > 0) && (j<N_RBG[CC_id])) {
1020 1021
              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];
1022

knopp's avatar
knopp committed
1023 1024 1025
                if ((j == N_RBG[CC_id]-1) &&
                    ((N_RB_DL[CC_id] == 25)||
                     (N_RB_DL[CC_id] == 50))) {
1026
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]+1;
1027
                } else {
1028
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
1029
                }
1030 1031 1032 1033 1034 1035 1036 1037 1038
              }

              j = j+1;
            }
          }

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

          // if we have decreased too much or we don't have enough RBs, increase MCS
1043 1044
          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)))) {
1045
            mcs++;
1046
            TBS = get_TBS_DL(mcs,nb_rb);
1047 1048 1049 1050 1051
          }

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

#ifdef DEBUG_eNB_SCHEDULER
1052 1053
          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);
1054 1055
          // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
          //  TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
1056
#endif
1057 1058 1059 1060 1061 1062 1063 1064

          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