eNB_scheduler_dlsch.c 93.6 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
  memset(sli->rballoc_sub, 0, sizeof(sli->rballoc_sub));
416

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

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

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

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

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

    // Load any updated functions
465 466 467 468
    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;
469 470
      LOG_I(MAC, "update dl scheduler (%s) slice index %d ID %d\n",
            sli->dl[i].sched_name, i, sli->dl[i].id);
471 472
    }

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

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

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

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

      // check if a new scheduler, and log the console
514 515
      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",
516
              module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].sched_name);
517
        sli->dl[i].update_sched_current = sli->dl[i].update_sched;
518 519 520 521 522
      }

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

523
      if (sli->n_dl == sli->n_dl_current) {
524 525
        LOG_W(MAC,
              "[eNB %d][SLICE %d][DL] invalid total RB share (%f->%f), reduce proportionally the RB share by 0.1\n",
526
              module_idP, sli->dl[i].id, sli->tot_pct_dl_current, sli->tot_pct_dl);
527 528 529
        if (sli->dl[i].pct >= sli->avg_pct_dl) {
          sli->dl[i].pct -= 0.1;
          sli->tot_pct_dl -= 0.1;
530
        }
531
      } else {
532 533
        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",
534
              module_idP, sli->dl[i].id, sli->tot_pct_dl_current, sli->tot_pct_dl,
535 536 537
              sli->n_dl, sli->n_dl_current);
        sli->n_dl = sli->n_dl_current;
        sli->dl[i].pct = sli->dl[i].pct_current;
538 539 540
      }
    }

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

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

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

    // Check for new slice priority
586 587
    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",
588
            module_idP, sli->dl[i].id, frameP, subframeP, sli->dl[i].prio_current, sli->dl[i].prio);
589
      sli->dl[i].prio_current = sli->dl[i].prio;
590 591
    }

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

608
    // Run each enabled slice-specific schedulers one by one
609
    sli->dl[i].sched_cb(module_idP, i, frameP, subframeP, mbsfn_flag/*, dl_info*/);
610 611 612
  }

}
613

614 615
// changes to pre-processor for eMTC

616 617
//------------------------------------------------------------------------------
void
618
schedule_ue_spec(module_id_t module_idP, int slice_idxP,
619
                 frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag)
620
//------------------------------------------------------------------------------
621
{
622
  int CC_id;
623
  int UE_id;
624
  int aggregation;
625
  mac_rlc_status_resp_t rlc_status;
626 627 628 629 630 631
  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;
632
  unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES];
633 634
  int round = 0;
  int harq_pid = 0;
635
  eNB_UE_STATS *eNB_UE_stats = NULL;
636
  int sdu_length_total = 0;
637 638 639 640 641 642

  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;
643
  int tpc = 1;
644 645 646
  UE_sched_ctrl *ue_sched_ctl;
  int mcs;
  int i;
647 648 649 650
  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];
651 652 653 654
  nfapi_dl_config_request_body_t *dl_req;
  nfapi_dl_config_request_pdu_t *dl_config_pdu;
  int tdd_sfa;
  int ta_update;
655 656
  int header_length_last;
  int header_length_total;
657

658
  start_meas(&eNB->schedule_dlsch);
659
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
660

661 662 663 664
  // 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) {
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 693 694 695 696 697 698
      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;
699
    }
700 701 702
  }
  //weight = get_ue_weight(module_idP,UE_id);
  aggregation = 2;
703
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
704 705 706 707 708 709
    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)
710
        total_nb_available_rb[CC_id]--;
711 712 713 714 715 716 717 718 719 720

    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;
  }
721

722 723 724
  // 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);
725

Raymond Knopp's avatar
 
Raymond Knopp committed
726
  start_meas(&eNB->schedule_dlsch_preprocessor);
727
  dlsch_scheduler_pre_processor(module_idP,
728
                                slice_idxP,
729 730
                                frameP,
                                subframeP,
731 732
                                mbsfn_flag,
                                eNB->slice_info.rballoc_sub);
Raymond Knopp's avatar
 
Raymond Knopp committed
733
  stop_meas(&eNB->schedule_dlsch_preprocessor);
734 735

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT);
736

737
  //RC.mac[module_idP]->slice_info.slice_counter--;
738
  // Do the multiplexing and actual allocation only when all slices have been pre-processed.
739 740 741 742 743
  //if (RC.mac[module_idP]->slice_info.slice_counter > 0) {
    //stop_meas(&eNB->schedule_dlsch);
    //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT);
    //return;
  //}
744

745
  if (RC.mac[module_idP]->slice_info.interslice_share_active) {
746
    dlsch_scheduler_interslice_multiplexing(module_idP, frameP, subframeP, eNB->slice_info.rballoc_sub);
747 748 749
    /* the interslice multiplexing re-sorts the UE_list for the slices it tries
     * to multiplex, so we need to sort it for the current slice again */
    sort_UEs(module_idP, slice_idxP, frameP, subframeP);
750
  }
751 752

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

755
    dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
756

757
    if (mbsfn_flag[CC_id] > 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
758
      continue;
759

760 761
    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
762
      rnti = UE_RNTI(module_idP, UE_id);
763
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
764
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
765

766
      if (rnti == NOT_A_RNTI) {
767 768
        LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id, UE_list->num_UEs);
        continue_flag = 1;
769
      }
770

771
      if (eNB_UE_stats == NULL) {
772 773
        LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n");
        continue_flag = 1;
774
      }
775

776
      if (!ue_dl_slice_membership(module_idP, UE_id, slice_idxP))
777
        continue;
778

779
      if (continue_flag != 1) {
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
        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;
        }
797
      }
798

799
      /* if (continue_flag != 1 */
Cedric Roux's avatar
Cedric Roux committed
800
      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||	// no RBs allocated
801 802 803 804 805 806 807
	  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
808

809 810 811 812 813 814 815 816 817
      // 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);
818
      }
819

820
      if (continue_flag == 1) {
821 822
        add_ue_dlsch_info(module_idP, CC_id, UE_id, subframeP, S_DL_NONE);
        continue;
823
      }
Cedric Roux's avatar
Cedric Roux committed
824

825
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
826
      harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
827

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

830
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti;
831
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = mac_eNB_get_rrc_status(module_idP, rnti);
832
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid;
833
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
834

835 836
      if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED)
        continue;
837

838
      header_length_total = 0;
839 840
      sdu_length_total = 0;
      num_sdus = 0;
841

842
      /*
843 844 845
      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);
846 847
      */
      if (nfapi_mode) {
848 849
        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
850
        eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,
851
                                        eNB->slice_info.dl[slice_idxP].maxmcs);  // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
852
      }
853

854 855
      // Store stats
      // UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
856

857
      // Initializing the rb allocation indicator for each UE
858
      for (j = 0; j < N_RBG[CC_id]; j++) {
859
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
860 861 862
      }

      LOG_D(MAC,
863 864 865 866 867
            "[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);
868 869 870

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

872 873 874
        // 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);
875 876 877 878 879

	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,
880
			  UE_list->UE_template[CC_id][UE_id].DAI, subframeP);
881
	    LOG_D(MAC,
882 883 884 885 886
		  "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);
	  }

887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
          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];
                }
              }
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 953 954 955 956 957 958 959 960 961 962
              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]);
963

964 965 966 967 968 969
	    }
	    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
970

971 972 973
	      eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP;
	      eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;

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 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
                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);
              }
          }
1010

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

1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
	  //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;
1026

1027 1028
	// Now check RLC information to compute number of required RBs
	// get maximum TBS size for RLC request
1029
	TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_available_rb);
1030

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

1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
        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;
        }
1043

1044
        ta_len = (ta_update != 31) ? 2 : 0;
1045

1046 1047 1048
	// 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,
1049
                                          TBS - ta_len - header_length_total - sdu_length_total - 3
1050
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1051 1052 1053
                                                    ,0, 0
#endif
                          );
1054

1055
          sdu_lengths[0] = 0;
1056

1057 1058
	  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",
1059
		  module_idP, frameP, subframeP, CC_id,
1060 1061 1062 1063
		  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
1064
					      (char *)&dlsch_buffer[0]
1065
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1066 1067 1068
                          ,0, 0
#endif
                          );
1069

1070
            pthread_mutex_lock(&rrc_release_freelist);
wujing's avatar
wujing committed
1071
            if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)){
1072 1073
              uint16_t release_total = 0;
              for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
wujing's avatar
wujing committed
1074 1075 1076 1077 1078 1079
                if(rrc_release_info.RRC_release_ctrl[release_num].flag > 0){
                  release_total++;
                }else{
                  continue;
                }

1080
                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 1){
wujing's avatar
wujing committed
1081 1082 1083 1084 1085 1086
                  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;
1087 1088
                      }
                    }
1089 1090 1091
                  }
                }
                if(rrc_release_info.RRC_release_ctrl[release_num].flag == 2){
wujing's avatar
wujing committed
1092 1093 1094
                  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]){
1095 1096 1097
                        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
1098
                      }
1099
                    }
wujing's avatar
wujing committed
1100
                  }
1101 1102 1103 1104 1105 1106
                }
                if(release_total >= rrc_release_info.num_UEs)
                  break;
              }
            }
            pthread_mutex_unlock(&rrc_release_freelist);
Xu Bo's avatar
Xu Bo committed
1107 1108 1109

            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
1110 1111 1112 1113 1114 1115 1116 1117
              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
1118 1119
              }
            }
1120

1121 1122 1123 1124
            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]));
1125

1126
	    LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n",
1127
		  module_idP, CC_id, sdu_lengths[0]);
1128

1129 1130
	    sdu_length_total = sdu_lengths[0];
	    sdu_lcids[0] = DCCH;
1131 1132
            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];
1133 1134
	    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];
1135 1136 1137 1138

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

1139
	    num_sdus = 1;
1140

1141
#ifdef DEBUG_eNB_SCHEDULER
1142 1143 1144
            LOG_T(MAC,
              "[eNB %d][DCCH] CC_id %d Got %d bytes :",
              module_idP, CC_id, sdu_lengths[0]);
1145

1146 1147 1148
            for (j = 0; j < sdu_lengths[0]; ++j) {
              LOG_T(MAC, "%x ", dlsch_buffer[j]);
            }
1149

1150
            LOG_T(MAC, "\n");
1151
#endif
1152 1153
	  }
	}
1154 1155 1156 1157

	// 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,
1158
                                          TBS - ta_len - header_length_total - sdu_length_total - 3
1159
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1160 1161 1162
                                                    ,0, 0
#endif
                                         );
1163

1164 1165 1166 1167
	  // DCCH SDU
	  sdu_lengths[num_sdus] = 0;

	  if (rlc_status.bytes_in_buffer > 0) {
1168
	    LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n",
1169
		  module_idP, frameP, CC_id,
1170 1171 1172 1173
		  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
1174
						      (char *)&dlsch_buffer[sdu_length_total]
1175
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1176 1177 1178
                          ,0, 0
#endif
	    );
1179

1180 1181 1182 1183
            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]));
1184 1185 1186

	    sdu_lcids[num_sdus] = DCCH1;
	    sdu_length_total += sdu_lengths[num_sdus];
1187 1188
            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];
1189
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1;
1190
	    UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus];
1191 1192 1193 1194

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

1195
	    num_sdus++;
1196

nikaeinn's avatar
nikaeinn committed
1197
#ifdef DEBUG_eNB_SCHEDULER
1198 1199 1200
            LOG_T(MAC,
              "[eNB %d][DCCH1] CC_id %d Got %d bytes :",
              module_idP, CC_id, sdu_lengths[num_sdus]);
1201

1202 1203 1204
            for (j = 0; j < sdu_lengths[num_sdus]; ++j) {
              LOG_T(MAC, "%x ", dlsch_buffer[j]);
            }
1205

1206
            LOG_T(MAC, "\n");
nikaeinn's avatar
nikaeinn committed
1207
#endif
1208

1209 1210
	  }
	}
1211 1212

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

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

1220
	  if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) {
1221 1222 1223 1224 1225 1226 1227 1228
	    rlc_status = mac_rlc_status_ind(module_idP,
					    rnti,
					    module_idP,
					    frameP,
					    subframeP,
					    ENB_FLAG_YES,
					    MBMS_FLAG_NO,
					    lcid,
1229
					    TBS - ta_len - header_length_total - sdu_length_total - 3
1230
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1231 1232 1233
                                                    ,0, 0
#endif
                                           );
1234 1235 1236



1237
	    if (rlc_status.bytes_in_buffer > 0) {
1238 1239 1240
	      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,
1241 1242 1243 1244 1245 1246
                    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
1247
						       (char *)&dlsch_buffer[sdu_length_total]
1248
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
1249 1250 1251
                          ,0, 0
#endif
	      );
1252

1253 1254 1255 1256 1257 1258 1259 1260
	      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);
1261

1262 1263
	      sdu_lcids[num_sdus] = lcid;
	      sdu_length_total += sdu_lengths[num_sdus];
1264
	      UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid]++;
1265
              UE_list->eNB_UE_stats[CC_id][UE_id].lcid_sdu[num_sdus] = lcid;
Cedric Roux's avatar
Cedric Roux committed
1266
              UE_list->eNB_UE_stats[CC_id][UE_id].sdu_length_tx[lcid] = sdu_lengths[num_sdus];
1267 1268 1269 1270 1271
	      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;

1272
	      num_sdus++;
1273

1274 1275
	      UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
	    }
1276 1277
	  } else {
            // no TBS left
1278 1279 1280
	    break;
	  }
	}
1281 1282 1283 1284 1285 1286 1287 1288

        /* 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
1289
	// if (num_sdus > 0 ){
1290
	if (ta_len + sdu_length_total + header_length_total > 0) {
1291 1292 1293 1294

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

1295
          mcs = eNB_UE_stats->dlsch_mcs1;
1296

1297 1298 1299 1300 1301 1302
          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);
1303

1304
	  while (TBS < sdu_length_total + header_length_total + ta_len) {
1305 1306 1307 1308
	    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)
1309
	      TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_available_rb);
1310 1311 1312 1313
	      nb_rb = nb_available_rb;
	      break;
	    }

1314 1315
            TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rb);
          }
1316

1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
          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];
                }
              }
1335

1336 1337 1338
              j = j + 1;
            }
          }
1339 1340

	  // decrease mcs until TBS falls below required length
1341
	  while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) {
1342 1343 1344 1345 1346
	    mcs--;
	    TBS = get_TBS_DL(mcs, nb_rb);
	  }

	  // if we have decreased too much or we don't have enough RBs, increase MCS
1347
	  while ((TBS < sdu_length_total + header_length_total + ta_len)
1348 1349 1350 1351 1352 1353 1354 1355
		 && (((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);
	  }

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

#ifdef DEBUG_eNB_SCHEDULER
1361 1362 1363 1364 1365
          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);
1366
#endif
1367

1368 1369
	  if (TBS - header_length_total - sdu_length_total - ta_len <= 2) {
	    padding = TBS - header_length_total - sdu_length_total - ta_len;
1370 1371 1372
	    post_padding = 0;
	  } else {
	    padding = 0;
1373
	    post_padding = 1;
1374 1375
	  }

1376 1377 1378 1379 1380 1381 1382
          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);
1383 1384 1385 1386

	  //#ifdef DEBUG_eNB_SCHEDULER
	  if (ta_update != 31) {
	    LOG_D(MAC,
1387
		  "[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",
1388 1389 1390 1391
		  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,
1392
		  header_length_total);
1393 1394
	  }
	  //#endif
1395
#ifdef DEBUG_eNB_SCHEDULER
1396
          LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n");
1397

1398 1399 1400
          for (i = 0; i < 16; ++i) {
            LOG_T(MAC, "%x.", dlsch_buffer[i]);
          }
1401

1402
          LOG_T(MAC, "\n");
1403
#endif
Cedric Roux's avatar
Cedric Roux committed
1404

1405 1406 1407
          // 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]);
1408

1409 1410 1411 1412
	  // 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;
	  }
1413

1414
	  if (opt_enabled == 1) {
laurent's avatar
laurent committed
1415 1416 1417
	    trace_pdu(DIRECTION_DOWNLINK,
		      (uint8_t *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0],
		      TBS, module_idP, WS_C_RNTI,
1418 1419 1420 1421 1422 1423 1424
		      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);
	  }
1425

1426 1427 1428
	  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),
1429
	    T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS));
1430

1431
          UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb;
1432

1433 1434 1435 1436
          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;
1437 1438

	  UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb;
1439
          UE_list->eNB_UE_stats[CC_id][UE_id].num_mac_sdu_tx = num_sdus;
1440 1441 1442 1443 1444
	  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;

1445 1446 1447 1448
          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;
1449 1450 1451 1452

	  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,
1453 1454
			  UE_list->UE_template[CC_id][UE_id].DAI,
                          subframeP);
1455
	  }
1456

1457
	  // do PUCCH power control
1458 1459
	  // this is the normalized RX power
	  eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
1460

1461 1462 1463 1464
	  /* 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;
1465
	  // this assumes accumulated tpc
1466
	  // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out
1467 1468 1469 1470
	  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) {
1471
	      ue_sched_ctl->pucch1_cqi_update[CC_id] = 0;
1472

1473 1474
        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;
1475 1476 1477 1478 1479

	      if (normalized_rx_power > (target_rx_power + 4)) {
		tpc = 0;	//-1
	      } else if (normalized_rx_power < (target_rx_power - 4)) {
		tpc = 2;	//+1
1480
	      } else {
1481
		tpc = 1;	//0
1482
	      }
1483

1484
	      LOG_D(MAC,
1485 1486
		    "[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,
1487 1488
		    normalized_rx_power, target_rx_power);

Cedric Roux's avatar
Cedric Roux committed
1489
	    }	// Po_PUCCH has been updated
1490
	    else {
1491
	      tpc = 1;	//0
Cedric Roux's avatar
Cedric Roux committed
1492
	    }	// time to do TPC update
1493
	  else {
1494
	    tpc = 1;	//0
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 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
          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);
1531

1532
	  }
1533

1534 1535
	  LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n",
		dl_req->number_pdu);
1536

1537 1538 1539
	  if (!CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP,
					 dl_config_pdu->dci_dl_pdu.
					 dci_dl_pdu_rel8.aggregation_level, rnti)) {
1540
	    ue_sched_ctl->round[CC_id][harq_pid] = 0;
1541 1542
	    dl_req->number_dci++;
	    dl_req->number_pdu++;
Xu Bo's avatar
Xu Bo committed
1543
	    dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
1544

1545 1546
            eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP;
            eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST;
1547

1548 1549 1550 1551 1552
            // 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]);
1553 1554

	    UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid] = 1 - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid];
1555 1556
	    UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs;
	    UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0;
1557
	    AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL,
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
			"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
				    );
1580
	    eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body,
1581 1582
							  (frameP * 10) + subframeP,
							  TBS, eNB->pdu_index[CC_id],
1583
							  eNB->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0]);
Cedric Roux's avatar
Cedric Roux committed
1584

1585 1586 1587
	    LOG_D(MAC,
		  "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n",
		  eNB->pdu_index[CC_id]);
1588

1589
	    eNB->pdu_index[CC_id]++;
1590 1591
	    program_dlsch_acknak(module_idP, CC_id, UE_id,
				 frameP, subframeP,
1592
				 dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx);
1593 1594 1595 1596
	  } else {
	    LOG_W(MAC,
		  "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n",
		  frameP, subframeP, UE_id, rnti);
1597
	  }
1598
	} else {	// There is no data from RLC or MAC header, so don't schedule
1599

1600
	}
1601
      }
1602

1603 1604
      if (cc[CC_id].tdd_Config != NULL) {    // TDD
        set_ul_DAI(module_idP, UE_id, CC_id, frameP, subframeP);
1605
      }
1606 1607
    }			// UE_id loop
  }				// CC_id loop
Cedric Roux's avatar
Cedric Roux committed
1608

1609
  fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_flag);
1610

1611 1612
  stop_meas(&eNB->schedule_dlsch);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT);
1613 1614
}

1615
//------------------------------------------------------------------------------
1616 1617 1618 1619
void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id,
                                             int frameP,
                                             sub_frame_t subframeP,
                                             uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX])
1620 1621 1622 1623 1624 1625 1626 1627 1628
//------------------------------------------------------------------------------
{
  // 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;
1629
  slice_info_t *sli = &RC.mac[Mod_id]->slice_info;
1630 1631 1632 1633
  UE_sched_ctrl *ue_sched_ctl;
  COMMON_channels_t *cc;
  int N_RBG[NFAPI_CC_MAX];

1634 1635
  int slice_sorted_list[MAX_NUM_SLICES];
  int slice_idx;
1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
  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  (*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) {
1653 1654
      for (i = 0; i < sli->n_dl; ++i) {
        owned = sli->pre_processor_results[i].slice_allocation_mask[CC_id][rbg];
1655
        if (owned) {
1656
          used = rballoc_sub[CC_id][rbg];
1657 1658 1659 1660 1661 1662 1663 1664 1665 1666
          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) {
1667
    for (i = 0; i < sli->n_dl; ++i) {
1668 1669
      has_traffic[CC_id][i] = 0;
      for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) {
1670
        if (sli->pre_processor_results[i].nb_rbs_remaining[CC_id][UE_id] > 0) {
1671 1672 1673 1674 1675 1676 1677
          has_traffic[CC_id][i] = 1;
          break;
        }
      }
    }
  }

1678
  slice_priority_sort(Mod_id, slice_sorted_list);
1679 1680 1681 1682 1683 1684 1685 1686

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

1687
    for (i = 0; i < sli->n_dl; ++i) {
1688
      slice_idx = slice_sorted_list[i];
1689

1690
      if (has_traffic[CC_id][slice_idx] == 0) continue;
1691 1692 1693 1694 1695 1696 1697 1698

      // 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;
        }
1699
        if (sli->dl[free_rbgs_map[CC_id][rbg]].isol == 1) {
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
          // 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)
1710
      // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it
1711
      sort_UEs(Mod_id, slice_idx, frameP, subframeP);
1712

1713 1714 1715
      nb_rbs_remaining = sli->pre_processor_results[slice_idx].nb_rbs_remaining;
      nb_rbs_required = sli->pre_processor_results[slice_idx].nb_rbs_required;
      MIMO_mode_indicator = sli->pre_processor_results[slice_idx].MIMO_mode_indicator;
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 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764

      // 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;
            }
          }
        }
      }
    }
  }
}

1765 1766 1767 1768 1769 1770
//------------------------------------------------------------------------------
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;
1771
  slice_info_t *sli = &RC.mac[Mod_id]->slice_info;
1772
  //UE_sched_ctrl *ue_sched_ctl;
1773

1774
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; ++CC_id) {
1775
    for (i = 0; i < sli->n_dl; ++i) {
1776 1777 1778

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

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

        // TODO: Do something here
1785
        // ue_sched_ctl->pre_nb_available_rbs[CC_id];
1786 1787 1788 1789 1790 1791
      }
    }
  }
}


1792 1793
//------------------------------------------------------------------------------
void
1794
fill_DLSCH_dci(module_id_t module_idP,
1795
               frame_t frameP, sub_frame_t subframeP, int *mbsfn_flagP)
1796
//------------------------------------------------------------------------------
1797
{
1798 1799

  // loop over all allocated UEs and compute frequency allocations for PDSCH
1800 1801 1802
  int UE_id = -1;
  uint8_t /* first_rb, */ nb_rb = 3;
  rnti_t rnti;
1803
  //unsigned char *vrb_map;
1804
  uint8_t rballoc_sub[25];
1805 1806
  //uint8_t number_of_subbands=13;

1807
  //unsigned char round;
1808 1809 1810 1811 1812 1813 1814
  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;
1815
  COMMON_channels_t *cc;
1816

Raymond Knopp's avatar
 
Raymond Knopp committed
1817
  start_meas(&eNB->fill_DLSCH_dci);
1818
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME
1819
  (VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_IN);
1820

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

1824
    if (mbsfn_flagP[CC_id] > 0)
Raymond Knopp's avatar
 
Raymond Knopp committed
1825
      continue;
1826

1827 1828 1829
    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
1830

Raymond Knopp's avatar
 
Raymond Knopp committed
1831
    // UE specific DCIs
1832
    for (UE_id = UE_list->head; UE_id >= 0;
1833
         UE_id = UE_list->next[UE_id]) {
1834
      LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", CC_id, UE_id,
1835
            eNB_dlsch_info[module_idP][CC_id][UE_id].status);
1836

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

1839 1840 1841
        // clear scheduling flag
        eNB_dlsch_info[module_idP][CC_id][UE_id].status = S_DL_WAITING;
        rnti = UE_RNTI(module_idP, UE_id);
1842
        harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
1843
        nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
1844

1845 1846 1847 1848
        /// 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];
        }
1849

1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
        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
1870 1871
      }
    }
1872

1873 1874 1875 1876
  }

  stop_meas(&eNB->fill_DLSCH_dci);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_OUT);
1877 1878
}

1879
//------------------------------------------------------------------------------
1880
unsigned char *get_dlsch_sdu(module_id_t module_idP,
1881 1882
                             int CC_id, frame_t frameP, rnti_t rntiP,
                             uint8_t TBindex)
1883
//------------------------------------------------------------------------------
1884
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1885

1886 1887
  int UE_id;
  eNB_MAC_INST *eNB = RC.mac[module_idP];
Raymond Knopp's avatar
 
Raymond Knopp committed
1888

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

1893 1894
    return ((unsigned char *) &eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
  }
1895

1896 1897
  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);
1898

1899
    return ((unsigned char *) &eNB->common_channels[CC_id].PCCH_pdu.payload[0]);
1900
  }
1901

1902
  UE_id = find_UE_id(module_idP, rntiP);
1903

1904 1905
  if (UE_id != -1) {
    LOG_D(MAC,
1906 1907
          "[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);
1908 1909 1910
    return ((unsigned char *) &eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]);
  } else {
    LOG_E(MAC,
1911 1912
          "[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n",
          module_idP, frameP, CC_id, rntiP);
1913 1914
    return NULL;
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1915 1916

}
1917 1918


1919
//------------------------------------------------------------------------------
1920 1921
void
update_ul_dci(module_id_t module_idP,
1922
	      uint8_t CC_idP, rnti_t rntiP, uint8_t daiP, sub_frame_t subframe)
1923
//------------------------------------------------------------------------------
1924
{
1925

1926
  nfapi_hi_dci0_request_t *HI_DCI0_req =
1927
    &RC.mac[module_idP]->HI_DCI0_req[CC_idP][subframe];
1928
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu =
1929
          &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[0];
1930 1931
  COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_idP];
  int i;
1932

1933

Cedric Roux's avatar
Cedric Roux committed
1934
  if (cc->tdd_Config != NULL) {	// TDD
1935
    for (i = 0;
1936
	 i <HI_DCI0_req->hi_dci0_request_body.number_of_dci + HI_DCI0_req->hi_dci0_request_body.number_of_hi;
1937
	 i++) {
1938

1939
      if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) &&
1940 1941
          (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;
1942

1943
    }
1944
  }
1945 1946 1947
}


1948
//------------------------------------------------------------------------------
1949 1950
void
set_ue_dai(sub_frame_t subframeP,
1951 1952
           int UE_id, uint8_t CC_id, uint8_t tdd_config,
           UE_list_t *UE_list)
1953
//------------------------------------------------------------------------------
1954
{
1955
  switch (tdd_config) {
1956 1957 1958 1959 1960
    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;
      }
1961

1962
      break;
1963

1964 1965 1966 1967 1968
    case 1:
      if ((subframeP == 0) || (subframeP == 4) || (subframeP == 5)
          || (subframeP == 9)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1969

1970
      break;
1971

1972 1973 1974 1975
    case 2:
      if ((subframeP == 4) || (subframeP == 5)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1976

1977
      break;
1978

1979 1980 1981 1982
    case 3:
      if ((subframeP == 5) || (subframeP == 7) || (subframeP == 9)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1983

1984
      break;
1985

1986 1987 1988 1989
    case 4:
      if ((subframeP == 0) || (subframeP == 6)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1990

1991
      break;
1992

1993 1994 1995 1996
    case 5:
      if (subframeP == 9) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
1997

1998
      break;
1999

2000 2001 2002 2003 2004
    case 6:
      if ((subframeP == 0) || (subframeP == 1) || (subframeP == 5)
          || (subframeP == 6) || (subframeP == 9)) {
        UE_list->UE_template[CC_id][UE_id].DAI = 0;
      }
2005

2006
      break;
2007

2008 2009 2010 2011
    default:
      UE_list->UE_template[CC_id][UE_id].DAI = 0;
      LOG_I(MAC, "unknown TDD config %d\n", tdd_config);
      break;
2012
  }
2013
}
2014

2015
void schedule_PCH(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
2016 2017
  /* DCI:format 1A/1C P-RNTI:0xFFFE */
  /* PDU:eNB_rrc_inst[Mod_idP].common_channels[CC_id].PCCH_pdu.payload */
2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
  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;
2028 2029 2030 2031
  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] = {
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
    {-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] */
  };
2042 2043 2044 2045 2046
  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 */
2047
#endif
2048 2049 2050

  start_meas(&eNB->schedule_pch);

2051
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
2052
    cc              = &eNB->common_channels[CC_id];
2053
    vrb_map         = (void *) &cc->vrb_map;
2054 2055
    n_rb_dl         = to_prb(cc->mib->message.dl_Bandwidth);
    dl_req          = &eNB->DL_req[CC_id].dl_config_request_body;
2056
    for (uint16_t i = 0; i < MAX_MOBILES_PER_ENB; i++) {
2057 2058 2059 2060
      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) {
2061
        pcch_sdu_length = mac_rrc_data_req(module_idP,
2062 2063
                                           CC_id,
                                           frameP,
2064
                                           PCCH, 1,
2065 2066
                                           &cc->PCCH_pdu.payload[0],
                                           i); // used for ue index
2067 2068 2069 2070 2071 2072
        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);
2073
#ifdef FORMAT1C
2074
	//NO SIB
2075
	if ((subframeP == 0 || subframeP == 1 || subframeP == 2 || subframeP == 4 || subframeP == 6 || subframeP == 9) ||
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 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
	    (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;
	}
2168
#else
2169
	//NO SIB
2170
	if ((subframeP == 0 || subframeP == 1 || subframeP == 2 || subframeP == 4 || subframeP == 6 || subframeP == 9) ||
2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195
	    (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;
	  }
	}
2196

2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222
        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;
        }
2223
#endif
2224 2225 2226 2227
        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));
2228
#ifdef FORMAT1C
2229 2230 2231
        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;
2232
#else
2233 2234 2235 2236 2237 2238 2239
        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;
2240
#endif
2241 2242 2243 2244 2245
        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;
2246

2247
        // Rel10 fields
2248
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2249
        dl_config_pdu->dlsch_pdu.dlsch_pdu_rel10.pdsch_start                  = 3;
2250
#endif
2251
        // Rel13 fields
2252
#if (RRC_VERSION >= MAKE_VERSION(13, 0, 0))
2253 2254 2255
        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;
2256
#endif
2257 2258 2259 2260 2261

	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++;
2262 2263 2264 2265
          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;

2266 2267 2268 2269 2270 2271
	  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;
2272
#ifdef FORMAT1C
2273 2274
          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);
2275
#else
2276 2277 2278
          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
2279
#endif
2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305
	  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;
2306
          eNB->TX_req[CC_id].tx_request_body.tl.tag = NFAPI_TX_REQUEST_BODY_TAG;
2307 2308 2309 2310 2311
	  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;
	}
2312

2313
	if (opt_enabled == 1) {
laurent's avatar
laurent committed
2314
	  trace_pdu(DIRECTION_DOWNLINK,
2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337
		    &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);
2338 2339 2340 2341 2342 2343 2344
      }
    }
  }
  /* this might be misleading when pcch is inactive */
  stop_meas(&eNB->schedule_pch);
  return;
}
2345

2346 2347 2348 2349 2350 2351
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;
2352

2353
  if (sli->dl[slice_id1].prio > sli->dl[slice_id2].prio) {
2354 2355 2356 2357 2358
    return -1;
  }
  return 1;
}

2359 2360
void slice_priority_sort(module_id_t Mod_id, int slice_list[MAX_NUM_SLICES])
{
2361
  int i;
2362
  for (i = 0; i < RC.mac[Mod_id]->slice_info.n_dl; ++i) {
2363 2364 2365
    slice_list[i] = i;
  }

2366 2367
  qsort_r(slice_list, RC.mac[Mod_id]->slice_info.n_dl, sizeof(int),
          slice_priority_compare, &Mod_id);
2368
}