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

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

 */

32
#define _GNU_SOURCE
33

34 35 36
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "LAYER2/MAC/mac_extern.h"
37 38
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
39 40 41
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
42
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
43

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

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

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

#include "assertions.h"
53

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

58 59
#include <dlfcn.h>

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

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

65
#include "common/ran_context.h"
66
extern RAN_CONTEXT_t RC;
67
extern uint8_t nfapi_mode;
68

69 70
//------------------------------------------------------------------------------
void
71
add_ue_dlsch_info(module_id_t module_idP,
72 73
                  int CC_id,
                  int UE_id, sub_frame_t subframeP, UE_DLSCH_STATUS status)
74
//------------------------------------------------------------------------------
75
{
76
  //LOG_D(MAC, "%s(module_idP:%d, CC_id:%d, UE_id:%d, subframeP:%d, status:%d) serving_num:%d rnti:%x\n", __FUNCTION__, module_idP, CC_id, UE_id, subframeP, status, eNB_dlsch_info[module_idP][CC_id][UE_id].serving_num, UE_RNTI(module_idP,UE_id));
77

78
  eNB_dlsch_info[module_idP][CC_id][UE_id].rnti =
79
          UE_RNTI(module_idP, UE_id);
80 81 82
  //  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
//------------------------------------------------------------------------------
int
90
schedule_next_dlue(module_id_t module_idP, int CC_id,
91
                   sub_frame_t subframeP)
92
//------------------------------------------------------------------------------
93
{
94

95 96
  int next_ue;
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
97

98 99 100
  for (next_ue = UE_list->head; next_ue >= 0;
       next_ue = UE_list->next[next_ue]) {
    if (eNB_dlsch_info[module_idP][CC_id][next_ue].status ==
101
        S_DL_WAITING) {
102
      return next_ue;
103
    }
104
  }
105

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

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

}

117
//------------------------------------------------------------------------------
118
int
119
generate_dlsch_header(unsigned char *mac_header,
120 121 122 123 124 125 126 127
                      unsigned char num_sdus,
                      unsigned short *sdu_lengths,
                      unsigned char *sdu_lcids,
                      unsigned char drx_cmd,
                      unsigned short timing_advance_cmd,
                      unsigned char *ue_cont_res_id,
                      unsigned char short_padding,
                      unsigned short post_padding)
128
//------------------------------------------------------------------------------
129
{
130

131 132 133
  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;
134

135
  ce_ptr = &mac_header_control_elements[0];
136

137
  // compute header components
138

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
  if ((short_padding == 1) || (short_padding == 2)) {
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element = 1;
    last_size = 1;
  }

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

156 157 158 159 160 161
  if (drx_cmd != 255) {
    if (first_element > 0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
    } else {
      first_element = 1;
162
    }
163

164 165 166 167 168
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = DRX_CMD;
    last_size = 1;
  }
169

170 171 172 173 174 175
  if (timing_advance_cmd != 31) {
    if (first_element > 0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
    } else {
      first_element = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
176
    }
177

178 179 180 181 182 183 184
    mac_header_ptr->R = 0;
    mac_header_ptr->E = 0;
    mac_header_ptr->LCID = TIMING_ADV_CMD;
    last_size = 1;
    //    msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
    ((TIMING_ADVANCE_CMD *) ce_ptr)->R = 0;
    AssertFatal(timing_advance_cmd < 64,
185 186
                "timing_advance_cmd %d > 63\n", timing_advance_cmd);
    ((TIMING_ADVANCE_CMD *) ce_ptr)->TA = timing_advance_cmd;    //(timing_advance_cmd+31)&0x3f;
187
    LOG_D(MAC, "timing advance =%d (%d)\n", timing_advance_cmd,
188
          ((TIMING_ADVANCE_CMD *) ce_ptr)->TA);
189 190 191
    ce_ptr += sizeof(TIMING_ADVANCE_CMD);
    //msg("offset %d\n",ce_ptr-mac_header_control_elements);
  }
192

193 194 195 196 197 198 199 200 201 202 203 204
  if (ue_cont_res_id) {
    if (first_element > 0) {
      mac_header_ptr->E = 1;
      /*
	printf("[eNB][MAC] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
      */
      mac_header_ptr++;
    } else {
      first_element = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
205
    }
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,
213 214 215
          "[eNB ][RAPROC] Generate contention resolution msg: %x.%x.%x.%x.%x.%x\n",
          ue_cont_res_id[0], ue_cont_res_id[1], ue_cont_res_id[2],
          ue_cont_res_id[3], ue_cont_res_id[4], ue_cont_res_id[5]);
216

217 218 219 220 221 222 223 224
    memcpy(ce_ptr, ue_cont_res_id, 6);
    ce_ptr += 6;
    // msg("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
  }
  //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

  for (i = 0; i < num_sdus; i++) {
    LOG_T(MAC, "[eNB] Generate DLSCH header num sdu %d len sdu %d\n",
225
          num_sdus, sdu_lengths[i]);
226 227 228 229 230 231 232 233 234 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,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
      */
      mac_header_ptr += last_size;
      //msg("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
    } else {
      first_element = 1;
Raymond Knopp's avatar
 
Raymond Knopp committed
238
    }
239

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    if (sdu_lengths[i] < 128) {
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->R = 0;
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->E = 0;
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->F = 0;
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L = (unsigned char) sdu_lengths[i];
      last_size = 2;
    } else {
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->R = 0;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->E = 0;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->F = 1;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_MSB = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_LSB = (unsigned short) sdu_lengths[i] & 0xff;
      ((SCH_SUBHEADER_LONG *) mac_header_ptr)->padding = 0x00;
      last_size = 3;
256
#ifdef DEBUG_HEADER_PARSING
257
      LOG_D(MAC,
258 259 260 261
        "[eNB] generate long sdu, size %x (MSB %x, LSB %x)\n",
        sdu_lengths[i],
        ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_MSB,
        ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_LSB);
262
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
263
    }
264
  }
265

266
  /*
267

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

270 271 272 273
    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);
274 275


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

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

298 299 300
  if ((ce_ptr - mac_header_control_elements) > 0) {
    // printf("Copying %d bytes for control elements\n",ce_ptr-mac_header_control_elements);
    memcpy((void *) mac_header_ptr, mac_header_control_elements,
301
           ce_ptr - mac_header_control_elements);
302
    mac_header_ptr +=
303
            (unsigned char) (ce_ptr - mac_header_control_elements);
304 305 306 307
  }
  //msg("After CEs %d\n",(uint8_t*)mac_header_ptr - mac_header);

  return ((unsigned char *) mac_header_ptr - mac_header);
308 309
}

310 311
//------------------------------------------------------------------------------
void
312
set_ul_DAI(int module_idP, int UE_idP, int CC_idP, int frameP,
313
           int subframeP)
314
//------------------------------------------------------------------------------
315 316
{

317 318 319 320
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  UE_list_t *UE_list = &eNB->UE_list;
  unsigned char DAI;
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
321
  if (cc->tdd_Config != NULL) {    //TDD
322 323
    DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI - 1) & 3;
    LOG_D(MAC,
324 325
          "[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n",
          module_idP, CC_idP, frameP, subframeP, DAI, UE_idP);
326 327 328
    // Save DAI for Format 0 DCI

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

333 334 335 336 337
      case 1:
        switch (subframeP) {
        case 0:
        case 1:
          UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI;
338
        break;
339

340 341 342
        case 4:
          UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI;
          break;
343

344 345 346 347
        case 5:
        case 6:
          UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
          break;
348

349 350 351 352
        case 9:
          UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
          break;
        }
353

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

359
      case 3:
360

361 362 363 364 365 366 367 368 369 370
        //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) {
        //  LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1);
        //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI;
        //}
        switch (subframeP) {
          case 5:
          case 6:
          case 1:
            UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI;
            break;
371

372 373 374 375
          case 7:
          case 8:
            UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI;
            break;
376

377 378 379 380
          case 9:
          case 0:
            UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI;
            break;
381

382 383 384
          default:
            break;
        }
385

386
        break;
387

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

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

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

      default:
        break;
Raymond Knopp's avatar
 
Raymond Knopp committed
405
    }
406
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
407 408
}

409 410
//------------------------------------------------------------------------------
void
411
schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) {
412

413
  int i = 0;
414
  slice_info_t *sli = &RC.mac[module_idP]->slice_info;
415

416 417 418
  sli->tot_pct_dl = 0;
  sli->avg_pct_dl = 1.0 / sli->n_dl;
  sli->slice_counter = sli->n_dl;
419 420

  // reset the slice percentage for inactive slices
421 422
  for (i = sli->n_dl; i < MAX_NUM_SLICES; i++) {
    sli->dl[i].pct = 0;
423
  }
424 425
  for (i = 0; i < sli->n_dl; i++) {
    if (sli->dl[i].pct < 0) {
426
      LOG_W(MAC, "[eNB %d] frame %d subframe %d:invalid slice %d percentage %f. resetting to zero",
427 428
            module_idP, frameP, subframeP, i, sli->dl[i].pct);
      sli->dl[i].pct = 0;
429
    }
430
    sli->tot_pct_dl += sli->dl[i].pct;
431 432
  }

433
  // Check for *intra*slice share activation
434 435
  if (sli->intraslice_share_active_current != sli->intraslice_share_active) {
    if (sli->intraslice_share_active != 1 && sli->intraslice_share_active != 0) {
436 437
      LOG_W(MAC,
            "[eNB %d][DL] frame %d subframe %d: invalid intraslice sharing status (%d), revert to its previous value (%d)\n",
438 439
            module_idP, frameP, subframeP, sli->intraslice_share_active, sli->intraslice_share_active_current);
      sli->intraslice_share_active = sli->intraslice_share_active_current;
440 441
    } else {
      LOG_N(MAC, "[eNB %d][DL] frame %d subframe %d: intraslice sharing status has changed (%x-->%x)\n",
442 443
            module_idP, frameP, subframeP, sli->intraslice_share_active_current, sli->intraslice_share_active);
      sli->intraslice_share_active_current = sli->intraslice_share_active;
444 445 446 447
    }
  }

  // Check for *inter*slice share activation
448 449
  if (sli->interslice_share_active_current != sli->interslice_share_active) {
    if (sli->interslice_share_active != 1 && sli->interslice_share_active != 0) {
450 451
      LOG_W(MAC,
            "[eNB %d][DL] frame %d subframe %d: invalid interslice sharing status (%d), revert to its previous value (%d)\n",
452 453
            module_idP, frameP, subframeP, sli->interslice_share_active, sli->interslice_share_active_current);
      sli->interslice_share_active = sli->interslice_share_active_current;
454 455
    } else {
      LOG_N(MAC, "[eNB %d][DL] frame %d subframe %d: interslice sharing status has changed (%x-->%x)\n",
456 457
            module_idP, frameP, subframeP, sli->interslice_share_active_current, sli->interslice_share_active);
      sli->interslice_share_active_current = sli->interslice_share_active;
458 459 460
    }
  }

461
  for (i = 0; i < sli->n_dl; i++) {
462 463

    // Load any updated functions
464 465 466 467
    if (sli->dl[i].update_sched > 0) {
      sli->dl[i].sched_cb = dlsym(NULL, sli->dl[i].sched_name);
      sli->dl[i].update_sched = 0;
      sli->dl[i].update_sched_current = 0;
468
      LOG_I(MAC, "update dl scheduler slice %d\n", i);
469 470
    }

471
    if (sli->tot_pct_dl <= 1.0) { // the new total RB share is within the range
472 473

      // check if the number of slices has changed, and log
474 475
      if (sli->n_dl_current != sli->n_dl) {
        if ((sli->n_dl > 0) && (sli->n_dl <= MAX_NUM_SLICES)) {
476
          LOG_I(MAC, "[eNB %d]frame %d subframe %d: number of active DL slices has changed: %d-->%d\n",
477 478
                module_idP, frameP, subframeP, sli->n_dl_current, sli->n_dl);
          sli->n_dl_current = sli->n_dl;
479 480
        } else {
          LOG_W(MAC, "invalid number of DL slices %d, revert to the previous value %d\n",
481 482
                sli->n_dl, sli->n_dl_current);
          sli->n_dl = sli->n_dl_current;
483
        }
484 485 486
      }

      // check if the slice rb share has changed, and log the console
487
      if (sli->dl[i].pct_current != sli->dl[i].pct) { // new slice percentage
488 489
        LOG_I(MAC,
              "[eNB %d][SLICE %d][DL] frame %d subframe %d: total percentage %f-->%f, slice RB percentage has changed: %f-->%f\n",
490 491 492 493
              module_idP, i, frameP, subframeP, sli->tot_pct_dl_current, sli->tot_pct_dl,
              sli->dl[i].pct_current, sli->dl[i].pct);
        sli->tot_pct_dl_current = sli->tot_pct_dl;
        sli->dl[i].pct_current = sli->dl[i].pct;
494 495 496
      }

      // check if the slice max MCS, and log the console
497 498
      if (sli->dl[i].maxmcs_current != sli->dl[i].maxmcs) {
        if ((sli->dl[i].maxmcs >= 0) && (sli->dl[i].maxmcs < 29)) {
499
          LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice MAX MCS has changed: %d-->%d\n",
500 501
                module_idP, i, frameP, subframeP, sli->dl[i].maxmcs_current, sli->dl[i].maxmcs);
          sli->dl[i].maxmcs_current = sli->dl[i].maxmcs;
502 503
        } else {
          LOG_W(MAC, "[eNB %d][SLICE %d][DL] invalid slice max mcs %d, revert the previous value %d\n",
504 505
                module_idP, i, sli->dl[i].maxmcs, sli->dl[i].maxmcs_current);
          sli->dl[i].maxmcs = sli->dl[i].maxmcs_current;
506
        }
507 508 509
      }

      // check if a new scheduler, and log the console
510 511 512 513
      if (sli->dl[i].update_sched_current != sli->dl[i].update_sched) {
        LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: DL scheduler for this slice is updated: %s \n",
              module_idP, i, frameP, subframeP, sli->dl[i].sched_name);
        sli->dl[i].update_sched_current = sli->dl[i].update_sched;
514 515 516 517 518
      }

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

519
      if (sli->n_dl == sli->n_dl_current) {
520 521
        LOG_W(MAC,
              "[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
522 523 524 525
              module_idP, i, sli->tot_pct_dl_current, sli->tot_pct_dl);
        if (sli->dl[i].pct >= sli->avg_pct_dl) {
          sli->dl[i].pct -= 0.1;
          sli->tot_pct_dl -= 0.1;
526
        }
527
      } else {
528 529
        LOG_W(MAC,
              "[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), revert the number of slice to its previous value (%d->%d)\n",
530 531 532 533
              module_idP, i, sli->tot_pct_dl_current, sli->tot_pct_dl,
              sli->n_dl, sli->n_dl_current);
        sli->n_dl = sli->n_dl_current;
        sli->dl[i].pct = sli->dl[i].pct_current;
534 535 536
      }
    }

537
    // Check for new slice positions
538 539 540
    if (sli->dl[i].pos_low > sli->dl[i].pos_high ||
        sli->dl[i].pos_low < 0 ||
        sli->dl[i].pos_high > N_RBG_MAX) {
541 542
      LOG_W(MAC, "[eNB %d][SLICE %d][DL] invalid slicing position (%d-%d), using previous values (%d-%d)\n",
            module_idP, i,
543 544 545 546
            sli->dl[i].pos_low, sli->dl[i].pos_high,
            sli->dl[i].pos_low_current, sli->dl[i].pos_high_current);
      sli->dl[i].pos_low = sli->dl[i].pos_low_current;
      sli->dl[i].pos_high = sli->dl[i].pos_high_current;
547
    } else {
548
      if (sli->dl[i].pos_low_current != sli->dl[i].pos_low) {
549
        LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: start frequency has changed (%d-->%d)\n",
550 551
              module_idP, i, frameP, subframeP, sli->dl[i].pos_low_current, sli->dl[i].pos_low);
        sli->dl[i].pos_low_current = sli->dl[i].pos_low;
552
      }
553
      if (sli->dl[i].pos_high_current != sli->dl[i].pos_high) {
554
        LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: end frequency has changed (%d-->%d)\n",
555 556
              module_idP, i, frameP, subframeP, sli->dl[i].pos_high_current, sli->dl[i].pos_high);
        sli->dl[i].pos_high_current = sli->dl[i].pos_high;
557 558 559
      }
    }

560
    // Check for new sorting policy
561
    if (sli->dl[i].sorting_current != sli->dl[i].sorting) {
562
      LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
563 564
            module_idP, i, frameP, subframeP, sli->dl[i].sorting_current, sli->dl[i].sorting);
      sli->dl[i].sorting_current = sli->dl[i].sorting;
565 566 567
    }

    // Check for new slice isolation
568 569
    if (sli->dl[i].isol_current != sli->dl[i].isol) {
      if (sli->dl[i].isol != 1 && sli->dl[i].isol != 0) {
570 571
        LOG_W(MAC,
              "[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid slice isolation setting (%d), revert to its previous value (%d)\n",
572 573
              module_idP, i, frameP, subframeP, sli->dl[i].isol, sli->dl[i].isol_current);
        sli->dl[i].isol = sli->dl[i].isol_current;
574 575
      } else {
        LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice isolation setting has changed (%x-->%x)\n",
576 577
              module_idP, i, frameP, subframeP, sli->dl[i].isol_current, sli->dl[i].isol);
        sli->dl[i].isol_current = sli->dl[i].isol;
578 579 580 581
      }
    }

    // Check for new slice priority
582 583 584 585
    if (sli->dl[i].prio_current != sli->dl[i].prio) {
      LOG_I(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: slice priority setting has changed (%d-->%d)\n",
            module_idP, i, frameP, subframeP, sli->dl[i].prio_current, sli->dl[i].prio);
      sli->dl[i].prio_current = sli->dl[i].prio;
586 587
    }

588
    // Check for new accounting policy
589 590
    if (sli->dl[i].accounting_current != sli->dl[i].accounting) {
      if (sli->dl[i].accounting > 1 || sli->dl[i].accounting < 0) {
591 592
        LOG_W(MAC,
              "[eNB %d][SLICE %d][DL] frame %d subframe %d: invalid accounting policy (%d), revert to its previous value (%d)\n",
593 594
              module_idP, i, frameP, subframeP, sli->dl[i].accounting, sli->dl[i].accounting_current);
        sli->dl[i].accounting = sli->dl[i].accounting_current;
595
      } else {
596
        LOG_N(MAC, "[eNB %d][SLICE %d][DL] frame %d subframe %d: UE sorting policy has changed (%x-->%x)\n",
597 598
              module_idP, i, frameP, subframeP, sli->dl[i].accounting_current, sli->dl[i].accounting);
        sli->dl[i].accounting_current = sli->dl[i].accounting;
599 600 601
      }
    }

602
    // Run each enabled slice-specific schedulers one by one
603
    sli->dl[i].sched_cb(module_idP, i, frameP, subframeP, mbsfn_flag/*, dl_info*/);
604 605 606
  }

}
607

608 609
// changes to pre-processor for eMTC

610 611
//------------------------------------------------------------------------------
void
612 613
schedule_ue_spec(module_id_t module_idP, slice_id_t slice_idP,
                 frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag)
614
//------------------------------------------------------------------------------
615
{
616
  int CC_id;
617
  int UE_id;
618
  int aggregation;
619
  mac_rlc_status_resp_t rlc_status;
620 621 622 623 624 625
  int ta_len = 0;
  unsigned char sdu_lcids[NB_RB_MAX];
  int lcid, offset, num_sdus = 0;
  int nb_rb, nb_rb_temp, nb_available_rb;
  uint16_t sdu_lengths[NB_RB_MAX];
  int TBS, j, rnti, padding = 0, post_padding = 0;
626
  unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
627 628
  int round = 0;
  int harq_pid = 0;
629
  eNB_UE_STATS *eNB_UE_stats = NULL;
630
  int sdu_length_total = 0;
631 632 633 634 635 636

  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;
637
  int tpc = 1;
638 639 640
  UE_sched_ctrl *ue_sched_ctl;
  int mcs;
  int i;
641 642 643 644
  int min_rb_unit[NFAPI_CC_MAX];
  int N_RB_DL[NFAPI_CC_MAX];
  int total_nb_available_rb[NFAPI_CC_MAX];
  int N_RBG[NFAPI_CC_MAX];
645 646 647 648
  nfapi_dl_config_request_body_t *dl_req;
  nfapi_dl_config_request_pdu_t *dl_config_pdu;
  int tdd_sfa;
  int ta_update;
649 650
  int header_length_last;
  int header_length_total;
651

652
  start_meas(&eNB->schedule_dlsch);
653
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
654

655 656 657 658
  // 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) {
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 691 692
      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 != 3) && (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 == 0)
          return;
        break;
693
    }
694 695 696
  }
  //weight = get_ue_weight(module_idP,UE_id);
  aggregation = 2;
697
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
698 699 700 701 702 703
    N_RB_DL[CC_id] = to_prb(cc[CC_id].mib->message.dl_Bandwidth);
    min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id);
    // get number of PRBs less those used by common channels
    total_nb_available_rb[CC_id] = N_RB_DL[CC_id];
    for (i = 0; i < N_RB_DL[CC_id]; i++)
      if (cc[CC_id].vrb_map[i] != 0)
704
        total_nb_available_rb[CC_id]--;
705 706 707 708 709 710 711 712 713 714

    N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth);

    // store the global enb stats:
    eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs;
    eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id];
    eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id];
    eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0;
    eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0;
  }
715

716 717 718
  // CALLING Pre_Processor for downlink scheduling
  // (Returns estimation of RBs required by each UE and the allocation on sub-band)
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN);
719

Raymond Knopp's avatar
 
Raymond Knopp committed
720
  start_meas(&eNB->schedule_dlsch_preprocessor);
721
  dlsch_scheduler_pre_processor(module_idP,
722
                                slice_idP,
723 724
                                frameP,
                                subframeP,
725
                                mbsfn_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
726
  stop_meas(&eNB->schedule_dlsch_preprocessor);
727 728

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT);
729

730
  RC.mac[module_idP]->slice_info.slice_counter--;
731
  // Do the multiplexing and actual allocation only when all slices have been pre-processed.
732
  if (RC.mac[module_idP]->slice_info.slice_counter > 0) {
733 734 735 736 737
    stop_meas(&eNB->schedule_dlsch);
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT);
    return;
  }

738
  if (RC.mac[module_idP]->slice_info.interslice_share_active) {
739 740
    dlsch_scheduler_interslice_multiplexing(module_idP, frameP, subframeP);
  }
741 742

  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
743
    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id);
744

745
    dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
746

747
    if (mbsfn_flag[CC_id] > 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
748
      continue;
749

750 751
    for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
      continue_flag = 0; // reset the flag to allow allocation for the remaining UEs
752
      rnti = UE_RNTI(module_idP, UE_id);
753
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
754
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
755

756
      if (rnti == NOT_A_RNTI) {
757 758
        LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id, UE_list->num_UEs);
        continue_flag = 1;
759
      }
760

761
      if (eNB_UE_stats == NULL) {
762 763
        LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n");
        continue_flag = 1;
764
      }
765

766
      if (!ue_dl_slice_membership(module_idP, UE_id, slice_idP))
767
        continue;
768

769
      if (continue_flag != 1) {
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
        switch (get_tmode(module_idP, CC_id, UE_id)) {
          case 1:
          case 2:
          case 7:
            aggregation = get_aggregation(get_bw_index(module_idP, CC_id),
                                          ue_sched_ctl->dl_cqi[CC_id],
                                          format1);
            break;
          case 3:
            aggregation = get_aggregation(get_bw_index(module_idP, CC_id),
                                          ue_sched_ctl->dl_cqi[CC_id],
                                          format2A);
            break;
          default:
            LOG_W(MAC, "Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id));
            aggregation = 2;
        }
787
      }
788

789
      /* if (continue_flag != 1 */
Cedric Roux's avatar
Cedric Roux committed
790
      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||	// no RBs allocated
791 792 793 794 795 796 797
	  CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP,
				    aggregation, rnti)) {
	LOG_D(MAC,
	      "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n",
	      module_idP, frameP, UE_id, CC_id);
	continue_flag = 1;	//to next user (there might be rbs availiable for other UEs in TM5
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
798

799 800 801 802 803 804 805 806 807
      // If TDD
      if (cc[CC_id].tdd_Config != NULL) {    //TDD
        set_ue_dai(subframeP,
                   UE_id,
                   CC_id,
                   cc[CC_id].tdd_Config->subframeAssignment,
                   UE_list);
        // update UL DAI after DLSCH scheduling
        set_ul_DAI(module_idP, UE_id, CC_id, frameP, subframeP);
808
      }
809

810
      if (continue_flag == 1) {
811 812
        add_ue_dlsch_info(module_idP, CC_id, UE_id, subframeP, S_DL_NONE);
        continue;
813
      }
Cedric Roux's avatar
Cedric Roux committed
814

815
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
816
      harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
817

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

820
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti;
821
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = mac_eNB_get_rrc_status(module_idP, rnti);
822
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid;
823
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
824

825 826
      if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED)
        continue;
827

828
      header_length_total = 0;
829 830
      sdu_length_total = 0;
      num_sdus = 0;
831

832
      /*
833 834 835
      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);
836 837
      */
      if (nfapi_mode) {
838 839
        eNB_UE_stats->dlsch_mcs1 = 10; // cqi_to_mcs[ue_sched_ctl->dl_cqi[CC_id]];
      } else { // this operation is also done in the preprocessor
840
        eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,
841
                                        RC.mac[module_idP]->slice_info.dl[slice_idP].maxmcs);  // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
842
      }
843

844 845
      // Store stats
      // UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
846

847
      // Initializing the rb allocation indicator for each UE
848
      for (j = 0; j < N_RBG[CC_id]; j++) {
849
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
850 851 852
      }

      LOG_D(MAC,
853 854 855 856 857
            "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n",
            module_idP, frameP, UE_id, CC_id, rnti, harq_pid, round,
            nb_available_rb, ue_sched_ctl->dl_cqi[CC_id],
            eNB_UE_stats->dlsch_mcs1,
            UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status);
858 859 860

      /* process retransmission  */
      if (round != 8) {
861

862 863 864
        // get freq_allocation
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
        TBS = get_TBS_DL(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid], nb_rb);
865 866 867 868 869

	if (nb_rb <= nb_available_rb) {
	  if (cc[CC_id].tdd_Config != NULL) {
	    UE_list->UE_template[CC_id][UE_id].DAI++;
	    update_ul_dci(module_idP, CC_id, rnti,
870
			  UE_list->UE_template[CC_id][UE_id].DAI, subframeP);
871
	    LOG_D(MAC,
872 873 874 875 876
		  "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);
	  }

877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
          if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
            for (j = 0; j < N_RBG[CC_id]; ++j) { // for indicating the rballoc for each sub-band
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
            }
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

            while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) {
              if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
                if (UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j])
                  printf("WARN: rballoc_subband not free for retrans?\n");
                UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];

                if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || (N_RB_DL[CC_id] == 50))) {
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1;
                } else {
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
                }
              }
897

898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
              j = j + 1;
            }
          }

          nb_available_rb -= nb_rb;
          /*
          eNB->mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb;
          eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id];

          for(j = 0; j < N_RBG[CC_id]; ++j) {
            eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j];
          }
          */

          switch (get_tmode(module_idP, CC_id, UE_id)) {
            case 1:
            case 2:
            case 7:
            default:
              LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", rnti);

              dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
              memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
              dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
              dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1;
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level =
                      get_aggregation(get_bw_index(module_idP, CC_id),
                                      ue_sched_ctl->dl_cqi[CC_id],
                                      format1);
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti;
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power

              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid;
              dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't 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;

              // TDD
              if (cc[CC_id].tdd_Config != NULL) {
                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]);
953

954 955 956 957 958 959
	    }
	    if (!CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP,
					   dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, rnti)) {
	      dl_req->number_dci++;
	      dl_req->number_pdu++;
	      dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
Cedric Roux's avatar
Cedric Roux committed
960

961 962 963
	      eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP;
	      eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;

964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
                fill_nfapi_dlsch_config(eNB, dl_req, TBS, -1,
                                        /* retransmission, no pdu_index */
                                        rnti, 0, // type 0 allocation from 7.1.6 in 36.213
                                        0,    // virtual_resource_block_assignment_flag, unused here
                                        0,    // resource_block_coding, to be filled in later
                                        getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]),
                                        round & 3, // redundancy version
                                        1,    // transport blocks
                                        0,    // transport block to codeword swap flag
                                        cc[CC_id].p_eNB == 1 ? 0 : 1,    // transmission_scheme
                                        1,    // number of layers
                                        1,    // number of subbands
                        //                      uint8_t codebook_index,
                                        4,    // UE category capacity
                                        UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a,
                                        0,    // delta_power_offset for TM5
                                        0,    // ngap
                                        0,    // nprb
                                        cc[CC_id].p_eNB == 1 ? 1 : 2,    // transmission mode
                                        0,    //number of PRBs treated as one subband, not used here
                                        0    // number of beamforming vectors, not used here
                );

                LOG_D(MAC,
                      "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n",
                      eNB->pdu_index[CC_id], round);

                program_dlsch_acknak(module_idP, CC_id, UE_id, frameP, subframeP,
                                     dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
                // No TX request for retransmission (check if null request for FAPI)
              } else {
                LOG_W(MAC,
                      "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n",
                      frameP, subframeP, UE_id, rnti);
              }
          }
1000

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

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
	  //eNB_UE_stats->dlsch_trials[round]++;
	  UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission += 1;
	  UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = nb_rb;
	  UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx += nb_rb;
	  UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1;
	  UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1;
	} else {
	  LOG_D(MAC,
		"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
		module_idP, frameP, CC_id, UE_id);
	}
      } else {		/* This is a potentially new SDU opportunity */
	rlc_status.bytes_in_buffer = 0;
1016

1017 1018
	// Now check RLC information to compute number of required RBs
	// get maximum TBS size for RLC request
1019
	TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_available_rb);
1020

1021
	// add the length for  all the control elements (timing adv, drx, etc) : header + payload
1022

1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
        if (ue_sched_ctl->ta_timer == 0) {
          ta_update = ue_sched_ctl->ta_update;
          /* if we send TA then set timer to not send it for a while */
          if (ta_update != 31)
            ue_sched_ctl->ta_timer = 20;
          /* reset ta_update */
          ue_sched_ctl->ta_update = 31;
        } else {
          ta_update = 31;
        }
1033

1034
        ta_len = (ta_update != 31) ? 2 : 0;
1035

1036 1037 1038
	// RLC data on DCCH
	if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) {
	  rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH,
1039
                                          TBS - ta_len - header_length_total - sdu_length_total - 3
1040
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1041 1042 1043
                                                    ,0, 0
#endif
                          );
1044

1045
          sdu_lengths[0] = 0;
1046

1047 1048
	  if (rlc_status.bytes_in_buffer > 0) {
	    LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
1049
		  module_idP, frameP, subframeP, CC_id,
1050 1051 1052 1053
		  TBS - ta_len - header_length_total - sdu_length_total - 3);

	    sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH,
                                              TBS, //not used
1054
					      (char *)&dlsch_buffer[0]
1055
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1056 1057 1058
                          ,0, 0
#endif
                          );
1059

1060
            pthread_mutex_lock(&rrc_release_freelist);
wujing's avatar
wujing committed
1061
            if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)){
1062 1063
              uint16_t release_total = 0;
              for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
wujing's avatar
wujing committed
1064 1065 1066 1067 1068 1069
                if(rrc_release_info.RRC_release_ctrl[release_num].flag > 0){
                  release_total++;
                }else{
                  continue;
                }

1070
                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 1){
wujing's avatar
wujing committed
1071 1072 1073 1074 1075 1076
                  if(rrc_release_info.RRC_release_ctrl[release_num].rnti == rnti){
                    for(uint16_t mui_num = 0;mui_num < rlc_am_mui.rrc_mui_num;mui_num++){
                      if(rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]){
                        rrc_release_info.RRC_release_ctrl[release_num].flag = 3;
                        LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n",release_num,rnti,rlc_am_mui.rrc_mui[mui_num],mui_num);
                        break;
1077 1078
                      }
                    }
1079 1080 1081
                  }
                }
                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 2){
wujing's avatar
wujing committed
1082 1083 1084
                  if(rrc_release_info.RRC_release_ctrl[release_num].rnti == rnti){
                    for(uint16_t mui_num = 0;mui_num < rlc_am_mui.rrc_mui_num;mui_num++){
                      if(rrc_release_info.RRC_release_ctrl[release_num].rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]){
1085 1086 1087
                        rrc_release_info.RRC_release_ctrl[release_num].flag = 4;
                        LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n",release_num,rnti,rlc_am_mui.rrc_mui[mui_num],mui_num);
                        break;
wujing's avatar
wujing committed
1088
                      }
1089
                    }
wujing's avatar
wujing committed
1090
                  }
1091 1092 1093 1094 1095 1096
                }
                if(release_total >= rrc_release_info.num_UEs)
                  break;
              }
            }
            pthread_mutex_unlock(&rrc_release_freelist);
Xu Bo's avatar
Xu Bo committed
1097 1098 1099

            RA_t *ra = &eNB->common_channels[CC_id].ra[0];
            for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++) {
wujing's avatar
wujing committed
1100 1101 1102 1103 1104 1105 1106 1107
              if((ra[ra_ii].rnti == rnti) && (ra[ra_ii].state == MSGCRNTI)){
                for(uint16_t mui_num = 0;mui_num < rlc_am_mui.rrc_mui_num;mui_num++){
                  if(ra[ra_ii].crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]){
                    ra[ra_ii].crnti_harq_pid = harq_pid;
                    ra[ra_ii].state = MSGCRNTI_ACK;
                    break;
                  }
                }
Xu Bo's avatar
Xu Bo committed
1108 1109
              }
            }
1110

1111 1112 1113 1114
            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]));
1115

1116
	    LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",
1117
		  module_idP, CC_id, sdu_lengths[0]);
1118

1119 1120
	    sdu_length_total = sdu_lengths[0];
	    sdu_lcids[0] = DCCH;
1121 1122
            UE_list->eNB_UE_stats[CC_id][UE_id].lcid_sdu[0] = DCCH;
            UE_list->eNB_UE_stats[CC_id][UE_id].sdu_length_tx[DCCH] = sdu_lengths[0];
1123 1124
	    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];
1125 1126 1127 1128

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

1129
	    num_sdus = 1;
1130

1131
#ifdef DEBUG_eNB_SCHEDULER
1132 1133 1134
            LOG_T(MAC,
              "[eNB %d][DCCH] CC_id %d Got %d bytes :",
              module_idP, CC_id, sdu_lengths[0]);
1135

1136 1137 1138
            for (j = 0; j < sdu_lengths[0]; ++j) {
              LOG_T(MAC, "%x ", dlsch_buffer[j]);
            }
1139

1140
            LOG_T(MAC, "\n");
1141
#endif
1142 1143
	  }
	}
1144 1145 1146 1147

	// RLC data on DCCH1
	if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) {
	  rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1,
1148
                                          TBS - ta_len - header_length_total - sdu_length_total - 3
1149
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1150 1151 1152
                                                    ,0, 0
#endif
                                         );
1153

1154 1155 1156 1157
	  // DCCH SDU
	  sdu_lengths[num_sdus] = 0;

	  if (rlc_status.bytes_in_buffer > 0) {
1158
	    LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
1159
		  module_idP, frameP, CC_id,
1160 1161 1162 1163
		  TBS - ta_len - header_length_total - sdu_length_total - 3);

	    sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1,
                                                      TBS, //not used
1164
						      (char *)&dlsch_buffer[sdu_length_total]
1165
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1166 1167 1168
                          ,0, 0
#endif
	    );
1169

1170 1171 1172 1173
            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]));
1174 1175 1176

	    sdu_lcids[num_sdus] = DCCH1;
	    sdu_length_total += sdu_lengths[num_sdus];
1177 1178
            UE_list->eNB_UE_stats[CC_id][UE_id].lcid_sdu[num_sdus] = DCCH1;
            UE_list->eNB_UE_stats[CC_id][UE_id].sdu_length_tx[DCCH1] = sdu_lengths[num_sdus];
1179
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1;
1180
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus];
1181 1182 1183 1184

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

1185
	    num_sdus++;
1186

nikaeinn's avatar
nikaeinn committed
1187
#ifdef DEBUG_eNB_SCHEDULER
1188 1189 1190
            LOG_T(MAC,
              "[eNB %d][DCCH1] CC_id %d Got %d bytes :",
              module_idP, CC_id, sdu_lengths[num_sdus]);
1191

1192 1193 1194
            for (j = 0; j < sdu_lengths[num_sdus]; ++j) {
              LOG_T(MAC, "%x ", dlsch_buffer[j]);
            }
1195

1196
            LOG_T(MAC, "\n");
nikaeinn's avatar
nikaeinn committed
1197
#endif
1198

1199 1200
	  }
	}
1201 1202

	// TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list).
1203
	for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) {
1204
	  // TODO: check if the lcid is active
1205

1206
	  LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n",
1207
		module_idP, frameP, lcid, TBS,
1208
                TBS - ta_len - header_length_total - sdu_length_total - 3);
1209

1210
	  if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) {
1211 1212 1213 1214 1215 1216 1217 1218
	    rlc_status = mac_rlc_status_ind(module_idP,
					    rnti,
					    module_idP,
					    frameP,
					    subframeP,
					    ENB_FLAG_YES,
					    MBMS_FLAG_NO,
					    lcid,
1219
					    TBS - ta_len - header_length_total - sdu_length_total - 3
1220
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1221 1222 1223
                                                    ,0, 0
#endif
                                           );
1224 1225 1226



1227
	    if (rlc_status.bytes_in_buffer > 0) {
1228 1229 1230
	      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",
		    module_idP, frameP,
1231 1232 1233 1234 1235 1236
                    TBS - ta_len - header_length_total - sdu_length_total - 3,
		    lcid,
		    header_length_total);

	      sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid,
                                                       TBS, //not used
1237
						       (char *)&dlsch_buffer[sdu_length_total]
1238
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1239 1240 1241
                          ,0, 0
#endif
	      );
1242

1243 1244 1245 1246 1247 1248 1249 1250
	      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]));

	      LOG_D(MAC,
		    "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n",
		    module_idP, sdu_lengths[num_sdus], lcid);
1251

1252 1253
	      sdu_lcids[num_sdus] = lcid;
	      sdu_length_total += sdu_lengths[num_sdus];
1254
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid]++;
1255
              UE_list->eNB_UE_stats[CC_id][UE_id].lcid_sdu[num_sdus] = lcid;
Cedric Roux's avatar
Cedric Roux committed
1256
              UE_list->eNB_UE_stats[CC_id][UE_id].sdu_length_tx[lcid] = sdu_lengths[num_sdus];
1257 1258 1259 1260 1261
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[num_sdus];

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

1262
	      num_sdus++;
1263

1264 1265
	      UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
	    }
1266 1267
	  } else {
            // no TBS left
1268 1269 1270
	    break;
	  }
	}
1271 1272 1273 1274 1275 1276 1277 1278

        /* last header does not have length field */
        if (header_length_total) {
          header_length_total -= header_length_last;
          header_length_total++;
        }

	// there is at least one SDU or TA command
1279
	// if (num_sdus > 0 ){
1280
	if (ta_len + sdu_length_total + header_length_total > 0) {
1281 1282 1283 1284

	  // Now compute number of required RBs for total sdu length
	  // Assume RAH format 2

1285
          mcs = eNB_UE_stats->dlsch_mcs1;
1286

1287 1288 1289 1290 1291 1292
          if (mcs == 0) {
            nb_rb = 4;    // don't let the TBS get too small
          } else {
            nb_rb = min_rb_unit[CC_id];
          }
          TBS = get_TBS_DL(mcs, nb_rb);
1293

1294
	  while (TBS < sdu_length_total + header_length_total + ta_len) {
1295 1296 1297 1298
	    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)
1299
	      TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_available_rb);
1300 1301 1302 1303
	      nb_rb = nb_available_rb;
	      break;
	    }

1304 1305
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rb);
          }
1306

1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
          if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) {
            for (j = 0; j < N_RBG[CC_id]; ++j) {    // for indicating the rballoc for each sub-band
              UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
            }
          } else {
            nb_rb_temp = nb_rb;
            j = 0;

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

                if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || (N_RB_DL[CC_id] == 50))) {
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1;
                } else {
                  nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id];
                }
              }
1325

1326 1327 1328
              j = j + 1;
            }
          }
1329 1330

	  // decrease mcs until TBS falls below required length
1331
	  while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) {
1332 1333 1334 1335 1336
	    mcs--;
	    TBS = get_TBS_DL(mcs, nb_rb);
	  }

	  // if we have decreased too much or we don't have enough RBs, increase MCS
1337
	  while ((TBS < sdu_length_total + header_length_total + ta_len)
1338 1339 1340 1341 1342 1343 1344 1345
		 && (((ue_sched_ctl->dl_pow_off[CC_id] > 0)
		      && (mcs < 28))
		     || ((ue_sched_ctl->dl_pow_off[CC_id] == 0)
			 && (mcs <= 15)))) {
	    mcs++;
	    TBS = get_TBS_DL(mcs, nb_rb);
	  }

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

#ifdef DEBUG_eNB_SCHEDULER
1351 1352 1353 1354 1355
          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);
          // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n",
          //  TBS, sdu_length_total, offset, TBS-sdu_length_total-offset);
1356
#endif
1357

1358 1359
	  if (TBS - header_length_total - sdu_length_total - ta_len <= 2) {
	    padding = TBS - header_length_total - sdu_length_total - ta_len;
1360 1361 1362
	    post_padding = 0;
	  } else {
	    padding = 0;
1363
	    post_padding = 1;
1364 1365
	  }

1366 1367 1368 1369 1370 1371 1372
          offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
                                         num_sdus,    //num_sdus
                                         sdu_lengths,    //
                                         sdu_lcids, 255,    // no drx
                                         ta_update,    // timing advance
                                         NULL,    // contention res id
                                         padding, post_padding);
1373 1374 1375 1376

	  //#ifdef DEBUG_eNB_SCHEDULER
	  if (ta_update != 31) {
	    LOG_D(MAC,
1377
		  "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n",
1378 1379 1380 1381
		  module_idP, frameP, UE_id, CC_id,
		  sdu_length_total, num_sdus, sdu_lengths[0],
		  sdu_lcids[0], offset, ta_update, padding,
		  post_padding, mcs, TBS, nb_rb,
1382
		  header_length_total);
1383 1384
	  }
	  //#endif
1385
#ifdef DEBUG_eNB_SCHEDULER
1386
          LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n");
1387

1388 1389 1390
          for (i = 0; i < 16; ++i) {
            LOG_T(MAC, "%x.", dlsch_buffer[i]);
          }
1391

1392
          LOG_T(MAC, "\n");
1393
#endif
Cedric Roux's avatar
Cedric Roux committed
1394

1395 1396 1397
          // cycle through SDUs and place in dlsch_buffer
          memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], dlsch_buffer, sdu_length_total);
          // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]);
1398

1399 1400 1401 1402
	  // fill remainder of DLSCH with 0
	  for (j = 0; j < (TBS - sdu_length_total - offset); j++) {
	    UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset + sdu_length_total + j] = 0;
	  }
1403

1404
	  if (opt_enabled == 1) {
laurent's avatar
laurent committed
1405 1406 1407
	    trace_pdu(DIRECTION_DOWNLINK,
		      (uint8_t *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
		      TBS, module_idP, WS_C_RNTI,
1408 1409 1410 1411 1412 1413 1414
		      UE_RNTI(module_idP, UE_id), eNB->frame,
		      eNB->subframe, 0, 0);
	    LOG_D(OPT,
		  "[eNB %d][DLSCH] CC_id %d Frame %d  rnti %x  with size %d\n",
		  module_idP, CC_id, frameP,
		  UE_RNTI(module_idP, UE_id), TBS);
	  }
1415

1416 1417 1418
	  T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP),
	    T_INT(CC_id), T_INT(rnti), T_INT(frameP),
	    T_INT(subframeP), T_INT(harq_pid),
1419
	    T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS));
1420

1421
          UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
1422

1423 1424 1425 1426
          add_ue_dlsch_info(module_idP, CC_id, UE_id, subframeP, S_DL_SCHEDULED);
          // store stats
          eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total;
          eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1;
1427 1428

	  UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
1429
          UE_list->eNB_UE_stats[CC_id][UE_id].num_mac_sdu_tx = num_sdus;
1430 1431 1432 1433 1434
	  UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += 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 = mcs;
	  UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS;

1435 1436 1437 1438
          UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes = TBS - sdu_length_total;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes += sdu_length_total;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes += TBS;
          UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus += 1;
1439 1440 1441 1442

	  if (cc[CC_id].tdd_Config != NULL) {	// TDD
	    UE_list->UE_template[CC_id][UE_id].DAI++;
	    update_ul_dci(module_idP, CC_id, rnti,
1443 1444
			  UE_list->UE_template[CC_id][UE_id].DAI,
                          subframeP);
1445
	  }
1446

1447
	  // do PUCCH power control
1448 1449
	  // this is the normalized RX power
	  eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
1450

1451 1452 1453 1454
	  /* unit is not dBm, it's special from nfapi */
	  // converting to dBm: ToDo: Noise power hard coded to 30
	  normalized_rx_power = (5*ue_sched_ctl->pucch1_snr[CC_id]-640)/10+30;
	  target_rx_power= eNB->puCch10xSnr/10 + 30;
1455
	  // this assumes accumulated tpc
1456
	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
1457 1458 1459 1460
	  int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame * 10 + UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe;
	  if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) ||	//normal case
	      ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe + frameP * 10 + subframeP) >= 10))))	//frame wrap-around
	    if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) {
1461
	      ue_sched_ctl->pucch1_cqi_update[CC_id] = 0;
1462

1463 1464
        UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP;
        UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP;
1465 1466 1467 1468 1469

	      if (normalized_rx_power > (target_rx_power + 4)) {
		tpc = 0;	//-1
	      } else if (normalized_rx_power < (target_rx_power - 4)) {
		tpc = 2;	//+1
1470
	      } else {
1471
		tpc = 1;	//0
1472
	      }
1473

1474
	      LOG_D(MAC,
1475 1476
		    "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, normalized/target rx power %d/%d\n",
		    module_idP, frameP, subframeP, harq_pid, tpc,
1477 1478
		    normalized_rx_power, target_rx_power);

Cedric Roux's avatar
Cedric Roux committed
1479
	    }	// Po_PUCCH has been updated
1480
	    else {
1481
	      tpc = 1;	//0
Cedric Roux's avatar
Cedric Roux committed
1482
	    }	// time to do TPC update
1483
	  else {
1484
	    tpc = 1;	//0
1485 1486
	  }

1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520
          dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
          memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
          dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
          dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1;
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level =
                  get_aggregation(get_bw_index(module_idP, CC_id), ue_sched_ctl->dl_cqi[CC_id], format1);
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
          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 = tpc;    // dont adjust power when retransmitting
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 =
                  1 - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs;
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0;
          //deactivate second codeword
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0;
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1;

          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] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n",
                  module_idP, CC_id, harq_pid,
                  (UE_list->UE_template[CC_id][UE_id].DAI - 1),
                  mcs);
          } else {
            LOG_D(MAC,
                  "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n",
                  module_idP, CC_id, harq_pid, mcs);
1521

1522
	  }
1523

1524 1525
	  LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n",
		dl_req->number_pdu);
1526

1527 1528 1529
	  if (!CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP,
					 dl_config_pdu->dci_dl_pdu.
					 dci_dl_pdu_rel8.aggregation_level, rnti)) {
1530
	    ue_sched_ctl->round[CC_id][harq_pid] = 0;
1531 1532
	    dl_req->number_dci++;
	    dl_req->number_pdu++;
Xu Bo's avatar
Xu Bo committed
1533
	    dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
1534

1535 1536
            eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP;
            eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;
1537

1538 1539 1540 1541 1542
            // Toggle NDI for next time
            LOG_D(MAC,
                  "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n",
                  CC_id, frameP, subframeP, UE_id, rnti, harq_pid,
                  UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]);
1543 1544

	    UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid] = 1 - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
1545 1546
	    UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs;
	    UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0;
1547
	    AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
			"physicalConfigDedicated is NULL\n");
	    AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated != NULL,
			"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n");

	    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(mcs), 0,	// 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
				    );
1570
	    eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body,
1571 1572
							  (frameP * 10) + subframeP,
							  TBS, eNB->pdu_index[CC_id],
1573
							  eNB->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0]);
Cedric Roux's avatar
Cedric Roux committed
1574

1575 1576 1577
	    LOG_D(MAC,
		  "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n",
		  eNB->pdu_index[CC_id]);
1578

1579
	    eNB->pdu_index[CC_id]++;
1580 1581
	    program_dlsch_acknak(module_idP, CC_id, UE_id,
				 frameP, subframeP,
1582
				 dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
1583 1584 1585 1586
	  } else {
	    LOG_W(MAC,
		  "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n",
		  frameP, subframeP, UE_id, rnti);
1587
	  }
1588
	} else {	// There is no data from RLC or MAC header, so don't schedule
1589

1590
	}
1591
      }
1592

1593 1594
      if (cc[CC_id].tdd_Config != NULL) {    // TDD
        set_ul_DAI(module_idP, UE_id, CC_id, frameP, subframeP);
1595
      }
1596 1597
    }			// UE_id loop
  }				// CC_id loop
Cedric Roux's avatar
Cedric Roux committed
1598

1599
  fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_flag);
1600

1601 1602
  stop_meas(&eNB->schedule_dlsch);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT);
1603 1604
}

1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615
//------------------------------------------------------------------------------
void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, int frameP, sub_frame_t subframeP)
//------------------------------------------------------------------------------
{
  // FIXME: I'm prototyping the algorithm, so there may be arrays and variables that carry redundant information here and in pre_processor_results struct.

  int UE_id, CC_id, rbg, i;
  int N_RB_DL, min_rb_unit, tm;
  int owned, used;

  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
1616
  slice_info_t *sli = &RC.mac[Mod_id]->slice_info;
1617 1618 1619 1620
  UE_sched_ctrl *ue_sched_ctl;
  COMMON_channels_t *cc;
  int N_RBG[NFAPI_CC_MAX];

1621
  int slice_sorted_list[MAX_NUM_SLICES], slice_id;
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
  int8_t free_rbgs_map[NFAPI_CC_MAX][N_RBG_MAX];
  int has_traffic[NFAPI_CC_MAX][MAX_NUM_SLICES];
  uint8_t allocation_mask[NFAPI_CC_MAX][N_RBG_MAX];

  uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB];
  uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB];
  uint8_t  (*rballoc_sub)[N_RBG_MAX];
  uint8_t  (*MIMO_mode_indicator)[N_RBG_MAX];

  // Initialize the free RBGs map
  // free_rbgs_map[CC_id][rbg] = -1 if RBG is allocated,
  // otherwise it contains the id of the slice it belongs to.
  // (Information about slicing must be retained to deal with isolation).
  // FIXME: This method does not consider RBGs that are free and belong to no slices
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; ++CC_id) {
    cc = &RC.mac[Mod_id]->common_channels[CC_id];
    N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth);
    for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) {
1640 1641
      for (i = 0; i < sli->n_dl; ++i) {
        owned = sli->pre_processor_results[i].slice_allocation_mask[CC_id][rbg];
1642
        if (owned) {
1643
          used = sli->pre_processor_results[i].slice_allocated_rbgs[CC_id][rbg];
1644 1645 1646 1647 1648 1649 1650 1651 1652 1653
          free_rbgs_map[CC_id][rbg] = used ? -1 : i;
          break;
        }
      }
    }
  }

  // Find out which slices need other resources.
  // FIXME: I don't think is really needed since we check nb_rbs_remaining later
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; ++CC_id) {
1654
    for (i = 0; i < sli->n_dl; ++i) {
1655 1656
      has_traffic[CC_id][i] = 0;
      for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) {
1657
        if (sli->pre_processor_results[i].nb_rbs_remaining[CC_id][UE_id] > 0) {
1658 1659 1660 1661 1662 1663 1664
          has_traffic[CC_id][i] = 1;
          break;
        }
      }
    }
  }

1665
  slice_priority_sort(Mod_id, slice_sorted_list);
1666 1667 1668 1669 1670 1671 1672 1673

  // MULTIPLEXING
  // This part is an adaptation of dlsch_scheduler_pre_processor_allocate() code
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; ++CC_id) {

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

1674
    for (i = 0; i < sli->n_dl; ++i) {
1675
      slice_id = slice_sorted_list[i];
1676

1677
      if (has_traffic[CC_id][slice_id] == 0) continue;
1678 1679 1680 1681 1682 1683 1684 1685

      // Build an ad-hoc allocation mask fo the slice
      for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) {
        if (free_rbgs_map[CC_id][rbg] == -1) {
          // RBG is already allocated
          allocation_mask[CC_id][rbg] = 0;
          continue;
        }
1686
        if (sli->dl[free_rbgs_map[CC_id][rbg]].isol == 1) {
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696
          // RBG belongs to an isolated slice
          allocation_mask[CC_id][rbg] = 0;
          continue;
        }
        // RBG is free
        allocation_mask[CC_id][rbg] = 1;
      }

      // Sort UE again
      // (UE list gets sorted every time pre_processor is called so it is probably dirty at this point)
1697 1698
      // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it
      sort_UEs(Mod_id, (slice_id_t) slice_id, frameP, subframeP);
1699

1700 1701 1702 1703
      nb_rbs_remaining = sli->pre_processor_results[slice_id].nb_rbs_remaining;
      nb_rbs_required = sli->pre_processor_results[slice_id].nb_rbs_required;
      rballoc_sub = sli->pre_processor_results[slice_id].slice_allocated_rbgs;
      MIMO_mode_indicator = sli->pre_processor_results[slice_id].MIMO_mode_indicator;
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752

      // Allocation
      for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
        ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
        tm = get_tmode(Mod_id, CC_id, UE_id);

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

          // FIXME: I think that some of these checks are redundant
          if (allocation_mask[CC_id][rbg] == 0) continue;
          if (rballoc_sub[CC_id][rbg] != 0) continue;
          if (ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] != 0) continue;
          if (nb_rbs_remaining[CC_id][UE_id] <= 0) continue;
          if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required[CC_id][UE_id]) continue;
          if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue;

          if ((rbg == N_RBG[CC_id] - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
            // Allocating last, smaller RBG
            if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) {
              rballoc_sub[CC_id][rbg] = 1;
              free_rbgs_map[CC_id][rbg] = -1;
              ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] = 1;
              MIMO_mode_indicator[CC_id][rbg] = 1;
              if (tm == 5) {
                ue_sched_ctl->dl_pow_off[CC_id] = 1;
              }
              nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1;
              ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
            }
          } else {
            // Allocating a standard-sized RBG
            if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) {
              rballoc_sub[CC_id][rbg] = 1;
              free_rbgs_map[CC_id][rbg] = -1;
              ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] = 1;
              MIMO_mode_indicator[CC_id][rbg] = 1;
              if (tm == 5) {
                ue_sched_ctl->dl_pow_off[CC_id] = 1;
              }
              nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit;
              ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit;
            }
          }
        }
      }
    }
  }
}

1753 1754 1755 1756 1757 1758
//------------------------------------------------------------------------------
void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id, int frameP, sub_frame_t subframeP)
//------------------------------------------------------------------------------
{
  int UE_id, CC_id, i;
  UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
1759
  slice_info_t *sli = &RC.mac[Mod_id]->slice_info;
1760 1761
  UE_sched_ctrl *ue_sched_ctl;

1762
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; ++CC_id) {
1763
    for (i = 0; i < sli->n_dl; ++i) {
1764 1765 1766 1767 1768 1769 1770 1771 1772

      // Sort UE again
      // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it
      sort_UEs(Mod_id, (slice_id_t) i, frameP, subframeP);

      for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
        ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];

        // TODO: Do something here
1773
        // ue_sched_ctl->pre_nb_available_rbs[CC_id];
1774 1775 1776 1777 1778 1779
      }
    }
  }
}


1780 1781
//------------------------------------------------------------------------------
void
1782
fill_DLSCH_dci(module_id_t module_idP,
1783
               frame_t frameP, sub_frame_t subframeP, int *mbsfn_flagP)
1784
//------------------------------------------------------------------------------
1785
{
1786 1787

  // loop over all allocated UEs and compute frequency allocations for PDSCH
1788 1789 1790
  int UE_id = -1;
  uint8_t /* first_rb, */ nb_rb = 3;
  rnti_t rnti;
1791
  //unsigned char *vrb_map;
1792
  uint8_t rballoc_sub[25];
1793 1794
  //uint8_t number_of_subbands=13;

1795
  //unsigned char round;
1796 1797 1798 1799 1800 1801 1802
  unsigned char harq_pid;
  int i;
  int CC_id;
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  UE_list_t *UE_list = &eNB->UE_list;
  int N_RBG;
  int N_RB_DL;
1803
  COMMON_channels_t *cc;
1804

Raymond Knopp's avatar
 
Raymond Knopp committed
1805
  start_meas(&eNB->fill_DLSCH_dci);
1806
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
1807
  (VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_IN);
1808

1809
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
1810
    LOG_D(MAC, "Doing fill DCI for CC_id %d\n", CC_id);
Raymond Knopp's avatar
 
Raymond Knopp committed
1811

1812
    if (mbsfn_flagP[CC_id] > 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1813
      continue;
1814

1815 1816 1817
    cc = &eNB->common_channels[CC_id];
    N_RBG = to_rbg(cc->mib->message.dl_Bandwidth);
    N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
Raymond Knopp's avatar
 
Raymond Knopp committed
1818

Raymond Knopp's avatar
 
Raymond Knopp committed
1819
    // UE specific DCIs
1820
    for (UE_id = UE_list->head; UE_id >= 0;
1821
         UE_id = UE_list->next[UE_id]) {
1822
      LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", CC_id, UE_id,
1823
            eNB_dlsch_info[module_idP][CC_id][UE_id].status);
1824

1825
      if (eNB_dlsch_info[module_idP][CC_id][UE_id].status == S_DL_SCHEDULED) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1826

1827 1828 1829
        // clear scheduling flag
        eNB_dlsch_info[module_idP][CC_id][UE_id].status = S_DL_WAITING;
        rnti = UE_RNTI(module_idP, UE_id);
1830
        harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
1831
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
1832

1833 1834 1835 1836
        /// Synchronizing rballoc with rballoc_sub
        for (i = 0; i < N_RBG; i++) {
          rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i];
        }
1837

1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
        nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0];
        nfapi_dl_config_request_pdu_t *dl_config_pdu;

        for (i = 0;
             i < DL_req[CC_id].dl_config_request_body.number_pdu;
             i++) {
          dl_config_pdu = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[i];
          if ((dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
              && (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti)
              && (dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1)) {
            dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG,
                                                                                                rballoc_sub);
            dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0;
          } else if ((dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE)
                     && (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti)
                     && (dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type == 0)) {
            dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG,
                                                                                              rballoc_sub);
          }
        }
Raymond Knopp's avatar
 
Raymond Knopp committed
1858 1859
      }
    }
1860

1861 1862 1863 1864
  }

  stop_meas(&eNB->fill_DLSCH_dci);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_OUT);
1865 1866
}

1867
//------------------------------------------------------------------------------
1868
unsigned char *get_dlsch_sdu(module_id_t module_idP,
1869 1870
                             int CC_id, frame_t frameP, rnti_t rntiP,
                             uint8_t TBindex)
1871
//------------------------------------------------------------------------------
1872
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1873

1874 1875
  int UE_id;
  eNB_MAC_INST *eNB = RC.mac[module_idP];
Raymond Knopp's avatar
 
Raymond Knopp committed
1876

1877 1878
  if (rntiP == SI_RNTI) {
    LOG_D(MAC, "[eNB %d] CC_id %d Frame %d Get DLSCH sdu for BCCH \n",
1879
          module_idP, CC_id, frameP);
Raymond Knopp's avatar
 
Raymond Knopp committed
1880

1881 1882
    return ((unsigned char *) &eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
  }
1883

1884 1885
  if (rntiP == P_RNTI) {
    LOG_D(MAC, "[eNB %d] CC_id %d Frame %d Get PCH sdu for PCCH \n", module_idP, CC_id, frameP);
1886

1887
    return ((unsigned char *) &eNB->common_channels[CC_id].PCCH_pdu.payload[0]);
1888
  }
1889

1890
  UE_id = find_UE_id(module_idP, rntiP);
1891

1892 1893
  if (UE_id != -1) {
    LOG_D(MAC,
1894 1895
          "[eNB %d] Frame %d:  CC_id %d Get DLSCH sdu for rnti %x => UE_id %d\n",
          module_idP, frameP, CC_id, rntiP, UE_id);
1896 1897 1898
    return ((unsigned char *) &eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]);
  } else {
    LOG_E(MAC,
1899 1900
          "[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n",
          module_idP, frameP, CC_id, rntiP);
1901 1902
    return NULL;
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1903 1904

}
1905 1906


1907
//------------------------------------------------------------------------------
1908 1909
void
update_ul_dci(module_id_t module_idP,
1910
	      uint8_t CC_idP, rnti_t rntiP, uint8_t daiP, sub_frame_t subframe)
1911
//------------------------------------------------------------------------------
1912
{
1913

1914
  nfapi_hi_dci0_request_t *HI_DCI0_req =
1915
    &RC.mac[module_idP]->HI_DCI0_req[CC_idP][subframe];
1916
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu =
1917
          &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[0];
1918 1919
  COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_idP];
  int i;
1920

1921

Cedric Roux's avatar
Cedric Roux committed
1922
  if (cc->tdd_Config != NULL) {	// TDD
1923
    for (i = 0;
1924
	 i <HI_DCI0_req->hi_dci0_request_body.number_of_dci + HI_DCI0_req->hi_dci0_request_body.number_of_hi;
1925
	 i++) {
1926

1927
      if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) &&
1928 1929
          (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP))
        hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index = (daiP - 1) & 3;
1930

1931
    }
1932
  }
1933 1934 1935
}


1936
//------------------------------------------------------------------------------
1937 1938
void
set_ue_dai(sub_frame_t subframeP,
1939 1940
           int UE_id, uint8_t CC_id, uint8_t tdd_config,
           UE_list_t *UE_list)
1941
//------------------------------------------------------------------------------
1942
{
1943
  switch (tdd_config) {
1944 1945 1946 1947 1948
    case 0:
      if ((subframeP == 0) || (subframeP == 1) || (subframeP == 3)
          || (subframeP == 5) || (subframeP == 6) || (subframeP == 8)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1949

1950
      break;
1951

1952 1953 1954 1955 1956
    case 1:
      if ((subframeP == 0) || (subframeP == 4) || (subframeP == 5)
          || (subframeP == 9)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1957

1958
      break;
1959

1960 1961 1962 1963
    case 2:
      if ((subframeP == 4) || (subframeP == 5)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1964

1965
      break;
1966

1967 1968 1969 1970
    case 3:
      if ((subframeP == 5) || (subframeP == 7) || (subframeP == 9)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1971

1972
      break;
1973

1974 1975 1976 1977
    case 4:
      if ((subframeP == 0) || (subframeP == 6)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1978

1979
      break;
1980

1981 1982 1983 1984
    case 5:
      if (subframeP == 9) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1985

1986
      break;
1987

1988 1989 1990 1991 1992
    case 6:
      if ((subframeP == 0) || (subframeP == 1) || (subframeP == 5)
          || (subframeP == 6) || (subframeP == 9)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1993

1994
      break;
1995

1996 1997 1998 1999
    default:
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
      LOG_I(MAC, "unknown TDD config %d\n", tdd_config);
      break;
2000
  }
2001
}
2002

2003
void schedule_PCH(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
2004 2005
  /* DCI:format 1A/1C P-RNTI:0xFFFE */
  /* PDU:eNB_rrc_inst[Mod_idP].common_channels[CC_id].PCCH_pdu.payload */
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015
  uint16_t pcch_sdu_length;
  int mcs = -1;
  int CC_id;
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc;
  uint8_t *vrb_map;
  int n_rb_dl;
  int first_rb = -1;
  nfapi_dl_config_request_pdu_t *dl_config_pdu;
  nfapi_tx_request_pdu_t *TX_req;
2016 2017 2018 2019
  nfapi_dl_config_request_body_t *dl_req;
#ifdef FORMAT1C
  int                            gap_index = 0;      /* indicate which gap(1st or 2nd) is used (0:1st) */
  const int                      GAP_MAP [9][2] = {
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029
    {-1, 0},        /* N_RB_DL [6-10] -1: |N_RB/2| 0: N/A*/
    {4, 0},         /* N_RB_DL [11] */
    {8, 0},         /* N_RB_DL [12-19] */
    {12, 0},        /* N_RB_DL [20-26] */
    {18, 0},        /* N_RB_DL [27-44] */
    {27, 0},        /* N_RB_DL [45-49] */
    {27, 9},        /* N_RB_DL [50-63] */
    {32, 16},       /* N_RB_DL [64-79] */
    {48, 16}        /* N_RB_DL [80-110] */
  };
2030 2031 2032 2033 2034
  uint8_t                        n_rb_step = 0;
  uint8_t                        n_gap = 0;
  uint8_t                        n_vrb_dl = 0;
  uint8_t                        Lcrbs = 0;
  uint16_t                       rb_bit    = 168;    /* RB bit number value is unsure */
2035
#endif
2036 2037 2038

  start_meas(&eNB->schedule_pch);

2039
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
2040
    cc              = &eNB->common_channels[CC_id];
2041
    vrb_map         = (void *) &cc->vrb_map;
2042 2043
    n_rb_dl         = to_prb(cc->mib->message.dl_Bandwidth);
    dl_req          = &eNB->DL_req[CC_id].dl_config_request_body;
2044
    for (uint16_t i = 0; i < MAX_MOBILES_PER_ENB; i++) {
2045 2046 2047 2048
      if (UE_PF_PO[CC_id][i].enable_flag != TRUE) {
        continue;
      }
      if (frameP % UE_PF_PO[CC_id][i].T == UE_PF_PO[CC_id][i].PF_min && subframeP == UE_PF_PO[CC_id][i].PO) {
2049
        pcch_sdu_length = mac_rrc_data_req(module_idP,
2050 2051
                                           CC_id,
                                           frameP,
2052
                                           PCCH, 1,
2053 2054
                                           &cc->PCCH_pdu.payload[0],
                                           i); // used for ue index
2055 2056 2057 2058 2059 2060
        if (pcch_sdu_length == 0) {
          LOG_D(MAC, "[eNB %d] Frame %d subframe %d: PCCH not active(size = 0 byte)\n", module_idP, frameP, subframeP);
          continue;
        }
        LOG_D(MAC, "[eNB %d] Frame %d subframe %d: PCCH->PCH CC_id %d UE_id %d, Received %d bytes \n", module_idP,
              frameP, subframeP, CC_id, i, pcch_sdu_length);
2061
#ifdef FORMAT1C
2062
	//NO SIB
2063
	if ((subframeP == 0 || subframeP == 1 || subframeP == 2 || subframeP == 4 || subframeP == 6 || subframeP == 9) ||
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155
	    (subframeP == 5 && ((frameP % 2) != 0 && (frameP % 8) != 1))) {
	  switch (n_rb_dl) {
	  case 25:
	    n_gap = GAP_MAP[3][0];  /* expect: 12 */
	    n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));  /* expect: 24 */
	    first_rb = 10;
	    break;
	  case 50:
	    n_gap = GAP_MAP[6][gap_index];  /* expect: 27 or 9 */
	    if (gap_index > 0) {
	      n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap);  /* 36 */
	    } else {
	      n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));  /* expect: 46 */
	    }
	    first_rb = 24;
	    break;
	  case 100:
	    n_gap = GAP_MAP[8][gap_index];  /* expect: 48 or 16 */
	    if (gap_index > 0) {
	      n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap);  /* expect: 96 */
	    } else {
	      n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));  /* expect: 96 */
	    }
	    first_rb = 48;
	    break;
	  }
	} else if (subframeP == 5 && ((frameP % 2) == 0 || (frameP % 8) == 1)) {  // SIB + paging
	  switch (n_rb_dl) {
	  case 25:
	    n_gap = GAP_MAP[3][0];  /* expect: 12 */
	    n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));  /* expect: 24 */
	    first_rb = 14;
	    break;
	  case 50:
	    n_gap = GAP_MAP[6][gap_index];  /* expect: 27 or 9 */
	    if (gap_index > 0) {
	      n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap);  /* 36 */
	    } else {
	      n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));  /* expect: 46 */
	    }
	    first_rb = 28;
	    break;
	  case 100:
	    n_gap = GAP_MAP[8][gap_index];  /* expect: 48 or 16 */
	    if (gap_index > 0) {
	      n_vrb_dl = (n_rb_dl / (2*n_gap)) * (2*n_gap);  /* expect: 96 */
	    } else {
	      n_vrb_dl = 2*((n_gap < (n_rb_dl - n_gap)) ? n_gap : (n_rb_dl - n_gap));  /* expect: 96 */
	    }
	    first_rb = 52;
	    break;
	  }
	}
	/* Get MCS for length of PCH */
	if (pcch_sdu_length <= TBStable1C[0]) {
	  mcs=0;
	} else if (pcch_sdu_length <= TBStable1C[1]) {
	  mcs=1;
	} else if (pcch_sdu_length <= TBStable1C[2]) {
	  mcs=2;
	} else if (pcch_sdu_length <= TBStable1C[3]) {
	  mcs=3;
	} else if (pcch_sdu_length <= TBStable1C[4]) {
	  mcs=4;
	} else if (pcch_sdu_length <= TBStable1C[5]) {
	  mcs=5;
	} else if (pcch_sdu_length <= TBStable1C[6]) {
	  mcs=6;
	} else if (pcch_sdu_length <= TBStable1C[7]) {
	  mcs=7;
	} else if (pcch_sdu_length <= TBStable1C[8]) {
	  mcs=8;
	} else if (pcch_sdu_length <= TBStable1C[9]) {
	  mcs=9;
	} else {
	  /* unexpected: pcch sdb size is over max value*/
	  LOG_E(MAC,"[eNB %d] Frame %d : PCCH->PCH CC_id %d, Received %d bytes is over max length(256) \n",
		module_idP, frameP,CC_id, pcch_sdu_length);
	  return;
	}
	rb_num = TBStable1C[mcs] / rb_bit + ( (TBStable1C[mcs] % rb_bit == 0)? 0: 1) + 1;
	/* calculate N_RB_STEP and Lcrbs */
	if (n_rb_dl < 50) {
	  n_rb_step = 2;
	  Lcrbs = rb_num / 2 + ((rb_num % 2 == 0) ? 0:2);
	} else {
	  n_rb_step = 4;
	  Lcrbs = rb_num / 4 + ((rb_num % 4 == 0) ? 0:4);
	}
	for(i = 0;i < Lcrbs ;i++){
	  vrb_map[first_rb+i] = 1;
	}
2156
#else
2157
	//NO SIB
2158
	if ((subframeP == 0 || subframeP == 1 || subframeP == 2 || subframeP == 4 || subframeP == 6 || subframeP == 9) ||
2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183
	    (subframeP == 5 && ((frameP % 2) != 0 && (frameP % 8) != 1))) {
	  switch (n_rb_dl) {
	  case 25:
	    first_rb = 10;
	    break;
	  case 50:
	    first_rb = 24;
	    break;
	  case 100:
	    first_rb = 48;
	    break;
	  }
	} else if (subframeP == 5 && ((frameP % 2) == 0 || (frameP % 8) == 1)) {  // SIB + paging
	  switch (n_rb_dl) {
	  case 25:
	    first_rb = 14;
	    break;
	  case 50:
	    first_rb = 28;
	    break;
	  case 100:
	    first_rb = 52;
	    break;
	  }
	}
2184

2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210
        vrb_map[first_rb] = 1;
        vrb_map[first_rb + 1] = 1;
        vrb_map[first_rb + 2] = 1;
        vrb_map[first_rb + 3] = 1;
        /* Get MCS for length of PCH */
        if (pcch_sdu_length <= get_TBS_DL(0, 3)) {
          mcs = 0;
        } else if (pcch_sdu_length <= get_TBS_DL(1, 3)) {
          mcs = 1;
        } else if (pcch_sdu_length <= get_TBS_DL(2, 3)) {
          mcs = 2;
        } else if (pcch_sdu_length <= get_TBS_DL(3, 3)) {
          mcs = 3;
        } else if (pcch_sdu_length <= get_TBS_DL(4, 3)) {
          mcs = 4;
        } else if (pcch_sdu_length <= get_TBS_DL(5, 3)) {
          mcs = 5;
        } else if (pcch_sdu_length <= get_TBS_DL(6, 3)) {
          mcs = 6;
        } else if (pcch_sdu_length <= get_TBS_DL(7, 3)) {
          mcs = 7;
        } else if (pcch_sdu_length <= get_TBS_DL(8, 3)) {
          mcs = 8;
        } else if (pcch_sdu_length <= get_TBS_DL(9, 3)) {
          mcs = 9;
        }
2211
#endif
2212 2213 2214 2215
        dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
        memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
        dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
        dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
2216
#ifdef FORMAT1C
2217 2218 2219
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                  = NFAPI_DL_DCI_FORMAT_1C;
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding       = getRIV(n_vrb_dl/n_rb_step, first_rb/n_rb_step, Lcrbs/n_rb_step);
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.ngap                        = n_gap;
2220
#else
2221 2222 2223 2224 2225 2226 2227
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A;
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = 0;
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // no TPC
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1;
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 1;
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = getRIV(n_rb_dl, first_rb, 4);
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
2228
#endif
2229 2230 2231 2232 2233
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level           = 4;
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                        = 0xFFFE; // P-RNTI
        dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                   = 2;    // P-RNTI : 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.mcs_1                       = mcs;
2234

2235
        // Rel10 fields
2236
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2237
        dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start                  = 3;
2238
#endif
2239
        // Rel13 fields
2240
#if (RRC_VERSION >= MAKE_VERSION(13, 0, 0))
2241 2242 2243
        dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type                      = 0; // regular UE
        dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type           = 2; // not BR
        dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io   = 0xFFFF;
2244
#endif
2245 2246 2247 2248 2249

	if (!CCE_allocation_infeasible(module_idP, CC_id, 0, subframeP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, P_RNTI)) {
	  LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for P_RNTI\n", frameP,subframeP);
	  dl_req->number_dci++;
	  dl_req->number_pdu++;
2250 2251 2252 2253
          dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
          eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP;
          eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;

2254 2255 2256 2257 2258 2259
	  dl_config_pdu                                                                  = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
	  memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	  dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
	  dl_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu));
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index                              = eNB->pdu_index[CC_id];
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti                                   = 0xFFFE;
2260
#ifdef FORMAT1C
2261 2262
          dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type               = 3;   // format 1C
          dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = getRIV(n_vrb_dl/n_rb_step, first_rb/n_rb_step, Lcrbs/n_rb_step);
2263
#else
2264 2265 2266
          dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type = 2;   // format 1A/1B/1D
          dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = getRIV(n_rb_dl, first_rb, 4);
          dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0;   // localized
2267
#endif
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = 2; //QPSK
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version                     = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks                       = 1;// first block
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag  = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme                    = (cc->p_eNB==1 ) ? 0 : 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers                       = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands                     = 1;
	  // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = ;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = 4; // 0 dB
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = (cc->p_eNB==1 ) ? 1 : 2;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = 1;
	  // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector                    = ;
	  dl_req->number_pdu++;

	  eNB->TX_req[CC_id].sfn_sf                                                     = (frameP<<4)+subframeP;
	  TX_req                                                                         = &eNB->TX_req[CC_id].tx_request_body.tx_pdu_list[eNB->TX_req[CC_id].tx_request_body.number_of_pdus];
	  TX_req->pdu_length                                                             = pcch_sdu_length;
	  TX_req->pdu_index                                                              = eNB->pdu_index[CC_id]++;
	  TX_req->num_segments                                                           = 1;
	  TX_req->segments[0].segment_length                                             = pcch_sdu_length;
	  TX_req->segments[0].segment_data                                               = cc[CC_id].PCCH_pdu.payload;
2294
          eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
2295 2296 2297 2298 2299
	  eNB->TX_req[CC_id].tx_request_body.number_of_pdus++;
	} else {
	  LOG_E(MAC,"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A/1C for Paging\n",module_idP, CC_id, frameP, subframeP);
	  continue;
	}
2300

2301
	if (opt_enabled == 1) {
laurent's avatar
laurent committed
2302
	  trace_pdu(DIRECTION_DOWNLINK,
2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
		    &eNB->common_channels[CC_id].PCCH_pdu.payload[0],
		    pcch_sdu_length,
		    0xffff,
		    PCCH,
		    P_RNTI,
		    eNB->frame,
		    eNB->subframe,
		    0,
		    0);
	  LOG_D(OPT,"[eNB %d][PCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
		module_idP, frameP, CC_id, 0xffff, pcch_sdu_length);
	}
	eNB->eNB_stats[CC_id].total_num_pcch_pdu+=1;
	eNB->eNB_stats[CC_id].pcch_buffer=pcch_sdu_length;
	eNB->eNB_stats[CC_id].total_pcch_buffer+=pcch_sdu_length;
	eNB->eNB_stats[CC_id].pcch_mcs=mcs;
	//paging first_rb log
	LOG_D(MAC,"[eNB %d] Frame %d subframe %d PCH: paging_ue_index %d pcch_sdu_length %d mcs %d first_rb %d\n",
	      module_idP, frameP, subframeP, UE_PF_PO[CC_id][i].ue_index_value, pcch_sdu_length, mcs, first_rb);

	pthread_mutex_lock(&ue_pf_po_mutex);
	memset(&UE_PF_PO[CC_id][i], 0, sizeof(UE_PF_PO_t));
	pthread_mutex_unlock(&ue_pf_po_mutex);
2326 2327 2328 2329 2330 2331 2332
      }
    }
  }
  /* this might be misleading when pcch is inactive */
  stop_meas(&eNB->schedule_pch);
  return;
}
2333

2334 2335 2336 2337 2338 2339
static int slice_priority_compare(const void *_a, const void *_b, void *_c)
{
  const int slice_id1 = *(const int *) _a;
  const int slice_id2 = *(const int *) _b;
  const module_id_t Mod_id = *(int *)  _c;
  const slice_info_t *sli = &RC.mac[Mod_id]->slice_info;
2340

2341
  if (sli->dl[slice_id1].prio > sli->dl[slice_id2].prio) {
2342 2343 2344 2345 2346
    return -1;
  }
  return 1;
}

2347 2348
void slice_priority_sort(module_id_t Mod_id, int slice_list[MAX_NUM_SLICES])
{
2349 2350 2351 2352 2353
  int i;
  for (i = 0; i < MAX_NUM_SLICES; ++i) {
    slice_list[i] = i;
  }

2354
  qsort_r(slice_list, MAX_NUM_SLICES, sizeof(int), slice_priority_compare, &Mod_id);
2355
}