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

nikaeinn's avatar
nikaeinn committed
22
23
/*! \file eNB_scheduler_primitives.c
 * \brief primitives used by eNB for BCH, RACH, ULSCH, DLSCH scheduling
24
25
26
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
27
 * \version 1.0
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
 * @ingroup _mac

 */

#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"

#include "LAYER2/MAC/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

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

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

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

61
62
63
64
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1


65
//------------------------------------------------------------------------------
66
void init_ue_sched_info(void)
67
//------------------------------------------------------------------------------
68
{
69
  module_id_t i,j,k;
70
71

  for (i=0; i<NUMBER_OF_eNB_MAX; i++) {
Cedric Roux's avatar
Cedric Roux committed
72
    for (k=0; k<MAX_NUM_CCs; k++) {
73
74
75
76
77
78
79
80
81
82
      for (j=0; j<NUMBER_OF_UE_MAX; j++) {
        // init DL
        eNB_dlsch_info[i][k][j].weight           = 0;
        eNB_dlsch_info[i][k][j].subframe         = 0;
        eNB_dlsch_info[i][k][j].serving_num      = 0;
        eNB_dlsch_info[i][k][j].status           = S_DL_NONE;
        // init UL
        eNB_ulsch_info[i][k][j].subframe         = 0;
        eNB_ulsch_info[i][k][j].serving_num      = 0;
        eNB_ulsch_info[i][k][j].status           = S_UL_NONE;
83
      }
84
    }
85
86
87
88
89
  }
}



90
//------------------------------------------------------------------------------
91
unsigned char get_ue_weight(module_id_t module_idP, int CC_id, int ue_idP)
92
//------------------------------------------------------------------------------
93
{
94

95
  return(eNB_dlsch_info[module_idP][CC_id][ue_idP].weight);
96
97
98

}

99
//------------------------------------------------------------------------------
100
DCI_PDU *get_dci_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframeP)
101
//------------------------------------------------------------------------------
102
{
103

knopp's avatar
   
knopp committed
104
  return(&eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu);
105
106
107

}

108
//------------------------------------------------------------------------------
109
int find_UE_id(module_id_t mod_idP, rnti_t rntiP)
110
//------------------------------------------------------------------------------
111
{
knopp's avatar
   
knopp committed
112
113
  int UE_id;
  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
114

115
116
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;
knopp's avatar
   
knopp committed
117
118
119
    if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) {
      return(UE_id);
    }
120
  }
121

knopp's avatar
   
knopp committed
122
  return(-1);
123
124
}

125
//------------------------------------------------------------------------------
126
int UE_num_active_CC(UE_list_t *listP,int ue_idP)
127
//------------------------------------------------------------------------------
128
{
knopp's avatar
   
knopp committed
129
130
  return(listP->numactiveCCs[ue_idP]);
}
131

132
//------------------------------------------------------------------------------
133
int UE_PCCID(module_id_t mod_idP,int ue_idP)
134
//------------------------------------------------------------------------------
135
{
knopp's avatar
   
knopp committed
136
137
  return(eNB_mac_inst[mod_idP].UE_list.pCC_id[ue_idP]);
}
138

139
//------------------------------------------------------------------------------
140
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
141
//------------------------------------------------------------------------------
142
{
143

knopp's avatar
   
knopp committed
144
  rnti_t rnti = eNB_mac_inst[mod_idP].UE_list.UE_template[UE_PCCID(mod_idP,ue_idP)][ue_idP].rnti;
145

146
  if (rnti>0) {
knopp's avatar
   
knopp committed
147
    return (rnti);
148
  }
149

150
  LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
151
152
  //display_backtrace();
  return(NOT_A_RNTI);
153
}
knopp's avatar
   
knopp committed
154

155
//------------------------------------------------------------------------------
156
boolean_t is_UE_active(module_id_t mod_idP, int ue_idP)
157
//------------------------------------------------------------------------------
158
{
knopp's avatar
   
knopp committed
159
  return(eNB_mac_inst[mod_idP].UE_list.active[ue_idP]);
160
}
knopp's avatar
   
knopp committed
161
162
163

/*
uint8_t find_active_UEs(module_id_t module_idP,int CC_id){
164
165
166
167
168
169
170

  module_id_t        ue_mod_id      = 0;
  rnti_t        rnti         = 0;
  uint8_t            nb_active_ue = 0;

  for (ue_mod_id=0;ue_mod_id<NUMBER_OF_UE_MAX;ue_mod_id++) {

knopp's avatar
   
knopp committed
171
      if (((rnti=eNB_mac_inst[module_idP][CC_id].UE_template[ue_mod_id].rnti) !=0)&&(eNB_mac_inst[module_idP][CC_id].UE_template[ue_mod_id].ul_active==TRUE)){
172
173

          if (mac_xface->get_eNB_UE_stats(module_idP,rnti) != NULL){ // check at the phy enb_ue state for this rnti
174
      nb_active_ue++;
175
176
          }
          else { // this ue is removed at the phy => remove it at the mac as well
177
      mac_remove_ue(module_idP, CC_id, ue_mod_id);
178
179
180
181
182
          }
      }
  }
  return(nb_active_ue);
}
knopp's avatar
   
knopp committed
183
*/
184
185


186
187
// get aggregation (L) form phy for a give UE
unsigned char get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt)
188
{
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  unsigned char aggregation=3;
  
  switch (dci_fmt){
    
  case format0:
    aggregation = cqi2fmt0_agg[bw_index][cqi];
    break;
  case format1:
  case format1A:
  case format1B:
  case format1D:
    aggregation = cqi2fmt1x_agg[bw_index][cqi]; 
    break;
  case format2:
  case format2A:
  case format2B:
  case format2C:
  case format2D:
    aggregation = cqi2fmt2x_agg[bw_index][cqi]; 
    break;
  case format1C:
  case format1E_2A_M10PRB:
  case format3:
  case format3A:
  case format4:
  default:
    LOG_W(MAC,"unsupported DCI format %d\n",dci_fmt);
  }

   LOG_D(MAC,"Aggregation level %d (cqi %d, bw_index %d, format %d)\n", 
   	1<<aggregation, cqi,bw_index,dci_fmt);
   
221
222
223
  return aggregation;
}
#ifdef CBA
224
/*
knopp's avatar
   
knopp committed
225
uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, int CC_id,unsigned char group_id){
226
227
228
229
230
231

  module_id_t    UE_id;
  rnti_t    rnti;
  unsigned char nb_ue_in_pusch=0;
  LTE_eNB_UE_stats* eNB_UE_stats;

232
  for (UE_id=group_id;UE_id<NUMBER_OF_UE_MAX;UE_id+=eNB_mac_inst[module_idP].common_channels[CC_id].num_active_cba_groups) {
233

knopp's avatar
   
knopp committed
234
235
      if (((rnti=eNB_mac_inst[module_idP][CC_id].UE_template[UE_id].rnti) !=0) &&
          (eNB_mac_inst[module_idP][CC_id].UE_template[UE_id].ul_active==TRUE)    &&
236
          (mac_get_rrc_status(module_idP,1,UE_id) > RRC_CONNECTED)){
237
238
239
240
241
242
243
  //  && (UE_is_to_be_scheduled(module_idP,UE_id)))
  // check at the phy enb_ue state for this rnti
  if ((eNB_UE_stats= mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti)) != NULL){
    if ((eNB_UE_stats->mode == PUSCH) && (UE_is_to_be_scheduled(module_idP,UE_id) == 0)){
      nb_ue_in_pusch++;
    }
  }
244
245
246
247
      }
  }
  return(nb_ue_in_pusch);
}
248
*/
249
#endif
knopp's avatar
   
knopp committed
250

251
252
void dump_ue_list(UE_list_t *listP, int ul_flag)
{
knopp's avatar
   
knopp committed
253
  int j;
254
255
256

  if ( ul_flag == 0 ) {
    for (j=listP->head; j>=0; j=listP->next[j]) {
257
258
259
      LOG_T(MAC,"node %d => %d\n",j,listP->next[j]);
    }
  } else {
260
    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
261
262
      LOG_T(MAC,"node %d => %d\n",j,listP->next_ul[j]);
    }
knopp's avatar
   
knopp committed
263
264
265
  }
}

266
267
int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
{
knopp's avatar
   
knopp committed
268
  int UE_id;
269
  int i, j;
270

knopp's avatar
   
knopp committed
271
  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
272

knopp's avatar
   
knopp committed
273
  LOG_D(MAC,"[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n",mod_idP,cc_idP,rntiP,UE_list->avail,UE_list->num_UEs);
274
  dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
275

276
277
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] == TRUE) continue;
278
printf("MAC: new UE id %d rnti %x\n", i, rntiP);
279
    UE_id = i;
knopp's avatar
   
knopp committed
280
281
282
283
284
285
286
    UE_list->UE_template[cc_idP][UE_id].rnti       = rntiP;
    UE_list->UE_template[cc_idP][UE_id].configured = FALSE;
    UE_list->numactiveCCs[UE_id]                   = 1;
    UE_list->numactiveULCCs[UE_id]                 = 1;
    UE_list->pCC_id[UE_id]                         = cc_idP;
    UE_list->ordered_CCids[0][UE_id]               = cc_idP;
    UE_list->ordered_ULCCids[0][UE_id]             = cc_idP;
knopp's avatar
   
knopp committed
287
    UE_list->num_UEs++;
knopp's avatar
   
knopp committed
288
    UE_list->active[UE_id]                         = TRUE;
289
    memset((void*)&UE_list->UE_sched_ctrl[UE_id],0,sizeof(UE_sched_ctrl));
knopp's avatar
   
knopp committed
290

291
292
    for (j=0; j<8; j++) {
      UE_list->UE_template[cc_idP][UE_id].oldNDI[j]    = (j==0)?1:0;   // 1 because first transmission is with format1A (Msg4) for harq_pid 0
knopp's avatar
   
knopp committed
293
      UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = (j==harq_pidP)?0:1; // 1st transmission is with Msg3;
knopp's avatar
   
knopp committed
294
    }
295

296
    eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING;
297
    eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING;
knopp's avatar
   
knopp committed
298
    LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP);
299
    dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
300
    return(UE_id);
301
  }
knopp's avatar
   
knopp committed
302

303
printf("MAC: cannot add new UE for rnti %x\n", rntiP);
knopp's avatar
   
knopp committed
304
  LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
305
  dump_ue_list(UE_list,0);
306
307
308
  return(-1);
}

309
//------------------------------------------------------------------------------
310
int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) 
311
//------------------------------------------------------------------------------
312
{
313
  int i;
knopp's avatar
   
knopp committed
314
  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
315
  int UE_id = find_UE_id(mod_idP,rntiP);
316
  int pCC_id;
317

318
  if (UE_id == -1) {
319
printf("MAC: cannot remove UE rnti %x\n", rntiP);
320
    LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP);
321
    mac_phy_remove_ue(mod_idP, rntiP);
322
323
324
    return 0;
  }

325
326
  pCC_id = UE_PCCID(mod_idP,UE_id);

327
printf("MAC: remove UE %d rnti %x\n", UE_id, rntiP);
328
  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
329
  dump_ue_list(UE_list,0);
330

331
332
333
  UE_list->active[UE_id] = FALSE;
  UE_list->num_UEs--;

334
  // clear all remaining pending transmissions
335
336
337
338
339
340
341
342
343
344
345
346
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3]  = 0;

  UE_list->UE_template[pCC_id][UE_id].ul_SR             = 0;
  UE_list->UE_template[pCC_id][UE_id].rnti              = NOT_A_RNTI;
  UE_list->UE_template[pCC_id][UE_id].ul_active         = FALSE;
  eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
  eNB_ulsch_info[mod_idP][pCC_id][UE_id].status                      = S_UL_NONE;
  eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
  eNB_dlsch_info[mod_idP][pCC_id][UE_id].status                      = S_DL_NONE;
knopp's avatar
   
knopp committed
347

348
349
  mac_phy_remove_ue(mod_idP,rntiP);

350
351
352
353
  // check if this has an RA process active
  RA_TEMPLATE *RA_template;
  for (i=0;i<NB_RA_PROC_MAX;i++) {
    RA_template = (RA_TEMPLATE *)&eNB_mac_inst[mod_idP].common_channels[pCC_id].RA_template[i];
354
    if (RA_template->rnti == rntiP){
355
356
357
358
359
360
361
      RA_template->RA_active=FALSE;
      RA_template->generate_rar=0;
      RA_template->generate_Msg4=0;
      RA_template->wait_ack_Msg4=0;
      RA_template->timing_offset=0;
      RA_template->RRC_timer=20;
      RA_template->rnti = 0;
362
      //break;
363
364
    }
  }
knopp's avatar
   
knopp committed
365

366
  return 0;
367
368
369
}


knopp's avatar
   
knopp committed
370

371
372
int prev(UE_list_t *listP, int nodeP, int ul_flag)
{
knopp's avatar
   
knopp committed
373
  int j;
374

375
  if (ul_flag == 0 ) {
376
    if (nodeP==listP->head) {
377
      return(nodeP);
378
    }
379
380

    for (j=listP->head; j>=0; j=listP->next[j]) {
381
      if (listP->next[j]==nodeP) {
382
        return(j);
383
    }
384
    }
385
  } else {
386
    if (nodeP==listP->head_ul) {
387
      return(nodeP);
388
    }
389
390

    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
391
      if (listP->next_ul[j]==nodeP) {
392
        return(j);
393
      }
394
    }
knopp's avatar
   
knopp committed
395
  }
knopp's avatar
   
knopp committed
396

397
  LOG_E(MAC,"error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n",
398
        nodeP, (ul_flag == 0)? "DL" : "UL");
399
  dump_ue_list(listP, ul_flag);
knopp's avatar
   
knopp committed
400
401


knopp's avatar
   
knopp committed
402
403
  return(-1);
}
404

405
406
void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag)
{
407

knopp's avatar
   
knopp committed
408
409
  int prev_i,prev_j,next_i,next_j;

410
411
  LOG_T(MAC,"Swapping UE %d,%d\n",nodeiP,nodejP);
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
412

413
414
  prev_i = prev(listP,nodeiP,ul_flag);
  prev_j = prev(listP,nodejP,ul_flag);
415

416
  if ((prev_i<0) || (prev_j<0)) {
417
    mac_xface->macphy_exit("swap_UEs: problem");
418
419
    return; // not reached
  }
knopp's avatar
   
knopp committed
420

421
  if (ul_flag == 0) {
422
423
424
425
426
    next_i = listP->next[nodeiP];
    next_j = listP->next[nodejP];
  } else {
    next_i = listP->next_ul[nodeiP];
    next_j = listP->next_ul[nodejP];
knopp's avatar
   
knopp committed
427
  }
knopp's avatar
   
knopp committed
428

429
  LOG_T(MAC,"[%s] next_i %d, next_i, next_j %d, head %d \n",
430
431
        (ul_flag == 0)? "DL" : "UL",
        next_i,next_j,listP->head);
432
433

  if (ul_flag == 0 ) {
knopp's avatar
   
knopp committed
434

435
436
    if (next_i == nodejP) {   // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...
      LOG_T(MAC,"Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n");
437

438
439
      listP->next[nodeiP] = next_j;
      listP->next[nodejP] = nodeiP;
440

441
      if (nodeiP==listP->head) { // case i j n(j)
442
        listP->head = nodejP;
443
      } else {
444
        listP->next[prev_i] = nodejP;
445
      }
446
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
447
448
449
      LOG_T(MAC,"Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n");
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = nodejP;
450

451
      if (nodejP==listP->head) { // case j i n(i)
452
        listP->head = nodeiP;
453
      } else {
454
        listP->next[prev_j] = nodeiP;
455
      }
456
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...
457
458
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = next_j;
459
460


461
      if (nodeiP==listP->head) {
462
463
464
465
466
467
468
469
470
471
        LOG_T(MAC,"changing head to %d\n",nodejP);
        listP->head=nodejP;
        listP->next[prev_j] = nodeiP;
      } else if (nodejP==listP->head) {
        LOG_D(MAC,"changing head to %d\n",nodeiP);
        listP->head=nodeiP;
        listP->next[prev_i] = nodejP;
      } else {
        listP->next[prev_i] = nodejP;
        listP->next[prev_j] = nodeiP;
472
473
474
475
476
477
      }
    }
  } else { // ul_flag

    if (next_i == nodejP) {   // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...
      LOG_T(MAC,"[UL] Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n");
478

479
480
      listP->next_ul[nodeiP] = next_j;
      listP->next_ul[nodejP] = nodeiP;
481

482
      if (nodeiP==listP->head_ul) { // case i j n(j)
483
        listP->head_ul = nodejP;
484
      } else {
485
        listP->next_ul[prev_i] = nodejP;
486
      }
487
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
488
489
490
      LOG_T(MAC,"[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n");
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = nodejP;
491

492
      if (nodejP==listP->head_ul) { // case j i n(i)
493
        listP->head_ul = nodeiP;
494
      } else {
495
        listP->next_ul[prev_j] = nodeiP;
496
      }
497
498
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...

499
500
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = next_j;
501
502


503
      if (nodeiP==listP->head_ul) {
504
505
506
507
508
509
510
511
512
513
        LOG_T(MAC,"[UL]changing head to %d\n",nodejP);
        listP->head_ul=nodejP;
        listP->next_ul[prev_j] = nodeiP;
      } else if (nodejP==listP->head_ul) {
        LOG_T(MAC,"[UL]changing head to %d\n",nodeiP);
        listP->head_ul=nodeiP;
        listP->next_ul[prev_i] = nodejP;
      } else {
        listP->next_ul[prev_i] = nodejP;
        listP->next_ul[prev_j] = nodeiP;
514
      }
knopp's avatar
   
knopp committed
515
516
    }
  }
517

518
519
  LOG_T(MAC,"After swap\n");
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
520
521
522
523
}



524

525
526
527
528
529




/*
Cedric Roux's avatar
Cedric Roux committed
530
  #if defined(Rel10) || defined(Rel14)
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
  unsigned char generate_mch_header( unsigned char *mac_header,
  unsigned char num_sdus,
  unsigned short *sdu_lengths,
  unsigned char *sdu_lcids,
  unsigned char msi,
  unsigned char short_padding,
  unsigned short post_padding) {

  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[2*num_sdus],*ce_ptr;

  ce_ptr = &mac_header_control_elements[0];

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

  // SUBHEADER for MSI CE
  if (msi != 0) {// there is MSI MAC Control Element
  if (first_element>0) {
  mac_header_ptr->E = 1;
  mac_header_ptr+=last_size;
  }
  else {
  first_element = 1;
  }
  if (num_sdus*2 < 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 = MCH_SCHDL_INFO;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = num_sdus*2;
  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 = MCH_SCHDL_INFO;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L    = (num_sdus*2)&0x7fff;
  last_size=3;
  }
  // Create the MSI MAC Control Element here
  }

  // SUBHEADER for MAC SDU (MCCH+MTCHs)
  for (i=0;i<num_sdus;i++) {
  if (first_element>0) {
  mac_header_ptr->E = 1;
  mac_header_ptr+=last_size;
  }
  else {
  first_element = 1;
  }
  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    = (unsigned short) sdu_lengths[i]&0x7fff;
  last_size=3;
  }
  }

  if (post_padding>0) {// we have lots of padding at the end of the packet
  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++;
  }
  else { // no end of packet padding
  // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
  mac_header_ptr++;
  }

  // Copy MSI Control Element to the end of the MAC Header if it presents
  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,ce_ptr-mac_header_control_elements);
  mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements);
  }

  return((unsigned char*)mac_header_ptr - mac_header);
  }
  #endif
 */
void add_common_dci(DCI_PDU *DCI_pdu,
642
643
644
645
646
647
648
649
                    void *pdu,
                    rnti_t rnti,
                    unsigned char dci_size_bytes,
                    unsigned char aggregation,
                    unsigned char dci_size_bits,
                    unsigned char dci_fmt,
                    uint8_t ra_flag)
{
650
  if (DCI_pdu->Num_dci == NUM_DCI_MAX) { printf("%s: DCI FULL, fatal!\n", __FUNCTION__); abort(); }
651

652
653
654
655
656
657
658
  memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_dci].dci_pdu[0],pdu,dci_size_bytes);
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].dci_length   = dci_size_bits;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].L            = aggregation;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].rnti         = rnti;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].format       = dci_fmt;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].ra_flag      = ra_flag;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].search_space = DCI_COMMON_SPACE;
659
660


661
  DCI_pdu->Num_dci++;
662
  LOG_D(MAC,"add common dci format %d for rnti %x \n",dci_fmt,rnti);
663
664
}

665
666
void add_ue_spec_dci(DCI_PDU *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt,uint8_t ra_flag)
{
667
  if (DCI_pdu->Num_dci == NUM_DCI_MAX) { printf("%s: DCI FULL, fatal!\n", __FUNCTION__); abort(); }
668

669
670
671
672
673
674
675
  memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_dci].dci_pdu[0],pdu,dci_size_bytes);
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].dci_length   = dci_size_bits;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].L            = aggregation;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].rnti         = rnti;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].format       = dci_fmt;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].ra_flag      = ra_flag;
  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].search_space = DCI_UE_SPACE;
676

677
  DCI_pdu->Num_dci++;
nikaeinn's avatar
nikaeinn committed
678

679
  LOG_D(MAC,"add ue specific dci format %d for rnti %x \n",dci_fmt,rnti);
680
681
682
683
684
685
686
}





// This has to be updated to include BSR information
687
688
uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id)
{
689

690
691
  UE_TEMPLATE *UE_template    = &eNB_mac_inst[module_idP].UE_list.UE_template[CC_id][UE_id];
  UE_sched_ctrl *UE_sched_ctl = &eNB_mac_inst[module_idP].UE_list.UE_sched_ctrl[UE_id];
692

693

Florian Kaltenberger's avatar
Florian Kaltenberger committed
694
695
696
697
698
699
  // do not schedule UE if UL is not working
  if (UE_sched_ctl->ul_failure_timer>0)
    return(0);
  if (UE_sched_ctl->ul_out_of_sync>0)
    return(0);

700
701
  LOG_D(MAC,"[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id));

knopp's avatar
   
knopp committed
702
703
704
705
  if ((UE_template->bsr_info[LCGID0]>0) ||
      (UE_template->bsr_info[LCGID1]>0) ||
      (UE_template->bsr_info[LCGID2]>0) ||
      (UE_template->bsr_info[LCGID3]>0) ||
gauthier's avatar
gauthier committed
706
      (UE_template->ul_SR>0) || // uplink scheduling request
707
      ((UE_sched_ctl->ul_inactivity_timer>20)&&
708
709
710
711
712
       (UE_sched_ctl->ul_scheduled==0))||  // every 2 frames when RRC_CONNECTED
      ((UE_sched_ctl->ul_inactivity_timer>10)&&
       (UE_sched_ctl->ul_scheduled==0)&&
       (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) // every Frame when not RRC_CONNECTED
    { 
713

714
    LOG_D(MAC,"[eNB %d][PUSCH] UE %d/%x should be scheduled\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id));
715
    return(1);
716
  } else {
717
    return(0);
718
  }
719
720
721
722
723
}




724
725
uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, uint32_t *rballoc)
{
726
727
728
729
730

  int i;
  uint32_t rballoc_dci=0;
  unsigned char nb_rb_alloc=0;

731
  for (i=0; i<(mac_xface->frame_parms->N_RB_DL-2); i+=2) {
732
733
734
735
736
737
    if (((*rballoc>>i)&3)==0) {
      *rballoc |= (3<<i);
      rballoc_dci |= (1<<((12-i)>>1));
      nb_rb_alloc+=2;
    }

738
    if (nb_rb_alloc==nb_rb) {
739
      return(rballoc_dci);
740
    }
741
742
  }

743
744
745
746
  if ((mac_xface->frame_parms->N_RB_DL&1)==1) {
    if ((*rballoc>>(mac_xface->frame_parms->N_RB_DL-1)&1)==0) {
      *rballoc |= (1<<(mac_xface->frame_parms->N_RB_DL-1));
      rballoc_dci |= 1;//(1<<(mac_xface->frame_parms->N_RB_DL>>1));
747
    }
748
  }
749

750
751
752
  return(rballoc_dci);
}

753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
int get_bw_index(module_id_t module_id, uint8_t CC_id)
{

  int bw_index=0;
  LTE_DL_FRAME_PARMS* frame_parms = mac_xface->get_lte_frame_parms(module_id,CC_id);

  switch (frame_parms->N_RB_DL) {
  case 6: // 1.4 MHz
    bw_index=0;
    break;

  case 25: // 5HMz
    bw_index=1;
    break;

  case 50: // 10HMz
    bw_index=2;
    break;

  case 100: // 20HMz
    bw_index=3;
    break;

  default:
    bw_index=1;
778
    LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting bw_index to 1\n", module_id, frame_parms->N_RB_DL, CC_id);
779
780
781
782
783
784
    break;
  }

  return bw_index;
}

785
786
787
int get_min_rb_unit(module_id_t module_id, uint8_t CC_id)
{

788
  int min_rb_unit=0;
789
790
  LTE_DL_FRAME_PARMS* frame_parms = mac_xface->get_lte_frame_parms(module_id,CC_id);

791
792
793
794
  switch (frame_parms->N_RB_DL) {
  case 6: // 1.4 MHz
    min_rb_unit=1;
    break;
795

796
797
798
  case 25: // 5HMz
    min_rb_unit=2;
    break;
799

800
801
802
  case 50: // 10HMz
    min_rb_unit=3;
    break;
803

804
805
806
  case 100: // 20HMz
    min_rb_unit=4;
    break;
807

808
809
  default:
    min_rb_unit=2;
Cedric Roux's avatar
Cedric Roux committed
810
811
    LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n",
          module_id, frame_parms->N_RB_DL, CC_id);
812
813
    break;
  }
814

815
816
  return min_rb_unit;
}
817

818
819
uint32_t allocate_prbs_sub(int nb_rb, uint8_t *rballoc)
{
820
821
822
823
824

  int check=0;//check1=0,check2=0;
  uint32_t rballoc_dci=0;
  //uint8_t number_of_subbands=13;

825
  LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n",
826
        rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,mac_xface->frame_parms->N_RBG);
827

828
  while((nb_rb >0) && (check < mac_xface->frame_parms->N_RBG)) {
knopp's avatar
   
knopp committed
829
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
830
    if(rballoc[check] == 1) {
831
      rballoc_dci |= (1<<((mac_xface->frame_parms->N_RBG-1)-check));
832

833
      switch (mac_xface->frame_parms->N_RB_DL) {
834
835
836
837
838
      case 6:
        nb_rb--;
        break;

      case 25:
839
        if ((check == mac_xface->frame_parms->N_RBG-1)) {
840
          nb_rb--;
841
        } else {
842
          nb_rb-=2;
843
        }
844
845
846
847

        break;

      case 50:
848
        if ((check == mac_xface->frame_parms->N_RBG-1)) {
849
          nb_rb-=2;
850
        } else {
851
          nb_rb-=3;
852
        }
853
854
855
856
857
858

        break;

      case 100:
        nb_rb-=4;
        break;
859
      }
860
861
862
863
864
    }

    //      printf("rb_alloc %x\n",rballoc_dci);
    check = check+1;
    //    check1 = check1+2;
865
  }
866

867
868
869
870
871
872
873
  // rballoc_dci = (rballoc_dci)&(0x1fff);
  LOG_T(MAC,"*********RBALLOC : %x\n",rballoc_dci);
  // exit(-1);
  return (rballoc_dci);
}


874
875
876
int get_nb_subband(void)
{

877
878
  int nb_sb=0;

879
  switch (mac_xface->frame_parms->N_RB_DL) {
880
  case 6:
881
    nb_sb=0;
882
    break;
883

884
885
  case 15:
    nb_sb = 4;  // sb_size =4
886
887

  case 25:
888
889
    nb_sb = 7; // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs
    break;
890

891
892
893
  case 50:    // sb_size =6
    nb_sb = 9;
    break;
894

895
896
897
  case 75:  // sb_size =8
    nb_sb = 10;
    break;
898

899
900
901
  case 100: // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs
    nb_sb = 13;
    break;
902

903
904
905
906
  default:
    nb_sb=0;
    break;
  }
907

908
  return nb_sb;
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

void init_CCE_table(int module_idP,int CC_idP)
{
  memset(eNB_mac_inst[module_idP].CCE_table[CC_idP],0,800*sizeof(int));
} 


int get_nCCE_offset(int *CCE_table,
		    const unsigned char L, 
		    const int nCCE, 
		    const int common_dci, 
		    const unsigned short rnti, 
		    const unsigned char subframe)
{

  int search_space_free,m,nb_candidates = 0,l,i;
  unsigned int Yk;
   /*
    printf("CCE Allocation: ");
    for (i=0;i<nCCE;i++)
    printf("%d.",CCE_table[i]);
    printf("\n");
  */
  if (common_dci == 1) {
    // check CCE(0 ... L-1)
    nb_candidates = (L==4) ? 4 : 2;
    nb_candidates = min(nb_candidates,nCCE/L);
knopp's avatar
knopp committed
938

939
    //    printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L);
knopp's avatar
knopp committed
940

941
942
943
944
    for (m = nb_candidates-1 ; m >=0 ; m--) {

      search_space_free = 1;
      for (l=0; l<L; l++) {
knopp's avatar
knopp committed
945

946
	//	printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]);
947
948
949
950
951
952
953
        if (CCE_table[(m*L) + l] == 1) {
          search_space_free = 0;
          break;
        }
      }
     
      if (search_space_free == 1) {
knopp's avatar
knopp committed
954

955
	//	printf("returning %d\n",m*L);
knopp's avatar
knopp committed
956

957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
        for (l=0; l<L; l++)
          CCE_table[(m*L)+l]=1;
        return(m*L);
      }
    }

    return(-1);

  } else { // Find first available in ue specific search space
    // according to procedure in Section 9.1.1 of 36.213 (v. 8.6)
    // compute Yk
    Yk = (unsigned int)rnti;

    for (i=0; i<=subframe; i++)
      Yk = (Yk*39827)%65537;

    Yk = Yk % (nCCE/L);


    switch (L) {
    case 1:
    case 2:
      nb_candidates = 6;
      break;

    case 4:
    case 8:
      nb_candidates = 2;
      break;

    default:
      DevParam(L, nCCE, rnti);
      break;
    }

knopp's avatar
knopp committed
992

993
    LOG_D(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates);
994
995
996
997
998

    for (m = 0 ; m < nb_candidates ; m++) {
      search_space_free = 1;

      for (l=0; l<L; l++) {
Cedric Roux's avatar
Cedric Roux committed
999
1000
        int cce = (((Yk+m)%(nCCE/L))*L) + l;
        if (cce >= nCCE || CCE_table[cce] == 1) {
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
          search_space_free = 0;
          break;
        }
      }

      if (search_space_free == 1) {
        for (l=0; l<L; l++)
          CCE_table[(((Yk+m)%(nCCE/L))*L)+l]=1;

        return(((Yk+m)%(nCCE/L))*L);
      }
    }

    return(-1);
  }
}

1018
1019
1020
1021
1022
void dump_CCE_table(int *CCE_table,const int nCCE,const unsigned short rnti,const int subframe,int L) {

  int nb_candidates = 0,i;
  unsigned int Yk;
  
1023
  printf("CCE 0: ");
1024
1025
  for (i=0;i<nCCE;i++) {
    printf("%1d.",CCE_table[i]);
1026
    if ((i&7) == 7)
knopp's avatar
knopp committed
1027
      printf("\n CCE %d: ",i);
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  }

  Yk = (unsigned int)rnti;
  
  for (i=0; i<=subframe; i++)
    Yk = (Yk*39827)%65537;
  
  Yk = Yk % (nCCE/L);
  
  
  switch (L) {
  case 1:
  case 2:
    nb_candidates = 6;
    break;
    
  case 4:
  case 8:
    nb_candidates = 2;
    break;
    
  default:
    DevParam(L, nCCE, rnti);
    break;
  }
  
  
  printf("rnti %x, Yk*L = %d, nCCE %d (nCCE/L %d),nb_cand*L %d\n",rnti,Yk*L,nCCE,nCCE/L,nb_candidates*L);

}

1059
1060
1061
1062
1063
1064
1065
1066
1067
// Allocate the CCEs
int allocate_CCEs(int module_idP,
		  int CC_idP,
		  int subframeP,
		  int test_onlyP) {


  int *CCE_table = eNB_mac_inst[module_idP].CCE_table[CC_idP];
  DCI_PDU *DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_idP].DCI_pdu;
1068
  int nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,1,subframeP);
1069
  int fCCE;
1070
  int i,j;
1071
  DCI_ALLOC_t *dci_alloc;
1072
  int nCCE=0;
1073