eNB_scheduler_dlsch.c 93.2 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
Cedric Roux's avatar
Cedric Roux committed
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
 */
nikaeinn's avatar
nikaeinn committed
21
22
23

/*! \file eNB_scheduler_dlsch.c
 * \brief procedures related to eNB for the DLSCH transport channel
24
 * \author  Navid Nikaein and Raymond Knopp
nikaeinn's avatar
nikaeinn committed
25
 * \date 2010 - 2014
26
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
27
 * \version 1.0
28
29
30
31
 * @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"
Cedric Roux's avatar
Cedric Roux committed
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
knopp's avatar
   
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

knopp's avatar
knopp committed
78
  eNB_dlsch_info[module_idP][CC_id][UE_id].rnti =
79
          UE_RNTI(module_idP, UE_id);
knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
95
96
  int next_ue;
  UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
97

knopp's avatar
knopp committed
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) {
knopp's avatar
knopp committed
102
      return next_ue;
103
    }
knopp's avatar
knopp committed
104
  }
105

knopp's avatar
knopp committed
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
    }
knopp's avatar
knopp committed
111
  }
knopp's avatar
   
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

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
135
  ce_ptr = &mac_header_control_elements[0];
136

knopp's avatar
knopp committed
137
  // compute header components
138

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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;
knopp's avatar
   
knopp committed
176
    }
177

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

knopp's avatar
knopp committed
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;
knopp's avatar
   
knopp committed
205
    }
206

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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

knopp's avatar
knopp committed
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]);
knopp's avatar
knopp committed
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;
knopp's avatar
   
knopp committed
238
    }
239

knopp's avatar
knopp committed
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
knopp's avatar
knopp committed
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
knopp's avatar
   
knopp committed
263
    }
knopp's avatar
knopp committed
264
  }
265

knopp's avatar
knopp committed
266
  /*
267

knopp's avatar
knopp committed
268
    printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
269

knopp's avatar
knopp committed
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


knopp's avatar
knopp committed
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
    }
knopp's avatar
knopp committed
282
  */
283
  if (post_padding > 0) {    // we have lots of padding at the end of the packet
knopp's avatar
knopp committed
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
knopp's avatar
knopp committed
292
293
294
    // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
    mac_header_ptr++;
  }
295

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

knopp's avatar
knopp committed
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);
knopp's avatar
knopp committed
302
    mac_header_ptr +=
303
            (unsigned char) (ce_ptr - mac_header_control_elements);
knopp's avatar
knopp committed
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
{

knopp's avatar
knopp committed
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
knopp's avatar
knopp committed
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);
knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
376

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

382
383
384
          default:
            break;
        }
knopp's avatar
knopp committed
385

386
        break;
knopp's avatar
knopp committed
387

388
389
390
391
      case 4:
        //      if ((subframeP==8)||(subframeP==9))
        //  UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI;
        break;
knopp's avatar
knopp committed
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;
knopp's avatar
   
knopp committed
405
    }
knopp's avatar
knopp committed
406
  }
knopp's avatar
   
knopp committed
407
408
}

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

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

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

  // reset the slice percentage for inactive slices
421
422
  for (i = sli->n_dl; i < MAX_NUM_SLICES; i++) {
    sli->dl[i].pct = 0;
423
  }
424
425
  for (i = 0; i < sli->n_dl; i++) {
    if (sli->dl[i].pct < 0) {
426
427
      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);
428
      sli->dl[i].pct = 0;
429
    }
430
    sli->tot_pct_dl += sli->dl[i].pct;
431
432
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}
611

612
613
// changes to pre-processor for eMTC

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

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

knopp's avatar
knopp committed
656
  start_meas(&eNB->schedule_dlsch);
657
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN);
658

knopp's avatar
knopp committed
659
660
661
662
  // 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) {
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
      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;
697
    }
knopp's avatar
knopp committed
698
699
700
  }
  //weight = get_ue_weight(module_idP,UE_id);
  aggregation = 2;
701
  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
knopp's avatar
knopp committed
702
703
704
705
706
707
    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)
708
        total_nb_available_rb[CC_id]--;
knopp's avatar
knopp committed
709
710
711
712
713
714
715
716
717
718

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

720
721
722
  // 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);
723

knopp's avatar
   
knopp committed
724
  start_meas(&eNB->schedule_dlsch_preprocessor);
725
  dlsch_scheduler_pre_processor(module_idP,
726
                                slice_idxP,
727
728
                                frameP,
                                subframeP,
Xu Bo's avatar
Xu Bo committed
729
                                mbsfn_flag);
knopp's avatar
   
knopp committed
730
  stop_meas(&eNB->schedule_dlsch_preprocessor);
731
732

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT);
733

734
  //RC.mac[module_idP]->slice_info.slice_counter--;
735
  // Do the multiplexing and actual allocation only when all slices have been pre-processed.
736
737
738
739
740
  //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;
  //}
741

742
  if (RC.mac[module_idP]->slice_info.interslice_share_active) {
743
744
    dlsch_scheduler_interslice_multiplexing(module_idP, frameP, subframeP);
  }
745
746

  for (CC_id = 0; CC_id < NFAPI_CC_MAX; CC_id++) {
knopp's avatar
knopp committed
747
    LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id);
748

knopp's avatar
knopp committed
749
    dl_req = &eNB->DL_req[CC_id].dl_config_request_body;
750

knopp's avatar
knopp committed
751
    if (mbsfn_flag[CC_id] > 0)
knopp's avatar
   
knopp committed
752
      continue;
753

754
755
    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
knopp's avatar
knopp committed
756
      rnti = UE_RNTI(module_idP, UE_id);
757
      eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id];
758
      ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
759

knopp's avatar
knopp committed
760
      if (rnti == NOT_A_RNTI) {
761
762
        LOG_D(MAC, "Cannot find rnti for UE_id %d (num_UEs %d)\n", UE_id, UE_list->num_UEs);
        continue_flag = 1;
763
      }
764

knopp's avatar
knopp committed
765
      if (eNB_UE_stats == NULL) {
766
767
        LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n");
        continue_flag = 1;
768
      }
769

770
      if (!ue_dl_slice_membership(module_idP, UE_id, slice_idxP))
771
        continue;
772

knopp's avatar
knopp committed
773
      if (continue_flag != 1) {
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
        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;
        }
knopp's avatar
knopp committed
791
      }
792

knopp's avatar
knopp committed
793
      /* if (continue_flag != 1 */
Cedric Roux's avatar
Cedric Roux committed
794
      if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) ||	// no RBs allocated
knopp's avatar
knopp committed
795
796
797
798
799
800
801
	  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
      }
knopp's avatar
   
knopp committed
802

803
804
805
806
807
808
809
810
811
      // 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);
knopp's avatar
knopp committed
812
      }
813

knopp's avatar
knopp committed
814
      if (continue_flag == 1) {
815
816
        add_ue_dlsch_info(module_idP, CC_id, UE_id, subframeP, S_DL_NONE);
        continue;
knopp's avatar
knopp committed
817
      }
Cedric Roux's avatar
Cedric Roux committed
818

knopp's avatar
knopp committed
819
      nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
820
      harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP ,subframeP);
821

knopp's avatar
knopp committed
822
      round = ue_sched_ctl->round[CC_id][harq_pid];
823

824
      UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti;
knopp's avatar
knopp committed
825
      UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = mac_eNB_get_rrc_status(module_idP, rnti);
826
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid;
knopp's avatar
knopp committed
827
      UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round;
828

829
830
      if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED)
        continue;
831

832
      header_length_total = 0;
knopp's avatar
knopp committed
833
834
      sdu_length_total = 0;
      num_sdus = 0;
835

knopp's avatar
knopp committed
836
      /*
837
838
839
      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);
knopp's avatar
knopp committed
840
841
      */
      if (nfapi_mode) {
842
843
        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
844
        eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1,
845
                                        RC.mac[module_idP]->slice_info.dl[slice_idxP].maxmcs);  // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs);
knopp's avatar
knopp committed
846
      }
847

848
849
      // Store stats
      // UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi;
850

851
      // Initializing the rb allocation indicator for each UE
knopp's avatar
knopp committed
852
      for (j = 0; j < N_RBG[CC_id]; j++) {
853
        UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0;
knopp's avatar
knopp committed
854
855
856
      }

      LOG_D(MAC,
857
858
859
860
861
            "[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);
knopp's avatar
knopp committed
862
863
864

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

866
867
868
        // 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);
knopp's avatar
knopp committed
869
870
871
872
873

	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,
874
			  UE_list->UE_template[CC_id][UE_id].DAI, subframeP);
875
	    LOG_D(MAC,
knopp's avatar
knopp committed
876
877
878
879
880
		  "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);
	  }

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
          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];
                }
              }
901

902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
              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]);
957

knopp's avatar
knopp committed
958
959
960
961
962
963
	    }
	    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;