eNB_scheduler_primitives.c 23.3 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2
3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


nikaeinn's avatar
nikaeinn committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16
17
18
19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.
20
21

  Contact Information
nikaeinn's avatar
nikaeinn committed
22
23
24
25
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
nikaeinn's avatar
nikaeinn committed
27
28
29
30
31

*******************************************************************************/

/*! \file eNB_scheduler_primitives.c
 * \brief primitives used by eNB for BCH, RACH, ULSCH, DLSCH scheduling
32
33
34
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
35
 * \version 1.0
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
 * @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


void init_ue_sched_info(void){
  module_id_t i,j;
  for (i=0;i<NUMBER_OF_eNB_MAX;i++){
      for (j=0;j<NUMBER_OF_UE_MAX;j++){
          // init DL
          eNB_dlsch_info[i][j].weight           = 0;
          eNB_dlsch_info[i][j].subframe         = 0;
          eNB_dlsch_info[i][j].serving_num      = 0;
          eNB_dlsch_info[i][j].status           = S_DL_NONE;
          // init UL
          eNB_ulsch_info[i][j].subframe         = 0;
          eNB_ulsch_info[i][j].serving_num      = 0;
          eNB_ulsch_info[i][j].status           = S_UL_NONE;
      }
  }
}



knopp's avatar
   
knopp committed
90
unsigned char get_ue_weight(module_id_t module_idP, int ue_idP){
91

knopp's avatar
   
knopp committed
92
  return(eNB_dlsch_info[module_idP][ue_idP].weight);
93
94
95

}

knopp's avatar
   
knopp committed
96
DCI_PDU *get_dci_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframeP) {
97

knopp's avatar
   
knopp committed
98
  return(&eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu);
99
100
101

}

knopp's avatar
   
knopp committed
102
int find_UE_id(module_id_t mod_idP, rnti_t rntiP) {
103

knopp's avatar
   
knopp committed
104
105
106
107
108
109
110
  int UE_id;
  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
  
  for (UE_id=UE_list->head;UE_id>=0;UE_id=UE_list->next[UE_id]){
    if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) {
      return(UE_id);
    }
111
  }
knopp's avatar
   
knopp committed
112
  return(-1);
113
114
115

}

knopp's avatar
   
knopp committed
116
117
118
int UE_num_active_CC(UE_list_t *listP,int ue_idP) {
  return(listP->numactiveCCs[ue_idP]);
}
119

knopp's avatar
   
knopp committed
120
121
122
int UE_PCCID(module_id_t mod_idP,int ue_idP) {
  return(eNB_mac_inst[mod_idP].UE_list.pCC_id[ue_idP]);
}
123

knopp's avatar
   
knopp committed
124
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP) {
125

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

knopp's avatar
   
knopp committed
128
129
130
131
132
  if (rnti>0)
    return (rnti);
  LOG_E(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
  mac_xface->macphy_exit("");
  return(0);
133
}
knopp's avatar
   
knopp committed
134
135
136

boolean_t is_UE_active(module_id_t mod_idP, int ue_idP){
  return(eNB_mac_inst[mod_idP].UE_list.active[ue_idP]);
137
}
knopp's avatar
   
knopp committed
138
139
140

/*
uint8_t find_active_UEs(module_id_t module_idP,int CC_id){
141
142
143
144
145
146
147

  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
148
      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)){
149
150

          if (mac_xface->get_eNB_UE_stats(module_idP,rnti) != NULL){ // check at the phy enb_ue state for this rnti
knopp's avatar
   
knopp committed
151
	    nb_active_ue++;
152
153
          }
          else { // this ue is removed at the phy => remove it at the mac as well
knopp's avatar
   
knopp committed
154
	    mac_remove_ue(module_idP, CC_id, ue_mod_id);
155
156
157
158
159
          }
      }
  }
  return(nb_active_ue);
}
knopp's avatar
   
knopp committed
160
*/
161
162
163


// get aggregatiob form phy for a give UE
knopp's avatar
   
knopp committed
164
unsigned char process_ue_cqi (module_id_t module_idP, int ue_idP) {
165
166
167
168
169
  unsigned char aggregation=2;
  // check the MCS and SNR and set the aggregation accordingly
  return aggregation;
}
#ifdef CBA
knopp's avatar
   
knopp committed
170
uint8_t find_num_active_UEs_in_cbagroup(module_id_t module_idP, int CC_id,unsigned char group_id){
171
172
173
174
175
176

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

knopp's avatar
   
knopp committed
177
  for (UE_id=group_id;UE_id<NUMBER_OF_UE_MAX;UE_id+=eNB_mac_inst[module_idP][CC_id].num_active_cba_groups) {
178

knopp's avatar
   
knopp committed
179
180
      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)    &&
181
          (mac_get_rrc_status(module_idP,1,UE_id) > RRC_CONNECTED)){
knopp's avatar
   
knopp committed
182
183
184
185
186
187
188
	//  && (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++;
	  }
	}
189
190
191
192
193
      }
  }
  return(nb_ue_in_pusch);
}
#endif
knopp's avatar
   
knopp committed
194

195
void dump_ue_list(UE_list_t *listP, int ul_flag) {
knopp's avatar
   
knopp committed
196
  int j;
197
198
199
200
201
202
203
204
  if ( ul_flag == 0 ){
    for (j=listP->head;j>=0;j=listP->next[j]) {
      LOG_T(MAC,"node %d => %d\n",j,listP->next[j]);
    }
  } else {
    for (j=listP->head_ul;j>=0;j=listP->next_ul[j]) {
      LOG_T(MAC,"node %d => %d\n",j,listP->next_ul[j]);
    }
knopp's avatar
   
knopp committed
205
206
207
  }
}

knopp's avatar
   
knopp committed
208
int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP) {
knopp's avatar
   
knopp committed
209
210
  int UE_id;
  int j;
211

knopp's avatar
   
knopp committed
212
213
214
  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
  
  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);
215
  dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
216
217
218
219
220

  if (UE_list->avail>=0) {
    UE_id = UE_list->avail;
    UE_list->avail = UE_list->next[UE_list->avail];
    UE_list->next[UE_id] = UE_list->head;
221
    UE_list->next_ul[UE_id] = UE_list->head;
knopp's avatar
   
knopp committed
222
    UE_list->head = UE_id;
223
    UE_list->head_ul = UE_id;
knopp's avatar
   
knopp committed
224
225
226
227
228
229
230
    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
231
    UE_list->num_UEs++;
knopp's avatar
   
knopp committed
232
    UE_list->active[UE_id]                         = TRUE;
knopp's avatar
   
knopp committed
233
234

    for (j=0;j<8;j++) {
knopp's avatar
   
knopp committed
235
      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
236
      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
237
238
239
240
    }
    eNB_ulsch_info[mod_idP][UE_id].status = S_UL_WAITING;
    eNB_dlsch_info[mod_idP][UE_id].status = S_UL_WAITING;
    LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP);
241
    dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
242
    return(UE_id);
243
  }
knopp's avatar
   
knopp committed
244
245

  LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
246
  dump_ue_list(UE_list,0);
247
248
249
  return(-1);
}

knopp's avatar
   
knopp committed
250
251
int mac_remove_ue(module_id_t mod_idP, int ue_idP) {

252
  int prev,i, ret=-1;
knopp's avatar
   
knopp committed
253
254
255

  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
  int pCC_id = UE_PCCID(mod_idP,ue_idP);
256

knopp's avatar
   
knopp committed
257
  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",ue_idP,pCC_id, UE_list->UE_template[pCC_id][ue_idP].rnti);
258
  dump_ue_list(UE_list,0);
259
260

  // clear all remaining pending transmissions
knopp's avatar
   
knopp committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  UE_list->UE_template[pCC_id][ue_idP].bsr_info[LCGID0]  = 0;
  UE_list->UE_template[pCC_id][ue_idP].bsr_info[LCGID1]  = 0;
  UE_list->UE_template[pCC_id][ue_idP].bsr_info[LCGID2]  = 0;
  UE_list->UE_template[pCC_id][ue_idP].bsr_info[LCGID3]  = 0;

  UE_list->UE_template[pCC_id][ue_idP].ul_SR             = 0;
  UE_list->UE_template[pCC_id][ue_idP].rnti              = 0;
  UE_list->UE_template[pCC_id][ue_idP].ul_active         = FALSE;
  eNB_ulsch_info[mod_idP][ue_idP].rnti                        = 0;
  eNB_ulsch_info[mod_idP][ue_idP].status                      = S_UL_NONE;
  eNB_dlsch_info[mod_idP][ue_idP].rnti                        = 0;
  eNB_dlsch_info[mod_idP][ue_idP].status                      = S_DL_NONE;

  rrc_eNB_free_UE_index(mod_idP,ue_idP);

  prev = UE_list->head;
  for (i=UE_list->head;i>=0;i=UE_list->next[i]) {
    if (i == ue_idP) {
      // link prev to next in Active list
      if (prev==UE_list->head)
	UE_list->head = UE_list->next[i];
      else
	UE_list->next[prev] = UE_list->next[i];
      // add UE id (i)to available 
      UE_list->next[i] = UE_list->avail;
      UE_list->avail = i;
      UE_list->active[i] = FALSE;
knopp's avatar
   
knopp committed
288
      UE_list->num_UEs--;  
289
290
      ret=0;
      break;
knopp's avatar
   
knopp committed
291
292
293
    }
    prev=i;
  }
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  // do the same for UL
  prev = UE_list->head_ul;
  for (i=UE_list->head_ul;i>=0;i=UE_list->next_ul[i]) {
    if (i == ue_idP) {
      // link prev to next in Active list
      if (prev==UE_list->head_ul)
	UE_list->head_ul = UE_list->next_ul[i];
      else
	UE_list->next_ul[prev] = UE_list->next_ul[i];
      // add UE id (i)to available 
      UE_list->next_ul[i] = UE_list->avail;
      ret = 0;
      break;
    }
    prev=i;
  }
  if (ret == 0)
    return (0);
knopp's avatar
   
knopp committed
312
313
  
  LOG_E(MAC,"error in mac_remove_ue(), could not find previous to %d in UE_list, should never happen, Dumping UE list\n",ue_idP);
314
  dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
315
  mac_xface->macphy_exit("");    
knopp's avatar
   
knopp committed
316
317
  return(-1);

318
319
320
}


knopp's avatar
   
knopp committed
321

322
int prev(UE_list_t *listP, int nodeP, int ul_flag) {
knopp's avatar
   
knopp committed
323
  int j;
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  
  if (ul_flag == 0 ) {
    if (nodeP==listP->head)
      return(nodeP);
    for (j=listP->head;j>=0;j=listP->next[j]) {
      if (listP->next[j]==nodeP)
	return(j);
    }
  } else {
    if (nodeP==listP->head_ul)
      return(nodeP);
    for (j=listP->head_ul;j>=0;j=listP->next_ul[j]) {
      if (listP->next_ul[j]==nodeP)
	return(j);
    }
knopp's avatar
   
knopp committed
339
  }
knopp's avatar
   
knopp committed
340

341

knopp's avatar
   
knopp committed
342
  
343
344
345
  LOG_E(MAC,"error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n",
	nodeP, (ul_flag == 0)? "DL" : "UL");
  dump_ue_list(listP, ul_flag);
knopp's avatar
   
knopp committed
346
347


knopp's avatar
   
knopp committed
348
349
  return(-1);
}
350

351
void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag) {
352

knopp's avatar
   
knopp committed
353
354
  int prev_i,prev_j,next_i,next_j;

355
356
  LOG_T(MAC,"Swapping UE %d,%d\n",nodeiP,nodejP);
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
357

358
359
  prev_i = prev(listP,nodeiP,ul_flag);
  prev_j = prev(listP,nodejP,ul_flag);
knopp's avatar
   
knopp committed
360
361
  if ((prev_i<0) || (prev_j<0))
    mac_xface->macphy_exit("");    
knopp's avatar
   
knopp committed
362

363
364
365
366
367
368
  if (ul_flag == 0){
    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
369
  }
knopp's avatar
   
knopp committed
370

371
372
373
374
375
  LOG_T(MAC,"[%s] next_i %d, next_i, next_j %d, head %d \n",
	(ul_flag == 0)? "DL" : "UL",
	next_i,next_j,listP->head);

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

377
378
379
380
381
382
383
384
385
    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");
      
      listP->next[nodeiP] = next_j;
      listP->next[nodejP] = nodeiP;
      if (nodeiP==listP->head)  // case i j n(j)
	listP->head = nodejP;
      else
	listP->next[prev_i] = nodejP;
knopp's avatar
   
knopp committed
386
    }
387
388
389
390
391
392
393
394
    else if (next_j == nodeiP) {    // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
      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;
      if (nodejP==listP->head)  // case j i n(i)
	listP->head = nodeiP;
      else
	listP->next[prev_j] = nodeiP;
knopp's avatar
   
knopp committed
395
    }
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
    else {    // case ...  p(i) i n(i) ... p(j) j n(j) ...
      
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = next_j;
      
      
      if (nodeiP==listP->head) {
	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;
      }
    }
  } 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");
      
      listP->next_ul[nodeiP] = next_j;
      listP->next_ul[nodejP] = nodeiP;
      if (nodeiP==listP->head_ul)  // case i j n(j)
	listP->head_ul = nodejP;
      else
	listP->next_ul[prev_i] = nodejP;
    }
    else if (next_j == nodeiP) {    // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
      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;
      if (nodejP==listP->head_ul)  // case j i n(i)
	listP->head_ul = nodeiP;
      else
	listP->next_ul[prev_j] = nodeiP;
    }
    else {    // case ...  p(i) i n(i) ... p(j) j n(j) ...
      
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = next_j;
      
      
      if (nodeiP==listP->head_ul) {
	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;
      }
knopp's avatar
   
knopp committed
458
459
    }
  }
460
461
  LOG_T(MAC,"After swap\n");
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
462
463
464
465
466
467
468
469
470
471
472
}

void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP, sub_frame_t subframeP) {

  int UE_id = find_UE_id(mod_idP, rntiP);
  UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;

  if (UE_id  != UE_INDEX_INVALID ) {
    LOG_D(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d on CC_id %d\n",mod_idP,rntiP,frameP,subframeP, UE_id,cc_idP);
      UE_list->UE_template[cc_idP][UE_id].ul_SR = 1;
      UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE;
473
474
  } else {
    //     AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP);
knopp's avatar
   
knopp committed
475
    //    AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP);
knopp's avatar
   
knopp committed
476
    LOG_D(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d (unknown UEid) \n",mod_idP,rntiP,frameP,subframeP, UE_id);
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
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
  }
}




/*
  #ifdef Rel10
  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,
    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) {

  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++;
  LOG_D(MAC,"add common dci format %d for rnti %d \n",dci_fmt,rnti);
}

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

  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
626
627

  LOG_D(MAC,"add ue specific dci format %d for rnti %d \n",dci_fmt,rnti);
628
629
630
631
632
633
634
}





// This has to be updated to include BSR information
knopp's avatar
   
knopp committed
635
uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id) {
636

knopp's avatar
   
knopp committed
637
  UE_TEMPLATE *UE_template = &eNB_mac_inst[module_idP].UE_list.UE_template[CC_id][UE_id];
638
639
640
641

  //  LOG_D(MAC,"[eNB %d][PUSCH] Frame %d subframeP %d Scheduling UE %d\n",module_idP,rnti,frameP,subframeP,
  //	UE_id);

knopp's avatar
   
knopp committed
642
643
644
645
646
  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) ||
      (UE_template->ul_SR>0)) // uplink scheduling request
647
648
649
650
651
652
653
654
    return(1);
  else
    return(0);
}




knopp's avatar
   
knopp committed
655
uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, uint32_t *rballoc) {
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679

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

  for (i=0;i<(mac_xface->lte_frame_parms->N_RB_DL-2);i+=2) {
      if (((*rballoc>>i)&3)==0) {
          *rballoc |= (3<<i);
          rballoc_dci |= (1<<((12-i)>>1));
          nb_rb_alloc+=2;
      }
      if (nb_rb_alloc==nb_rb)
        return(rballoc_dci);
  }

  if ((mac_xface->lte_frame_parms->N_RB_DL&1)==1) {
      if ((*rballoc>>(mac_xface->lte_frame_parms->N_RB_DL-1)&1)==0) {
          *rballoc |= (1<<(mac_xface->lte_frame_parms->N_RB_DL-1));
          rballoc_dci |= 1;//(1<<(mac_xface->lte_frame_parms->N_RB_DL>>1));
      }
  }
  return(rballoc_dci);
}

680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
int get_min_rb_unit(module_id_t module_id, uint8_t CC_id){
  
  int min_rb_unit=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
    min_rb_unit=1;
    break;
  case 25: // 5HMz
    min_rb_unit=2;
    break;
  case 50: // 10HMz
    min_rb_unit=3;
    break;
  case 100: // 20HMz
    min_rb_unit=4;
    break;
  default:
    min_rb_unit=2;
    LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n", module_id, CC_id);
    break;
  }
  return min_rb_unit;
}
704
705
706
707
708
709
710

uint32_t allocate_prbs_sub(int nb_rb, uint8_t *rballoc) {

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

711
712
713
  LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n",
      rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,mac_xface->lte_frame_parms->N_RBG);
  while((nb_rb >0) && (check < mac_xface->lte_frame_parms->N_RBG)){
knopp's avatar
   
knopp committed
714
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
715
      if(rballoc[check] == 1){
716
          rballoc_dci |= (1<<((mac_xface->lte_frame_parms->N_RBG-1)-check));
717
718
719
          switch (mac_xface->lte_frame_parms->N_RB_DL) {
          case 6:
            nb_rb--;
knopp's avatar
   
knopp committed
720
	    break;
721
          case 25:
722
            if ((check == mac_xface->lte_frame_parms->N_RBG-1))
723
724
725
726
727
              nb_rb--;
            else
              nb_rb-=2;
            break;
          case 50:
728
            if ((check == mac_xface->lte_frame_parms->N_RBG-1))
729
730
731
732
733
734
735
736
737
              nb_rb-=2;
            else
              nb_rb-=3;
            break;
          case 100:
            nb_rb-=4;
            break;
          }
      }
knopp's avatar
   
knopp committed
738
      //      printf("rb_alloc %x\n",rballoc_dci);
739
740
741
742
743
744
745
746
747
748
      check = check+1;
      //    check1 = check1+2;
  }
  // rballoc_dci = (rballoc_dci)&(0x1fff);
  LOG_T(MAC,"*********RBALLOC : %x\n",rballoc_dci);
  // exit(-1);
  return (rballoc_dci);
}


749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
int get_nb_subband(void){
 
  int nb_sb=0;

  switch (mac_xface->lte_frame_parms->N_RB_DL) {
  case 6:
    nb_sb=0; 
    break;
  case 15:
    nb_sb = 4;  // sb_size =4
  case 25: 
    nb_sb = 7; // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs
    break;
  case 50:    // sb_size =6
    nb_sb = 9;
    break;
  case 75:  // sb_size =8
    nb_sb = 10;
    break;
  case 100: // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs
    nb_sb = 13;
    break;
  default:
    nb_sb=0;
    break;
  }
  return nb_sb;
776
777

}