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