eNB_scheduler_primitives.c 34.4 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
59
60
61
 * @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

#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1

knopp's avatar
knopp committed
62
63
int to_prb(int dl_Bandwidth) {
  int prbmap[6] = {6,15,25,50,75,100};
64

knopp's avatar
knopp committed
65
66
67
68
69
70
71
72
73
74
  AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n");
  return(prbmap[dl_Bandwidth]);
}

int to_rbg(int dl_Bandwidth) {
  int rbgmap[6] = {6,8,13,17,19,25};

  AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n");
  return(rbgmap[dl_Bandwidth]);
}
75
//------------------------------------------------------------------------------
76
void init_ue_sched_info(void)
77
//------------------------------------------------------------------------------
78
{
79
  module_id_t i,j,k;
80
81

  for (i=0; i<NUMBER_OF_eNB_MAX; i++) {
Cedric Roux's avatar
Cedric Roux committed
82
    for (k=0; k<MAX_NUM_CCs; k++) {
83
84
85
86
87
88
89
90
91
92
      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;
93
      }
94
    }
95
96
97
98
99
  }
}



100
//------------------------------------------------------------------------------
101
unsigned char get_ue_weight(module_id_t module_idP, int CC_id, int ue_idP)
102
//------------------------------------------------------------------------------
103
{
104

105
  return(eNB_dlsch_info[module_idP][CC_id][ue_idP].weight);
106
107
108

}

109
//------------------------------------------------------------------------------
110
DCI_PDU *get_dci_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframeP)
111
//------------------------------------------------------------------------------
112
{
113

114
  return(&RC.mac[module_idP]->common_channels[CC_id].DCI_pdu);
115
116
117

}

118
//------------------------------------------------------------------------------
119
int find_UE_id(module_id_t mod_idP, rnti_t rntiP)
120
//------------------------------------------------------------------------------
121
{
knopp's avatar
   
knopp committed
122
  int UE_id;
123
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
124

125
126
  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
127
128
129
    if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) {
      return(UE_id);
    }
130
  }
131

knopp's avatar
   
knopp committed
132
  return(-1);
133
134
}

135
//------------------------------------------------------------------------------
136
int UE_num_active_CC(UE_list_t *listP,int ue_idP)
137
//------------------------------------------------------------------------------
138
{
knopp's avatar
   
knopp committed
139
140
  return(listP->numactiveCCs[ue_idP]);
}
141

142
//------------------------------------------------------------------------------
143
int UE_PCCID(module_id_t mod_idP,int ue_idP)
144
//------------------------------------------------------------------------------
145
{
146
  return(RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]);
knopp's avatar
   
knopp committed
147
}
148

149
//------------------------------------------------------------------------------
150
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
151
//------------------------------------------------------------------------------
152
{
153

154
  rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP,ue_idP)][ue_idP].rnti;
155

156
  if (rnti>0) {
knopp's avatar
   
knopp committed
157
    return (rnti);
158
  }
159

160
  LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
161
162
  //display_backtrace();
  return(NOT_A_RNTI);
163
}
knopp's avatar
   
knopp committed
164

165
//------------------------------------------------------------------------------
166
boolean_t is_UE_active(module_id_t mod_idP, int ue_idP)
167
//------------------------------------------------------------------------------
168
{
169
  return(RC.mac[mod_idP]->UE_list.active[ue_idP]);
170
}
knopp's avatar
   
knopp committed
171
172
173

/*
uint8_t find_active_UEs(module_id_t module_idP,int CC_id){
174
175
176
177
178
179
180

  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
181
      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)){
182
183

          if (mac_xface->get_eNB_UE_stats(module_idP,rnti) != NULL){ // check at the phy enb_ue state for this rnti
184
      nb_active_ue++;
185
186
          }
          else { // this ue is removed at the phy => remove it at the mac as well
187
      mac_remove_ue(module_idP, CC_id, ue_mod_id);
188
189
190
191
192
          }
      }
  }
  return(nb_active_ue);
}
knopp's avatar
   
knopp committed
193
*/
194
195


196
197
// get aggregation (L) form phy for a give UE
unsigned char get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt)
198
{
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
  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);
   
231
232
233
  return aggregation;
}
#ifdef CBA
234
/*
knopp's avatar
   
knopp committed
235
uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, int CC_id,unsigned char group_id){
236
237
238
239
240
241

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

242
  for (UE_id=group_id;UE_id<NUMBER_OF_UE_MAX;UE_id+=RC.mac[module_idP]->common_channels[CC_id].num_active_cba_groups) {
243

knopp's avatar
   
knopp committed
244
245
      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)    &&
246
          (mac_get_rrc_status(module_idP,1,UE_id) > RRC_CONNECTED)){
247
248
249
250
251
252
253
  //  && (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++;
    }
  }
254
255
256
257
      }
  }
  return(nb_ue_in_pusch);
}
258
*/
259
#endif
knopp's avatar
   
knopp committed
260

261
262
void dump_ue_list(UE_list_t *listP, int ul_flag)
{
knopp's avatar
   
knopp committed
263
  int j;
264
265
266

  if ( ul_flag == 0 ) {
    for (j=listP->head; j>=0; j=listP->next[j]) {
267
268
269
      LOG_T(MAC,"node %d => %d\n",j,listP->next[j]);
    }
  } else {
270
    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
271
272
      LOG_T(MAC,"node %d => %d\n",j,listP->next_ul[j]);
    }
knopp's avatar
   
knopp committed
273
274
275
  }
}

276
277
int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
{
knopp's avatar
   
knopp committed
278
  int UE_id;
279
  int i, j;
280

281
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
282

knopp's avatar
   
knopp committed
283
  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);
284
  dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
285

286
287
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] == TRUE) continue;
288
printf("MAC: new UE id %d rnti %x\n", i, rntiP);
289
    UE_id = i;
knopp's avatar
   
knopp committed
290
291
292
293
294
295
296
    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
297
    UE_list->num_UEs++;
knopp's avatar
   
knopp committed
298
    UE_list->active[UE_id]                         = TRUE;
299
    memset((void*)&UE_list->UE_sched_ctrl[UE_id],0,sizeof(UE_sched_ctrl));
knopp's avatar
   
knopp committed
300

301
302
    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
303
      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
304
    }
305

306
    eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING;
307
    eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING;
knopp's avatar
   
knopp committed
308
    LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP);
309
    dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
310
    return(UE_id);
311
  }
knopp's avatar
   
knopp committed
312

313
printf("MAC: cannot add new UE for rnti %x\n", rntiP);
knopp's avatar
   
knopp committed
314
  LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
315
  dump_ue_list(UE_list,0);
316
317
318
  return(-1);
}

319
//------------------------------------------------------------------------------
320
int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) 
321
//------------------------------------------------------------------------------
322
{
323
  int i;
324
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
325
  int UE_id = find_UE_id(mod_idP,rntiP);
326
  int pCC_id;
327

328
  if (UE_id == -1) {
329
printf("MAC: cannot remove UE rnti %x\n", rntiP);
330
    LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP);
331
    mac_phy_remove_ue(mod_idP, rntiP);
332
333
334
    return 0;
  }

335
336
  pCC_id = UE_PCCID(mod_idP,UE_id);

337
printf("MAC: remove UE %d rnti %x\n", UE_id, rntiP);
338
  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
339
  dump_ue_list(UE_list,0);
340

341
342
343
  UE_list->active[UE_id] = FALSE;
  UE_list->num_UEs--;

344
  // clear all remaining pending transmissions
345
346
347
348
349
350
351
352
353
354
355
356
  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
357

358
359
  mac_phy_remove_ue(mod_idP,rntiP);

360
361
362
  // check if this has an RA process active
  RA_TEMPLATE *RA_template;
  for (i=0;i<NB_RA_PROC_MAX;i++) {
363
    RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[pCC_id].RA_template[i];
364
    if (RA_template->rnti == rntiP){
365
366
367
368
369
370
371
      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;
372
      //break;
373
374
    }
  }
knopp's avatar
   
knopp committed
375

376
  return 0;
377
378
379
}


knopp's avatar
   
knopp committed
380

381
382
int prev(UE_list_t *listP, int nodeP, int ul_flag)
{
knopp's avatar
   
knopp committed
383
  int j;
384

385
  if (ul_flag == 0 ) {
386
    if (nodeP==listP->head) {
387
      return(nodeP);
388
    }
389
390

    for (j=listP->head; j>=0; j=listP->next[j]) {
391
      if (listP->next[j]==nodeP) {
392
        return(j);
393
    }
394
    }
395
  } else {
396
    if (nodeP==listP->head_ul) {
397
      return(nodeP);
398
    }
399
400

    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
401
      if (listP->next_ul[j]==nodeP) {
402
        return(j);
403
      }
404
    }
knopp's avatar
   
knopp committed
405
  }
knopp's avatar
   
knopp committed
406

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


knopp's avatar
   
knopp committed
412
413
  return(-1);
}
414

415
416
void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag)
{
417

knopp's avatar
   
knopp committed
418
419
  int prev_i,prev_j,next_i,next_j;

420
421
  LOG_T(MAC,"Swapping UE %d,%d\n",nodeiP,nodejP);
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
422

423
424
  prev_i = prev(listP,nodeiP,ul_flag);
  prev_j = prev(listP,nodejP,ul_flag);
425

426
  if ((prev_i<0) || (prev_j<0)) {
427
    mac_xface->macphy_exit("swap_UEs: problem");
428
429
    return; // not reached
  }
knopp's avatar
   
knopp committed
430

431
  if (ul_flag == 0) {
432
433
434
435
436
    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
437
  }
knopp's avatar
   
knopp committed
438

439
  LOG_T(MAC,"[%s] next_i %d, next_i, next_j %d, head %d \n",
440
441
        (ul_flag == 0)? "DL" : "UL",
        next_i,next_j,listP->head);
442
443

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

445
446
    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");
447

448
449
      listP->next[nodeiP] = next_j;
      listP->next[nodejP] = nodeiP;
450

451
      if (nodeiP==listP->head) { // case i j n(j)
452
        listP->head = nodejP;
453
      } else {
454
        listP->next[prev_i] = nodejP;
455
      }
456
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
457
458
459
      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;
460

461
      if (nodejP==listP->head) { // case j i n(i)
462
        listP->head = nodeiP;
463
      } else {
464
        listP->next[prev_j] = nodeiP;
465
      }
466
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...
467
468
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = next_j;
469
470


471
      if (nodeiP==listP->head) {
472
473
474
475
476
477
478
479
480
481
        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;
482
483
484
485
486
487
      }
    }
  } 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");
488

489
490
      listP->next_ul[nodeiP] = next_j;
      listP->next_ul[nodejP] = nodeiP;
491

492
      if (nodeiP==listP->head_ul) { // case i j n(j)
493
        listP->head_ul = nodejP;
494
      } else {
495
        listP->next_ul[prev_i] = nodejP;
496
      }
497
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
498
499
500
      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;
501

502
      if (nodejP==listP->head_ul) { // case j i n(i)
503
        listP->head_ul = nodeiP;
504
      } else {
505
        listP->next_ul[prev_j] = nodeiP;
506
      }
507
508
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...

509
510
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = next_j;
511
512


513
      if (nodeiP==listP->head_ul) {
514
515
516
517
518
519
520
521
522
523
        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;
524
      }
knopp's avatar
   
knopp committed
525
526
    }
  }
527

528
529
  LOG_T(MAC,"After swap\n");
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
530
531
532
533
}



534

535
536
537
538
539




/*
Cedric Roux's avatar
Cedric Roux committed
540
  #if defined(Rel10) || defined(Rel14)
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
642
643
644
645
646
647
648
649
650
651
  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,
652
653
654
655
656
657
658
659
                    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)
{
660
661
662
663
664
665
666
667
668
669

  memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].dci_pdu[0],pdu,dci_size_bytes);
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].dci_length = dci_size_bits;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].L          = aggregation;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].rnti       = rnti;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].format     = dci_fmt;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci].ra_flag    = ra_flag;


  DCI_pdu->Num_common_dci++;
670
  LOG_D(MAC,"add common dci format %d for rnti %x \n",dci_fmt,rnti);
671
672
}

673
674
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)
{
675
676
677
678
679
680
681
682
683

  memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].dci_pdu[0],pdu,dci_size_bytes);
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].dci_length = dci_size_bits;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].L          = aggregation;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].rnti       = rnti;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].format     = dci_fmt;
  DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci].ra_flag    = ra_flag;

  DCI_pdu->Num_ue_spec_dci++;
nikaeinn's avatar
nikaeinn committed
684

685
  LOG_D(MAC,"add ue specific dci format %d for rnti %x \n",dci_fmt,rnti);
686
687
688
689
690
691
692
}





// This has to be updated to include BSR information
693
694
uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id)
{
695

696
697
  UE_TEMPLATE *UE_template    = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id];
  UE_sched_ctrl *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id];
698

699

Florian Kaltenberger's avatar
Florian Kaltenberger committed
700
701
702
703
704
705
  // 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);

706
707
  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
708
709
710
711
  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
712
      (UE_template->ul_SR>0) || // uplink scheduling request
713
      ((UE_sched_ctl->ul_inactivity_timer>20)&&
714
715
716
717
718
       (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
    { 
719

720
    LOG_D(MAC,"[eNB %d][PUSCH] UE %d/%x should be scheduled\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id));
721
    return(1);
722
  } else {
723
    return(0);
724
  }
725
726
727
728
729
}




knopp's avatar
knopp committed
730
uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, int N_RB_DL, uint32_t *rballoc)
731
{
732
733
734
735
736

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

knopp's avatar
knopp committed
737
  for (i=0; i<(N_RB_DL-2); i+=2) {
738
739
740
741
742
743
    if (((*rballoc>>i)&3)==0) {
      *rballoc |= (3<<i);
      rballoc_dci |= (1<<((12-i)>>1));
      nb_rb_alloc+=2;
    }

744
    if (nb_rb_alloc==nb_rb) {
745
      return(rballoc_dci);
746
    }
747
748
  }

knopp's avatar
knopp committed
749
750
751
752
  if ((N_RB_DL&1)==1) {
    if ((*rballoc>>(N_RB_DL-1)&1)==0) {
      *rballoc |= (1<<(N_RB_DL-1));
      rballoc_dci |= 1;
753
    }
754
  }
755

756
757
758
  return(rballoc_dci);
}

759
760
761
762
int get_bw_index(module_id_t module_id, uint8_t CC_id)
{

  int bw_index=0;
knopp's avatar
knopp committed
763
764
 
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
765

knopp's avatar
knopp committed
766
  switch (N_RB_DL) {
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  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;
knopp's avatar
knopp committed
785
    LOG_W(MAC,"[eNB %d] N_RB_DL %d unknown for CC_id %d, setting bw_index to 1\n", module_id, N_RB_DL,CC_id);
786
787
788
789
790
791
    break;
  }

  return bw_index;
}

792
793
794
int get_min_rb_unit(module_id_t module_id, uint8_t CC_id)
{

795
  int min_rb_unit=0;
knopp's avatar
knopp committed
796
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
797

knopp's avatar
knopp committed
798
  switch (N_RB_DL) {
799
800
801
  case 6: // 1.4 MHz
    min_rb_unit=1;
    break;
802

803
804
805
  case 25: // 5HMz
    min_rb_unit=2;
    break;
806

807
808
809
  case 50: // 10HMz
    min_rb_unit=3;
    break;
810

811
812
813
  case 100: // 20HMz
    min_rb_unit=4;
    break;
814

815
816
  default:
    min_rb_unit=2;
Cedric Roux's avatar
Cedric Roux committed
817
    LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n",
knopp's avatar
knopp committed
818
          module_id, N_RB_DL, CC_id);
819
820
    break;
  }
821

822
823
  return min_rb_unit;
}
824

knopp's avatar
knopp committed
825
uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, uint8_t *rballoc)
826
{
827
828
829
830
831

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

832
  LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n",
knopp's avatar
knopp committed
833
        rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,N_RBG);
834

knopp's avatar
knopp committed
835
  while((nb_rb >0) && (check < N_RBG)) {
knopp's avatar
   
knopp committed
836
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
837
    if(rballoc[check] == 1) {
knopp's avatar
knopp committed
838
      rballoc_dci |= (1<<((N_RBG-1)-check));
839

knopp's avatar
knopp committed
840
      switch (N_RB_DL) {
841
842
843
844
845
      case 6:
        nb_rb--;
        break;

      case 25:
knopp's avatar
knopp committed
846
        if ((check == N_RBG-1)) {
847
          nb_rb--;
848
        } else {
849
          nb_rb-=2;
850
        }
851
852
853
854

        break;

      case 50:
knopp's avatar
knopp committed
855
        if ((check == N_RBG-1)) {
856
          nb_rb-=2;
857
        } else {
858
          nb_rb-=3;
859
        }
860
861
862
863
864
865

        break;

      case 100:
        nb_rb-=4;
        break;
866
      }
867
868
869
870
871
    }

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

874
875
876
877
878
879
880
  // rballoc_dci = (rballoc_dci)&(0x1fff);
  LOG_T(MAC,"*********RBALLOC : %x\n",rballoc_dci);
  // exit(-1);
  return (rballoc_dci);
}


knopp's avatar
knopp committed
881
int get_nb_subband(int N_RB_DL)
882
883
{

884
885
  int nb_sb=0;

knopp's avatar
knopp committed
886
  switch (N_RB_DL) {
887
  case 6:
888
    nb_sb=0;
889
    break;
890

891
892
  case 15:
    nb_sb = 4;  // sb_size =4
893
894

  case 25:
895
896
    nb_sb = 7; // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs
    break;
897

898
899
900
  case 50:    // sb_size =6
    nb_sb = 9;
    break;
901

902
903
904
  case 75:  // sb_size =8
    nb_sb = 10;
    break;
905

906
907
908
  case 100: // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs
    nb_sb = 13;
    break;
909

910
911
912
913
  default:
    nb_sb=0;
    break;
  }
914

915
  return nb_sb;
916
917

}
918
919
920

void init_CCE_table(int module_idP,int CC_idP)
{
921
  memset(RC.mac[module_idP]->CCE_table[CC_idP],0,800*sizeof(int));
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
} 


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
945

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

948
949
950
951
    for (m = nb_candidates-1 ; m >=0 ; m--) {

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

953
	//	printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]);
954
955
956
957
958
959
960
        if (CCE_table[(m*L) + l] == 1) {
          search_space_free = 0;
          break;
        }
      }
     
      if (search_space_free == 1) {
knopp's avatar
knopp committed
961

962
	//	printf("returning %d\n",m*L);
knopp's avatar
knopp committed
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
992
993
994
995
996
997
998
        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
999

1000
    LOG_D(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates);
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023

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

      for (l=0; l<L; l++) {
        if (CCE_table[(((Yk+m)%(nCCE/L))*L) + l] == 1) {
          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);
  }
}

1024
1025
1026
1027
1028
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;
  
1029
  printf("CCE 0: ");
1030
1031
  for (i=0;i<nCCE;i++) {
    printf("%1d.",CCE_table[i]);
1032
    if ((i&7) == 7)
knopp's avatar
knopp committed
1033
      printf("\n CCE %d: ",i);
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
1059
1060
1061
1062
1063
1064
  }

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

}

1065
1066
1067
1068
1069
1070
1071
// Allocate the CCEs
int allocate_CCEs(int module_idP,
		  int CC_idP,
		  int subframeP,
		  int test_onlyP) {


1072
1073
  int *CCE_table = RC.mac[module_idP]->CCE_table[CC_idP];
  DCI_PDU *DCI_pdu = &RC.mac[module_idP]->common_channels[CC_idP].DCI_pdu;
1074
  int nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,1,subframeP);
1075
  int fCCE;
1076
  int i,j;
1077
  DCI_ALLOC_t *dci_alloc;
1078
  int nCCE=0;
1079

1080