ue_procedures.c 80 KB
Newer Older
1
/*******************************************************************************
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

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


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

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
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
27 28

*******************************************************************************/
29 30

/*! \file ue_procedures.c
31
 * \brief procedures related to UE
32 33 34
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \version 1
35 36
 * \email: navid.nikaein@eurecom.fr
 * @ingroup _mac
37

38
 */
39

40 41 42 43
#ifdef EXMIMO
#include <pthread.h>
#endif

44 45
#include "extern.h"
#include "defs.h"
46
#include "proto.h"
47
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
48
# include "SIMULATION/PHY_EMULATION/impl_defs.h"
49
#else
Cedric Roux's avatar
Cedric Roux committed
50 51
# include "SCHED/defs.h"
# include "PHY/impl_defs_top.h"
52 53 54 55
#endif
#include "PHY_INTERFACE/defs.h"
#include "PHY_INTERFACE/extern.h"
#include "COMMON/mac_rrc_primitives.h"
Cedric Roux's avatar
Cedric Roux committed
56 57

#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
58 59 60
#include "RRC/LITE/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
Cedric Roux's avatar
Cedric Roux committed
61
#include "UTIL/OPT/opt.h"
62 63
#include "OCG.h"
#include "OCG_extern.h"
Cedric Roux's avatar
Cedric Roux committed
64

65
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
66
# include "SIMULATION/simulation_defs.h"
67
#endif
68
#include "pdcp.h"
69

70 71 72 73
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

74 75
#include "assertions.h"

76 77
#include "SIMULATION/TOOLS/defs.h" // for taus

78
#define DEBUG_HEADER_PARSING 1
79
#define ENABLE_MAC_PAYLOAD_DEBUG 1
80 81 82 83 84

/*
#ifndef USER_MODE
#define msg debug_msg
#endif
85
 */
86
mapping BSR_names[] = {
87 88 89 90 91 92
  {"NONE", 0},
  {"SHORT BSR", 1},
  {"TRUNCATED BSR", 2},
  {"LONG BSR", 3},
  {"PADDING BSR", 4},
  {NULL, -1}
93 94 95
};


96 97
void ue_init_mac(module_id_t module_idP)
{
98 99
  int i;
  // default values as deined in 36.331 sec 9.2.2
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
  LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
  //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity;
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1;
  UE_mac_inst[module_idP].PHR_state = MAC_MainConfig__phr_Config_PR_setup;
  UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
  UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
  UE_mac_inst[module_idP].scheduling_info.ttiBundling=0;
  UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db =  get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange);
120 121

  for (i=0; i < MAX_NUM_LCID; i++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
122 123
    LOG_D(MAC,"[UE%d] Applying default logical channel config for LCGID %d\n",module_idP,i);
    UE_mac_inst[module_idP].scheduling_info.Bj[i]=-1;
124 125
    UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1;

126
    if (i < DTCH) { // initilize all control channels lcgid to 0
127
      UE_mac_inst[module_idP].scheduling_info.LCGID[i]=0;
128
    } else { // initialize all the data channels lcgid to 1
129
      UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
130
    }
131 132

    UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=0;
133
  }
134

135
#ifdef CBA
136

137
  for (i=0; i <NUM_MAX_CBA_GROUP; i++) {
138
    UE_mac_inst[module_idP].cba_last_access[i]= round(uniform_rngen(1,30));
139
  }
140 141

#endif
142 143
}

Raymond Knopp's avatar
 
Raymond Knopp committed
144

145
unsigned char *parse_header(unsigned char *mac_header,
146 147 148 149 150 151 152
                            unsigned char *num_ce,
                            unsigned char *num_sdu,
                            unsigned char *rx_ces,
                            unsigned char *rx_lcids,
                            unsigned short *rx_lengths,
                            unsigned short tb_length)
{
153 154 155 156 157 158 159

  unsigned char not_done=1,num_ces=0,num_sdus=0,lcid, num_sdu_cnt;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length,ce_len=0;

  while (not_done==1) {

160 161 162 163 164 165 166 167 168 169 170 171 172
    if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
      //      printf("E=0\n");
      not_done = 0;
    }

    lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;

    if (lcid < UE_CONT_RES) {
      //printf("[MAC][UE] header %x.%x.%x\n",mac_header_ptr[0],mac_header_ptr[1],mac_header_ptr[2]);
      if (not_done==0) {// last MAC SDU, length is implicit
        mac_header_ptr++;
        length = tb_length-(mac_header_ptr-mac_header)-ce_len;

173
        for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++) {
174
          length -= rx_lengths[num_sdu_cnt];
175
        }
176 177 178 179
      } else {
        if (((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {
          length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
          mac_header_ptr += 3;
180
#ifdef DEBUG_HEADER_PARSING
181
          LOG_D(MAC,"[UE] parse long sdu, size %x \n",length);
182
#endif
183

184 185 186 187 188 189
        }  else { //if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;
        }
      }

190
#ifdef DEBUG_HEADER_PARSING
191 192
      LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %d)\n",
            num_sdus,lcid,length,mac_header_ptr-mac_header);
193
#endif
194 195 196 197 198 199 200 201 202 203 204
      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
    } else { // This is a control element subheader
      if (lcid == SHORT_PADDING) {
        mac_header_ptr++;
      } else {
        rx_ces[num_ces] = lcid;
        num_ces++;
        mac_header_ptr ++;

205
        if (lcid==TIMING_ADV_CMD) {
206
          ce_len++;
207
        } else if (lcid==UE_CONT_RES) {
208
          ce_len+=6;
209
        }
210
      }
211

212
#ifdef DEBUG_HEADER_PARSING
213
      LOG_D(MAC,"[UE] ce %d lcid %d (offset now %d)\n",num_ces,lcid,mac_header_ptr-mac_header);
214
#endif
215
    }
216
  }
217

218 219 220 221 222 223
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
}

224 225
uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_id,uint16_t rnti, sub_frame_t subframe)
{
226 227 228

  // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
  //  int MGL=6;// measurement gap length in ms
229 230 231
  int MGRP       = 0; // measurement gap repetition period in ms
  int gapOffset  = -1;
  int T          = 0;
232

233
  DevCheck(module_idP < (int)NB_UE_INST, module_idP, NB_UE_INST, 0);
234

Raymond Knopp's avatar
 
Raymond Knopp committed
235 236 237
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
238
    return 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
239 240
  }

241
  // determin the measurement gap
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
  if (UE_mac_inst[module_idP].measGapConfig !=NULL) {
    if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
      MGRP= 40;
      gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp0;
    } else if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
      MGRP= 80;
      gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp1;
    } else {
      LOG_W(MAC, "Measurement GAP offset is unknown\n");
    }

    T=MGRP/10;
    DevAssert( T != 0 );

    //check the measurement gap and sr prohibit timer
    if ((subframe ==  gapOffset %10) && ((frameP %T) == (floor(gapOffset/10)))
        && (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running ==0)) {
      UE_mac_inst[module_idP].scheduling_info.SR_pending=1;
      return(0);
    }
262
  }
263 264

  if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) &&
265
      (UE_mac_inst[module_idP].scheduling_info.SR_pending==1) &&
266
      (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER <
267 268
       (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)))
     ) {
269
    LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
270
          module_idP,rnti,frameP,subframe,
271 272 273 274
          UE_mac_inst[module_idP].scheduling_info.SR_COUNTER,
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)),
          UE_mac_inst[module_idP].scheduling_info.SR_pending);

275
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++;
276

277 278 279 280
    // start the sr-prohibittimer : rel 9 and above
    if (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer > 0) { // timer configured
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer--;
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=1;
281
    } else {
282
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
283
    }
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

    LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
          module_idP,rnti,frameP,subframe,
          UE_mac_inst[module_idP].scheduling_info.SR_COUNTER,
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)),
          UE_mac_inst[module_idP].scheduling_info.SR_pending);

    //UE_mac_inst[module_idP].ul_active =1;
    return(1); //instruct phy to signal SR
  } else {
    // notify RRC to relase PUCCH/SRS
    // clear any configured dl/ul
    // initiate RA
    UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
    return(0);
300 301 302
  }
}

303 304 305 306 307 308 309 310 311 312 313
//------------------------------------------------------------------------------
void
ue_send_sdu(
  module_id_t module_idP,
  uint8_t CC_id,
  frame_t frameP,
  uint8_t* sdu,
  uint16_t sdu_len,
  uint8_t eNB_index
)
//------------------------------------------------------------------------------
314
{
315 316 317 318 319 320

  unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
  unsigned char rx_lcids[NB_RB_MAX];
  unsigned short rx_lengths[NB_RB_MAX];
  unsigned char *tx_sdu;

321
  start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
322
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
323 324

  LOG_T(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]);
325
#if defined(USER_MODE) && defined(OAI_EMU)
326

327
  if (oai_emulation.info.opt_enabled) {
328
    trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
329
              UE_mac_inst[module_idP].subframe, 0, 0);
330 331
  }

332
#endif
333 334 335
  payload_ptr = parse_header(sdu,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_len);

#ifdef DEBUG_HEADER_PARSING
336
  LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP,
337
        frameP,eNB_index,num_ce,num_sdu);
338 339 340 341
#endif

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
  LOG_T(MAC,"[eNB %d] First 32 bytes of DLSCH : \n");
342

343
  for (i=0; i<32; i++) {
344
    LOG_T(MAC,"%x.",sdu[i]);
345
  }
346

347
  LOG_T(MAC,"\n");
348 349
#endif

350 351 352 353
  for (i=0; i<num_ce; i++) {
    //    printf("ce %d : %d\n",i,rx_ces[i]);
    switch (rx_ces[i]) {
    case UE_CONT_RES:
354

355
      LOG_I(MAC,"[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n",
356
            module_idP,frameP,payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4],payload_ptr[5]);
357 358 359 360 361 362 363 364 365 366 367 368 369

      if (UE_mac_inst[module_idP].RA_active == 1) {
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n");
        UE_mac_inst[module_idP].RA_active=0;
        // check if RA procedure has finished completely (no contention)
        tx_sdu = &UE_mac_inst[module_idP].CCCH_pdu.payload[3];

        //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits)
        // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or SCH_SUBHEADER_SHORT)
        for (i=0; i<6; i++)
          if (tx_sdu[i] != payload_ptr[i]) {
            LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP);
            mac_xface->ra_failed(module_idP,CC_id,eNB_index);
370
            UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
371
            VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
372 373 374 375 376 377 378 379 380 381 382 383
            return;
          }

        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n");
        UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
        mac_xface->ra_succeeded(module_idP,CC_id,eNB_index);
      }

      payload_ptr+=6;
      break;

    case TIMING_ADV_CMD:
384
#ifdef DEBUG_HEADER_PARSING
385
      LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]);
386
#endif
387 388 389 390 391
      mac_xface->process_timing_advance(module_idP,CC_id,payload_ptr[0]);
      payload_ptr++;
      break;

    case DRX_CMD:
392
#ifdef DEBUG_HEADER_PARSING
393
      LOG_D(MAC,"[UE] CE %d : UE DRX :",i);
394
#endif
395 396 397
      payload_ptr++;
      break;
    }
398
  }
399 400

  for (i=0; i<num_sdu; i++) {
401
#ifdef DEBUG_HEADER_PARSING
402
    LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
403
#endif
404

405 406
    if (rx_lcids[i] == CCCH) {

407 408 409 410 411 412
      LOG_D(MAC,"[UE %d] rnti %x Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n",
            module_idP,
            UE_mac_inst[module_idP].crnti,
            frameP,
            eNB_index,
            rx_lengths[i]);
413 414

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
415
      int j;
416

417
      for (j=0; j<rx_lengths[i]; j++) {
418
        LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]);
419
      }
420 421 422 423 424

      LOG_T(MAC,"\n");
#endif
      mac_rrc_data_ind(module_idP,
                       frameP,
425
                       UE_mac_inst[module_idP].crnti,
426
                       CCCH,
427 428 429 430 431
                       (uint8_t*)payload_ptr,
                       rx_lengths[i],
                       ENB_FLAG_NO,
                       eNB_index,
                       0);
432 433 434

    } else if (rx_lcids[i] == DCCH) {
      LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i],eNB_index,rx_lengths[i]);
435 436
      mac_rlc_data_ind(module_idP,
                       UE_mac_inst[module_idP].crnti,
437 438 439 440 441 442 443 444 445 446
                       frameP,
                       ENB_FLAG_NO,
                       MBMS_FLAG_NO,
                       DCCH,
                       (char *)payload_ptr,
                       rx_lengths[i],
                       1,
                       NULL);
    } else if (rx_lcids[i] == DCCH1) {
      LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i], eNB_index,rx_lengths[i]);
447 448
      mac_rlc_data_ind(module_idP,
                       UE_mac_inst[module_idP].crnti,
449 450 451 452 453 454 455 456 457 458
                       frameP,
                       ENB_FLAG_NO,
                       MBMS_FLAG_NO,
                       DCCH1,
                       (char *)payload_ptr,
                       rx_lengths[i],
                       1,
                       NULL);
    } else if (rx_lcids[i] == DTCH) {
      LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", module_idP, frameP,rx_lcids[i], eNB_index,rx_lengths[i]);
459 460

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
461 462
      int j;

463
      for (j=0; j<rx_lengths[i]; j++) {
464
        LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]);
465
      }
466 467

      LOG_T(MAC,"\n");
468 469
#endif

470 471
      mac_rlc_data_ind(module_idP,
                       UE_mac_inst[module_idP].crnti,
472 473 474 475 476 477 478 479 480 481 482
                       frameP,
                       ENB_FLAG_NO,
                       MBMS_FLAG_NO,
                       DTCH,
                       (char *)payload_ptr,
                       rx_lengths[i],
                       1,
                       NULL);
    }

    payload_ptr+= rx_lengths[i];
483
  }
484

485
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
486
  stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
487 488
}

489 490
void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len)
{
491

492
  start_meas(&UE_mac_inst[module_idP].rx_si);
493
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);
494

495
  LOG_D(MAC,"[UE %d] Frame %d Sending SI to RRC (LCID Id %d,len %d)\n",module_idP,frameP,BCCH,len);
496

497
  mac_rrc_data_ind(module_idP,
498
                   frameP,
499
                   SI_RNTI,
500 501 502
                   BCCH,
                   (uint8_t *)pdu,
                   len,
503
                   ENB_FLAG_NO,
504 505
                   eNB_index,
                   0);
506
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
507
  stop_meas(&UE_mac_inst[module_idP].rx_si);
508 509 510 511
}

#ifdef Rel10
unsigned char *parse_mch_header(unsigned char *mac_header,
512 513 514 515 516
                                unsigned char *num_sdu,
                                unsigned char *rx_lcids,
                                unsigned short *rx_lengths,
                                unsigned short tb_length)
{
517 518 519
  unsigned char not_done=1, num_sdus=0, lcid, i;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length;
520

521
  while (not_done == 1) {
522 523 524 525 526 527 528 529 530 531 532
    if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
      not_done = 0;
    }

    lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;

    if (lcid < SHORT_PADDING) {// subheader for MSI, MCCH or MTCH
      if (not_done == 0) { // last MAC SDU, length is implicit
        mac_header_ptr++;
        length = tb_length- (mac_header_ptr - mac_header);

533
        for (i=0; i<num_sdus; i++) {
534
          length -= rx_lengths[i];
535
        }
536 537 538 539 540 541 542 543 544
      } else { // not the last MAC SDU
        if ( ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {// subheader has length of 3octets
          //    length = ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L;
          length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
          mac_header_ptr += 3;
        } else { // subheader has length of 2octets
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;
        }
545
      }
546 547 548 549 550 551 552 553

      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
    } else { // subheader for padding
      //     if (lcid == SHORT_PADDING)
      mac_header_ptr++;
    }
554
  }
555

556 557 558 559 560
  *num_sdu = num_sdus;
  return(mac_header_ptr);
}

// this function is for sending mch_sdu from phy to mac
561 562
void ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, uint8_t *sdu, uint16_t sdu_len, uint8_t eNB_index, uint8_t sync_area)
{
563 564

  unsigned char num_sdu, i, *payload_ptr;
565
  unsigned char rx_lcids[NB_RB_MAX];
566 567
  unsigned short rx_lengths[NB_RB_MAX];

568
  start_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
569
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN);
570

571
  LOG_D(MAC,"[UE %d] Frame %d : process the mch PDU for sync area %d \n",module_idP,frameP, sync_area);
572 573
  LOG_D(MAC,"[UE %d] sdu: %x.%x\n", module_idP,sdu[0], sdu[1]);
  LOG_D(MAC,"[UE %d] parse_mch_header, demultiplex\n",module_idP);
574 575

  payload_ptr = parse_mch_header(sdu, &num_sdu, rx_lcids, rx_lengths, sdu_len);
576
  LOG_D(MAC,"[UE %d] parse_mch_header, found %d sdus\n",module_idP,num_sdu);
577 578

  for (i=0; i<num_sdu; i++) {
579 580 581 582 583 584 585
    if (rx_lcids[i] == MCH_SCHDL_INFO) {
      if (UE_mac_inst[module_idP].mcch_status==1) {
        LOG_I(MAC,"[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]);
        // ??store necessary scheduling info to ue_mac_inst in order to
        // calculate exact position of interested service (for the complex case has >1 mtch)
        // set msi_status to 1
        UE_mac_inst[module_idP].msi_status = 1;
586
      }
587 588 589 590
    } else if (rx_lcids[i] == MCCH_LCHANID) {
      LOG_I(MAC,"[UE %d] Frame %d : SDU %d MCH->MCCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, i, sync_area, eNB_index, rx_lengths[i]);
      mac_rrc_data_ind(module_idP,
                       frameP,
591
                       M_RNTI,
592 593 594 595 596 597 598 599
                       MCCH,
                       payload_ptr, rx_lengths[i], 0, eNB_index, sync_area);
    } else if (rx_lcids[i] == MTCH) {
      if (UE_mac_inst[module_idP].msi_status==1) {
        LOG_I(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]);

        mac_rlc_data_ind(
          module_idP,
600
          UE_mac_inst[module_idP].crnti,
601 602 603 604 605 606 607 608
          frameP,
          ENB_FLAG_NO,
          MBMS_FLAG_YES,
          MTCH, /*+ (maxDRB + 3),*/
          (char *)payload_ptr,
          rx_lengths[i],
          1,
          NULL);
609 610

      }
611 612 613 614 615 616 617 618 619
    } else {
      LOG_W(MAC,"[UE %d] Frame %d : unknown sdu %d rx_lcids[%d]=%d mcch status %d eNB %d \n",
            module_idP,
            frameP,
            rx_lengths[i],
            i,
            rx_lcids[i],
            UE_mac_inst[module_idP].mcch_status, eNB_index);
    }
620

621
    payload_ptr += rx_lengths[i];
622 623
  }

624
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT);
625
  stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
626 627
}

628 629
int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index)
{
630
  // currently there is one-to-one mapping between sf allocation pattern and sync area
631 632
  if (mbsfn_sync_area >= MAX_MBSFN_AREA) {
    LOG_W( MAC, "[UE %"PRIu8"] MBSFN synchronization area %"PRIu8" out of range for eNB %"PRIu8"\n", module_idP, mbsfn_sync_area, eNB_index );
633
    return -1;
634
  } else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) {
635
    return mbsfn_sync_area;
636
  }
637
  else {
638
    LOG_W( MAC, "[UE %"PRIu8"] MBSFN Subframe Config pattern %"PRIu8" not found \n", module_idP, mbsfn_sync_area );
639
    return -1;
640 641
  }
}
642

643 644
int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active)
{
645

winckel's avatar
winckel committed
646
  int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1;
647
  int mcch_flag=0, mtch_flag=0, msi_flag=0;
648 649
  int mbsfn_period = 0;// 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
  int mcch_period = 0;// 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
winckel's avatar
winckel committed
650
  int mch_scheduling_period = -1;
651 652 653

  start_meas(&UE_mac_inst[module_idP].ue_query_mch);

654
  if (UE_mac_inst[module_idP].pmch_Config[0]) {
655
    mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9);
656
  }
657

658
  for (i=0;
659 660 661
       i< UE_mac_inst[module_idP].num_active_mbsfn_area;
       i++ ) {
    // assume, that there is always a mapping
662
    if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1) {
663
      return -1; // continue;
664
    }
665 666 667 668 669 670

    ii=0;
    msi_pos=0;
    mbsfn_period = 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
    mcch_period = 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);

671 672
    LOG_D(MAC,
          "[UE %d] Frame %d subframe %d: Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d,mac sched period (%d,%d))\n",
673
          module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area,
674 675 676
          j,UE_mac_inst[module_idP].num_sf_allocation_pattern,mbsfn_period,mcch_period,
          mch_scheduling_period,UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset);

677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
    // get the real MCS value
    switch (UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) {
    case 0:
      mcch_mcs = 2;
      break;

    case 1:
      mcch_mcs = 7;
      break;

    case 2:
      mcch_mcs = 13;
      break;

    case 3:
      mcch_mcs = 19;
      break;
    }

    if (frameP % mbsfn_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP
      if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format

        if (UE_mac_inst[module_idP].pmch_Config[0]) {
          //  Find the first subframe in this MCH to transmit MSI
          if (frameP % mch_scheduling_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) {
            while (ii == 0) {
              ii = UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos);
              msi_pos++;
            }
          }
        }

        // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
        switch (subframe) {
        case 1:
          if (mac_xface->lte_frame_parms->frame_type == FDD) {
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) {
714
              if (msi_pos == 1) {
715
                msi_flag = 1;
716
              }
717 718

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
719
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) ) {
720
                mcch_flag = 1;
721
              }
722 723 724 725 726 727 728 729 730 731

              mtch_flag = 1;
            }
          }

          break;

        case 2:
          if (mac_xface->lte_frame_parms->frame_type == FDD) {
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) {
732
              if (msi_pos == 2) {
733
                msi_flag = 1;
734
              }
735 736

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
737
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) ) {
738
                mcch_flag = 1;
739
              }
740 741 742 743

              mtch_flag = 1;
            }
          }
744

745 746 747 748 749
          break;

        case 3:
          if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) {
750
              if (msi_pos == 1) {
751
                msi_flag = 1;
752
              }
753 754

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
755
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) ) {
756
                mcch_flag = 1;
757
              }
758 759 760 761 762

              mtch_flag = 1;
            }
          } else { // FDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) {
763
              if (msi_pos == 3) {
764
                msi_flag = 1;
765
              }
766 767

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
768
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) ) {
769
                mcch_flag = 1;
770
              }
771 772 773 774 775 776 777 778 779 780

              mtch_flag = 1;
            }
          }

          break;

        case 4:
          if (mac_xface->lte_frame_parms->frame_type == TDD) {
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) {
781
              if (msi_pos == 2) {
782
                msi_flag = 1;
783
              }
784 785

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
786
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) ) {
787
                mcch_flag = 1;
788
              }
789 790 791 792 793 794 795 796 797 798

              mtch_flag = 1;
            }
          }

          break;

        case 6:
          if (mac_xface->lte_frame_parms->frame_type == FDD) {
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) {
799
              if (msi_pos == 4) {
800
                msi_flag = 1;
801
              }
802 803

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
804
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) ) {
805
                mcch_flag = 1;
806
              }
807 808 809

              mtch_flag = 1;
            }
810
          }
811 812 813 814 815 816

          break;

        case 7:
          if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) {
817
              if (msi_pos == 3) {
818
                msi_flag = 1;
819
              }
820 821

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
822
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) ) {
823
                mcch_flag = 1;
824
              }
825 826 827 828 829

              mtch_flag = 1;
            }
          } else { // FDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) {
830
              if (msi_pos == 5) {
831
                msi_flag = 1;
832
              }
833 834

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
835
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) ) {
836
                mcch_flag = 1;
837
              }
838 839 840

              mtch_flag = 1;
            }
841
          }
842 843 844 845 846 847

          break;

        case 8:
          if (mac_xface->lte_frame_parms->frame_type == TDD) { //TDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) {
848
              if (msi_pos == 4) {
849
                msi_flag = 1;
850
              }
851 852

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
853
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) ) {
854
                mcch_flag = 1;
855
              }
856 857 858 859 860

              mtch_flag = 1;
            }
          } else { // FDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) {
861
              if (msi_pos == 6) {
862
                msi_flag = 1;
863
              }
864 865

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
866
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) ) {
867
                mcch_flag = 1;
868
              }
869 870 871 872 873 874 875 876 877 878

              mtch_flag = 1;
            }
          }

          break;

        case 9:
          if (mac_xface->lte_frame_parms->frame_type == TDD) {
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) {
879
              if (msi_pos == 5) {
880
                msi_flag = 1;
881
              }
882 883

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
884
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) ) {
885
                mcch_flag = 1;
886
              }
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903

              mtch_flag = 1;
            }
          }

          break;
        }// end switch

        // sf allocation is non-overlapping
        if ((msi_flag==1) || (mcch_flag==1) || (mtch_flag==1)) {
          LOG_D(MAC,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n",
                module_idP, frameP, subframe,i,j,msi_flag,mcch_flag,mtch_flag);

          *sync_area=i;
          break;
        }
      } else { // four-frameP format
904
      }
905
    }
906
  } // end of for
907

908
  stop_meas(&UE_mac_inst[module_idP].ue_query_mch);
909

910
  if ( (mcch_flag==1)) { // || (msi_flag==1))
911
    *mcch_active=1;
912
  }
913

914 915
  if ( (mcch_flag==1) || ((msi_flag==1) && (UE_mac_inst[module_idP].mcch_status==1)) ) {
    return mcch_mcs;
916
  } else if ((mtch_flag==1) && (UE_mac_inst[module_idP].msi_status==1)) {
917
    return UE_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9;
918
  } else {
919
    return -1;
920
  }
921 922 923 924
}

#endif

925
unsigned char generate_ulsch_header(uint8_t *mac_header,
926 927 928 929 930 931 932 933 934 935 936
                                    uint8_t num_sdus,
                                    uint8_t short_padding,
                                    uint16_t *sdu_lengths,
                                    uint8_t *sdu_lcids,
                                    POWER_HEADROOM_CMD *power_headroom,
                                    uint16_t *crnti,
                                    BSR_SHORT *truncated_bsr,
                                    BSR_SHORT *short_bsr,
                                    BSR_LONG *long_bsr,
                                    unsigned short post_padding)
{
937 938 939 940 941 942 943

  SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header;
  unsigned char first_element=0,last_size=0,i;
  unsigned char mac_header_control_elements[16],*ce_ptr;

  LOG_D(MAC,"[UE] Generate ULSCH : num_sdus %d\n",num_sdus);
#ifdef DEBUG_HEADER_PARSING
944

945
  for (i=0; i<num_sdus; i++) {
946
    LOG_T(MAC,"[UE] sdu %d : lcid %d length %d",i,sdu_lcids[i],sdu_lengths[i]);
947
  }
948

949 950 951 952 953
  LOG_T(MAC,"\n");
#endif
  ce_ptr = &mac_header_control_elements[0];

  if ((short_padding == 1) || (short_padding == 2)) {
954 955 956 957 958
    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element=1;
    last_size=1;
959
  }
960

961
  if (short_padding == 2) {
962 963 964 965 966 967
    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;
968 969 970
  }

  if (power_headroom) {
971 972 973 974 975 976 977 978 979 980 981 982 983 984
    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
    } else {
      first_element=1;
    }

    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = POWER_HEADROOM;
    last_size=1;
    *((POWER_HEADROOM_CMD *)ce_ptr)=(*power_headroom);
    ce_ptr+=sizeof(POWER_HEADROOM_CMD);
    LOG_D(MAC, "phr header size %d\n",sizeof(POWER_HEADROOM_CMD));
985 986 987 988
  }

  if (crnti) {
#ifdef DEBUG_HEADER_PARSING
989
    LOG_D(MAC,"[UE] CRNTI : %x (first_element %d)\n",*crnti,first_element);
990
#endif
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005

    if (first_element>0) {
      mac_header_ptr->E = 1;
      mac_header_ptr++;
    } else {
      first_element=1;
    }

    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = CRNTI;
    last_size=1;
    *((uint16_t *)ce_ptr)=(*crnti);
    ce_ptr+=sizeof(uint16_t);
    //    printf("offset %d\n",ce_ptr-mac_header_control_elements);
1006 1007 1008
  }

  if (truncated_bsr) {
1009 1010 1011
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
1012
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
1013 1014 1015 1016 1017 1018 1019 1020 1021
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
       */
      mac_header_ptr++;
    } else {
      first_element=1;
    }

1022
#ifdef DEBUG_HEADER_PARSING
1023
    LOG_D(MAC,"[UE] Scheduler Truncated BSR Header\n");
1024
#endif
1025 1026 1027 1028 1029 1030 1031
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = TRUNCATED_BSR;
    last_size=1;
    *((BSR_TRUNCATED *)ce_ptr)=(*truncated_bsr);
    ce_ptr+=sizeof(BSR_TRUNCATED);
    //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
1032

1033 1034 1035 1036
  } else if (short_bsr) {
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
1037
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
1038 1039 1040 1041 1042 1043 1044 1045 1046
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
       */
      mac_header_ptr++;
    } else {
      first_element=1;
    }

1047
#ifdef DEBUG_HEADER_PARSING
1048
    LOG_D(MAC,"[UE] Scheduler SHORT BSR Header\n");
1049
#endif
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_BSR;
    last_size=1;
    *((BSR_SHORT *)ce_ptr)=(*short_bsr);
    ce_ptr+=sizeof(BSR_SHORT);

    //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
  } else if (long_bsr) {
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
1062
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
1063 1064 1065 1066 1067 1068 1069 1070 1071
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
      ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
       */
      mac_header_ptr++;
    } else {
      first_element=1;
    }

1072
#ifdef DEBUG_HEADER_PARSING
1073
    LOG_D(MAC,"[UE] Scheduler Long BSR Header\n");
1074
#endif
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
    mac_header_ptr->R = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = LONG_BSR;
    last_size=1;

    *(ce_ptr)     = (long_bsr->Buffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4);
    *(ce_ptr + 1) = ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr->Buffer_size2 & 0x3C) >> 2);
    *(ce_ptr + 2) = ((long_bsr->Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F);
    /* Padding */
    *(ce_ptr + 3) = 0;
    ce_ptr += BSR_LONG_SIZE;

    //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
1088
  }
1089

1090 1091
  //  printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

1092
  for (i=0; i<num_sdus; i++) {
1093
#ifdef DEBUG_HEADER_PARSING
1094
    LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]);
1095
#endif
1096 1097 1098

    if ((first_element>0)) {
      mac_header_ptr->E = 1;
1099
#ifdef DEBUG_HEADER_PARSING
1100 1101 1102 1103
      LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
            ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
            ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
            ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
1104
#endif
1105 1106 1107 1108
      mac_header_ptr+=last_size;
      //      printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
    } else {
      first_element=1;
1109

1110 1111 1112 1113 1114 1115 1116 1117 1118
    }

    if (sdu_lengths[i] < 128) {
      ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0; // 3
      ((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;
1119
#ifdef DEBUG_HEADER_PARSING
1120 1121 1122 1123 1124 1125 1126 1127
      LOG_D(MAC,"[UE] short sdu\n");
      LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n",
            ((uint16_t*)mac_header_ptr)[0],
            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R,
            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E,
            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID,
            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F,
            ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L);
1128
#endif
1129 1130 1131 1132 1133 1134 1135 1136 1137
    } else {
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB    = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB    = (unsigned short) sdu_lengths[i]&0xff;
      ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding  = 0x00;
      last_size=3;
1138
#ifdef DEBUG_HEADER_PARSING
1139
      LOG_D(MAC,"[UE] long sdu\n");
1140
#endif
1141
    }
1142
  }
1143

1144
  if (post_padding>0) {// we have lots of padding at the end of the packet
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
    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++;
    //mac_header_ptr=last_size; // FIXME: should be ++
1156
  }
1157

1158
  if ((ce_ptr-mac_header_control_elements) > 0) {
1159 1160
    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);
1161
  }
1162

1163 1164
#ifdef DEBUG_HEADER_PARSING
  LOG_T(MAC," [UE %d] header : ", crnti);
1165

1166
  for (i=0; i<((unsigned char*)mac_header_ptr - mac_header); i++) {
1167
    LOG_T(MAC,"%2x.",mac_header[i]);
1168
  }
1169

1170 1171 1172 1173 1174 1175
  LOG_T(MAC,"\n");
#endif
  return((unsigned char*)mac_header_ptr - mac_header);

}

1176 1177
void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen, uint8_t *access_mode)
{
1178 1179

  mac_rlc_status_resp_t rlc_status;
1180 1181
  uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0;
  uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0;
1182
  uint8_t bsr_header_len=0, bsr_ce_len=0, bsr_len=0;
1183 1184 1185 1186 1187 1188
  uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
  uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uint8_t sdu_lcids[8]    = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uint8_t payload_offset=0,num_sdus=0;
  uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
  uint16_t sdu_length_total=0;
1189 1190 1191 1192 1193 1194 1195
  BSR_SHORT bsr_short;
  BSR_LONG bsr_long;
  BSR_SHORT *bsr_s=&bsr_short;
  BSR_LONG  *bsr_l=&bsr_long;
  POWER_HEADROOM_CMD phr;
  POWER_HEADROOM_CMD *phr_p=&phr;
  unsigned short short_padding=0, post_padding=0;
Cedric Roux's avatar
Cedric Roux committed
1196
  int lcgid;
1197 1198 1199
  int j; // used for padding
  // Compute header length

Raymond Knopp's avatar
 
Raymond Knopp committed
1200 1201 1202 1203 1204 1205
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
    return;
  }

1206
  start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
1207
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_IN);
1208

Cedric Roux's avatar
Cedric Roux committed
1209
#ifdef CBA
1210 1211 1212

  if (*access_mode==CBA_ACCESS) {
    LOG_D(MAC,"[UE %d] frameP %d subframe %d try CBA transmission\n",
1213
          module_idP, frameP, subframe);
1214 1215 1216 1217

    //if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DTCH] == LCID_EMPTY)
    if (cba_access(module_idP,frameP,subframe,eNB_index,buflen)==0) {
      *access_mode=POSTPONED_ACCESS;
1218
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
1219 1220 1221 1222
      return;
    }

    LOG_I(MAC,"[UE %d] frameP %d subframe %d CBA transmission oppurtunity, tbs %d\n",
1223
          module_idP, frameP, subframe,buflen);
1224
  }
1225

1226 1227 1228 1229 1230 1231 1232
#endif
  dcch_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
  dcch1_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
  // hypo length,in case of long header skip the padding byte
  dtch_header_len=(buflen > 128 ) ? 3 : 2 ; //sizeof(SCH_SUBHEADER_LONG)-1 : sizeof(SCH_SUBHEADER_SHORT);
  bsr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
  phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
1233
  phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0;
1234 1235 1236 1237

  if (phr_ce_len > 0) {
    phr_len = phr_ce_len + phr_header_len;
    LOG_D(MAC,"[UE %d] header size info: PHR len %d (ce%d,hdr%d) buff_len %d\n",
1238
          module_idP, phr_len, phr_ce_len, phr_header_len, buflen);
1239
  } else {
1240
    phr_len=0;
1241
  }
1242 1243

  bsr_ce_len = get_bsr_len (module_idP, buflen-phr_len);
1244 1245 1246 1247

  if (bsr_ce_len > 0 ) {
    bsr_len = bsr_ce_len + bsr_header_len;
    LOG_D(MAC,"[UE %d] header size info: dcch %d, dcch1 %d, dtch %d, bsr (ce%d,hdr%d) buff_len %d\n",
1248
          module_idP, dcch_header_len,dcch1_header_len,dtch_header_len, bsr_ce_len, bsr_header_len, buflen);
1249 1250 1251 1252 1253 1254
  } else {
    bsr_len=0;
    //LOG_D(MAC,"[UE %d] Empty buffers, send a long BSR to reset the bsr at eNB \n ",Mod_id);
    //    bsr_ce_len = sizeof(BSR_LONG);
    //bsr_len = bsr_ce_len + bsr_header_len;
  }
1255 1256

  // check for UL bandwidth requests and add SR control element
1257 1258

  // check for UL bandwidth requests and add SR control element
1259 1260 1261

  // Check for DCCH first
  sdu_lengths[0]=0;
1262 1263 1264

  if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH] == LCID_NOT_EMPTY) {

1265
    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
1266 1267 1268
                                    DCCH,
                                    (buflen-dcch_header_len-bsr_len-phr_len));
    LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to "
Cedric Roux's avatar
Cedric Roux committed
1269
          "send (Transport Block size %d, mac header len %d)\n",
1270
          module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch_header_len);
1271

1272
    sdu_lengths[0] += mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
1273 1274
                                       DCCH,
                                       (char *)&ulsch_buff[sdu_lengths[0]]);
1275

1276 1277 1278 1279 1280 1281 1282 1283 1284
    sdu_length_total += sdu_lengths[0];
    sdu_lcids[0] = DCCH;
    LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
    num_sdus = 1;
    update_bsr(module_idP, frameP, DCCH, UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]);
    //header_len +=2;
  } else {
    dcch_header_len=0;
    num_sdus = 0;
1285 1286
  }

1287 1288 1289 1290
  // if the RLC AM is used, then RLC will only provide 2 bytes for ACK
  // in this case, we sould add bsr


1291
  // DCCH1
1292
  if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH1] == LCID_NOT_EMPTY) {
1293

1294
    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
1295 1296
                                    DCCH1,
                                    (buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-sdu_length_total));
1297

1298
    LOG_D(MAC,"[UE %d] Frame %d : UL-DCCH1 -> ULSCH, RRC message has %d bytes to"
Cedric Roux's avatar
Cedric Roux committed
1299
          " send (Transport Block size %d, mac header len %d)\n",
1300
          module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dcch1_header_len);
1301

1302
    sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
                            DCCH1,
                            (char *)&ulsch_buff[sdu_lengths[0]]);
    sdu_length_total += sdu_lengths[num_sdus];
    sdu_lcids[num_sdus] = DCCH1;
    LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH1\n",module_idP,sdu_lengths[num_sdus]);
    num_sdus++;
    //update_bsr(module_idP, frameP, DCCH1);
    //dcch_header_len +=2; // include dcch1
  } else {
    dcch1_header_len =0;
1313 1314
  }

1315
  if ((UE_mac_inst[module_idP].scheduling_info.LCID_status[DTCH] == LCID_NOT_EMPTY) &&
1316 1317 1318 1319 1320 1321 1322 1323
      ((bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len+sdu_length_total) <= buflen)) {

    // optimize the dtch header lenght
    //if ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] > 128) &&
    /*   if (((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] >= 128) &&
    ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH]+bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len) > buflen)&&
    buflen >=128 ))
    dtch_header_len = 3;//sizeof(SCH_SUBHEADER_LONG);
1324
    else
1325 1326
    dtch_header_len = 2;//sizeof(SCH_SUBHEADER_SHORT);
     */
1327
    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
1328 1329
                                    DTCH,
                                    buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total);
1330

1331
    LOG_D(MAC,"[UE %d] Frame %d : UL-DTCH -> ULSCH, %d bytes to send (Transport Block size %d, mac header len %d, BSR byte[DTCH] %d)\n",
1332
          module_idP,frameP, rlc_status.bytes_in_buffer,buflen,dtch_header_len,
1333 1334
          UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH]);

1335
    sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,UE_mac_inst[module_idP].crnti,frameP, ENB_FLAG_NO, MBMS_FLAG_NO, // eNB_index
1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
                            DTCH,
                            (char *)&ulsch_buff[sdu_length_total]);

    //adjust dtch header
    dtch_header_len = (sdu_lengths[num_sdus] >= 128) ? 3 : 2;
    LOG_D(MAC,"[UE %d] TX Got %d bytes for DTCH\n",module_idP,sdu_lengths[num_sdus]);
    sdu_lcids[num_sdus] = DTCH;
    sdu_length_total += sdu_lengths[num_sdus];
    num_sdus++;
    UE_mac_inst[module_idP].ul_active = update_bsr(module_idP, frameP, DTCH, UE_mac_inst[module_idP].scheduling_info.LCGID[DTCH]);
  } else { // no rlc pdu : generate the dummy header
    dtch_header_len = 0;
1348
  }
1349 1350

  lcgid= get_bsr_lcgid(module_idP);
1351 1352

  if (lcgid < 0 ) {
1353 1354
    bsr_s = NULL;
    bsr_l = NULL ;
1355
  } else if ((lcgid ==MAX_NUM_LCGID) && (bsr_ce_len == sizeof(BSR_LONG))) {
1356 1357 1358 1359 1360 1361
    bsr_s = NULL;
    bsr_l->Buffer_size0 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0];
    bsr_l->Buffer_size1 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1];
    bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2];
    bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3];
    LOG_D(MAC, "[UE %d] Frame %d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,
1362 1363 1364 1365
          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0],
          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1],
          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2],
          UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]);
1366
  } else if (bsr_ce_len == sizeof(BSR_SHORT)) {
1367 1368 1369 1370
    bsr_l = NULL;
    bsr_s->LCGID = lcgid;
    bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcgid];
    LOG_D(MAC,"[UE %d] Frame %d report SHORT BSR with level %d for LCGID %d\n",
1371
          module_idP, frameP, UE_mac_inst[module_idP].scheduling_info.BSR[lcgid],lcgid);
1372
  } else {
1373 1374
    bsr_s = NULL;
    bsr_l = NULL;
1375 1376
  }

1377
  // build PHR and update the timers
1378
  if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1379 1380 1381 1382 1383
    phr_p->PH = get_phr_mapping(module_idP,CC_id,eNB_index);
    phr_p->R  = 0;
    LOG_D(MAC,"[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n",
          module_idP,frameP, mac_xface->get_PHR(module_idP,CC_id,eNB_index), phr_p->PH,POWER_HEADROOM);
    update_phr(module_idP,CC_id);
1384
  } else {
1385
    phr_p=NULL;
1386
  }
1387

1388
  LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n",  module_idP,frameP,bsr_s, bsr_l, phr_p);
1389

1390
  // adjust the header length
1391 1392
  dcch_header_len_tmp = dcch_header_len;
  dtch_header_len_tmp = dtch_header_len;
1393

1394
  if (dtch_header_len==0) {
1395
    dcch_header_len = (dcch_header_len>0)? 1: dcch_header_len;
1396
  } else {
1397
    dtch_header_len= (dtch_header_len >0)? 1: dtch_header_len;   // for short and long, cut the length+F fields
1398
  }
1399 1400

  if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) <= 2) {
1401 1402 1403 1404 1405 1406 1407 1408 1409
    short_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total;
    post_padding = 0;
  } else {
    if ((buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total) == buflen) {
      *access_mode=CANCELED_ACCESS;
    }

    short_padding = 0;

1410
    if (dtch_header_len==0) {
1411
      dcch_header_len = dcch_header_len_tmp;
1412
    } else {
1413
      dtch_header_len= dtch_header_len_tmp;
1414
    }
1415

1416
    post_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total -1 ;
1417
  }
1418

1419 1420
  // Generate header
  // if (num_sdus>0) {
1421

1422
  payload_offset = generate_ulsch_header(ulsch_buffer,  // mac header
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437
                                         num_sdus,      // num sdus
                                         short_padding,            // short pading
                                         sdu_lengths,  // sdu length
                                         sdu_lcids,    // sdu lcid
                                         phr_p,  // power headroom
                                         NULL,  // crnti
                                         NULL,  // truncated bsr
                                         bsr_s, // short bsr
                                         bsr_l,
                                         post_padding); // long_bsr

  LOG_I(MAC,
        "[UE %d] Generate header :bufflen %d  sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,  dcch_header_len %d, dtch_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n",
        module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, dcch_header_len,  dtch_header_len,
        short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset);
1438 1439
  // cycle through SDUs and place in ulsch_buffer
  memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
1440

1441
  // fill remainder of DLSCH with random data
1442
  for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
1443
    ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff);
1444
  }
1445

1446 1447 1448
#if defined(USER_MODE) && defined(OAI_EMU)

  if (oai_emulation.info.opt_enabled) {
1449
    trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, subframe, 0, 0);
1450
  }
1451

1452
    LOG_D(OPT,"[UE %d][ULSCH] Frame %d trace pdu for rnti %x  with size %d\n",
1453
          module_idP, frameP, UE_mac_inst[module_idP].crnti, buflen);
1454
#endif
1455 1456

  LOG_D(MAC,"[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n",
1457
        module_idP,payload_offset, sdu_length_total);
1458 1459
  UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
  UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
1460
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
1461
  stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
1462 1463
}

1464
//------------------------------------------------------------------------------
1465 1466 1467 1468 1469 1470 1471
// called at each subframe
// Performs :
// 1. Trigger PDCP every 5ms
// 2. Call RRC for link status return to PHY
// 3. Perform SR/BSR procedures for scheduling feedback
// 4. Perform PHR procedures

1472 1473 1474 1475 1476 1477 1478 1479 1480
UE_L2_STATE_t
ue_scheduler(
  const module_id_t    module_idP,
  const frame_t        frameP,
  const sub_frame_t    subframeP,
  const lte_subframe_t directionP,
  const uint8_t        eNB_indexP,
  const int            CC_id)
//------------------------------------------------------------------------------
1481
{
1482 1483 1484

  int lcid; // lcid index
  int TTI= 1;
winckel's avatar
winckel committed
1485 1486
  int bucketsizeduration = -1;
  int bucketsizeduration_max = -1;
1487
  // mac_rlc_status_resp_t rlc_status[MAX_NUM_LCGID]; // 4
1488
  // int8_t lcg_id;
1489
  struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL;
1490
  protocol_ctxt_t   ctxt;
1491
#if defined(ENABLE_ITTI)
1492 1493 1494 1495
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
1496
#endif
1497
  start_meas(&UE_mac_inst[module_idP].ue_scheduler);
1498
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_IN);
1499

1500
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, frameP, subframeP);
1501 1502
#if defined(ENABLE_ITTI)

1503 1504 1505
  do {
    // Checks if a message has been sent to MAC sub-task
    itti_poll_msg (TASK_MAC_UE, &msg_p);
1506

1507 1508 1509
    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);
1510

1511 1512 1513 1514 1515
      switch (ITTI_MSG_ID(msg_p)) {
      case RRC_MAC_CCCH_DATA_REQ:
        LOG_I(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_CCCH_DATA_REQ (msg_p).frame, RRC_MAC_CCCH_DATA_REQ (msg_p).enb_index);
1516

1517 1518
        // TODO process CCCH data req.
        break;
1519 1520


1521 1522 1523
      default:
        LOG_E(MAC, "Received unexpected message %s\n", msg_name);
        break;
1524
      }
1525 1526 1527 1528

      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    }
1529
  } while(msg_p != NULL);
1530

1531 1532
#endif

1533 1534
  //Mac_rlc_xface->frameP=frameP;
  //Rrc_xface->Frame_index=Mac_rlc_xface->frameP;
1535
  //if (subframe%5 == 0)
1536
  //LG#ifdef EXMIMO
1537
  pdcp_run(&ctxt);
1538
  //#endif
1539 1540
  UE_mac_inst[module_idP].frame = frameP;
  UE_mac_inst[module_idP].subframe = subframeP;
1541 1542

#ifdef CELLULAR
1543
  rrc_rx_tx(module_idP, frameP, 0, eNB_indexP);
1544
#else
1545

1546
  switch (rrc_rx_tx(&ctxt,
1547 1548
                    eNB_indexP,
                    CC_id)) {
1549 1550
  case RRC_OK:
    break;
1551

1552 1553
  case RRC_ConnSetup_failed:
    LOG_E(MAC,"RRCConnectionSetup failed, returning to IDLE state\n");
1554
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
1555
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
1556 1557
    return(CONNECTION_LOST);
    break;
1558

1559 1560
  case RRC_PHY_RESYNCH:
    LOG_E(MAC,"RRC Loss of synch, returning PHY_RESYNCH\n");
1561
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
1562
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
1563
    return(PHY_RESYNCH);
1564

1565
  case RRC_Handover_failed:
1566
    LOG_N(MAC,"Handover failure for UE %d eNB_index %d\n",module_idP,eNB_indexP);
1567
    //Invalid...need to add another MAC UE state for re-connection procedure
1568
    mac_xface->phy_config_afterHO_ue(module_idP,0,eNB_indexP,(MobilityControlInfo_t *)NULL,1);
1569 1570
    //return(3);
    break;
1571

1572 1573
  case RRC_HO_STARTED:
    LOG_I(MAC,"RRC handover, Instruct PHY to start the contention-free PRACH and synchronization\n");
1574
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
1575
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
1576
    return(PHY_HO_PRACH);
1577

1578 1579 1580
  default:
    break;
  }
1581

1582
#endif
1583 1584

  // Check Contention resolution timer (put in a function later)
1585
  if (UE_mac_inst[module_idP].RA_contention_resolution_timer_active == 1) {
1586

1587
    if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
1588
      rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon;
1589
    } else {
1590
      LOG_E(MAC,"FATAL: radioResourceConfigCommon is NULL!!!\n");
1591
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
1592 1593 1594 1595
      stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
      mac_xface->macphy_exit("");
      //return(RRC_OK);
    }
1596

1597
    LOG_I(MAC,"Frame %d: Contention resolution timer %d/%d\n",frameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt,
1598 1599
          ((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3));

1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
    UE_mac_inst[module_idP].RA_contention_resolution_cnt++;

    if (UE_mac_inst[module_idP].RA_contention_resolution_cnt ==
        ((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3)) {
      UE_mac_inst[module_idP].RA_active = 0;
      UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
      // Signal PHY to quit RA procedure
      LOG_E(MAC,"Module id %u Contention resolution timer expired, RA failed\n", module_idP);
      mac_xface->ra_failed(module_idP,0,eNB_indexP);
    }
1610 1611 1612 1613 1614 1615 1616
  }


  // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp.  This should implement the procedures
  // outlined in Sections 5.4.4 an 5.4.5 of 36.321
  // Put this in another function

1617
  // Get RLC status info and update Bj for all lcids that are active
1618
  for (lcid=DCCH; lcid <= DTCH; lcid++ ) {
1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
    if ((lcid == 0) ||(UE_mac_inst[module_idP].logicalChannelConfig[lcid])) {
      // meausre the Bj
      if ((directionP == SF_UL)&& (UE_mac_inst[module_idP].scheduling_info.Bj[lcid] >= 0)) {
        if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters) {
          bucketsizeduration = UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->prioritisedBitRate * TTI;
          bucketsizeduration_max = get_ms_bucketsizeduration(UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->bucketSizeDuration);
        } else {
          LOG_E(MAC,"[UE %d] lcid %d, NULL ul_SpecificParameters\n",module_idP,lcid);
          mac_xface->macphy_exit("");
        }

1630
        if ( UE_mac_inst[module_idP].scheduling_info.Bj[lcid] > bucketsizeduration_max ) {
1631
          UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = bucketsizeduration_max;
1632
        } else {
1633
          UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = bucketsizeduration;
1634
        }
1635 1636 1637 1638 1639 1640 1641 1642
      }

      if (update_bsr(module_idP,frameP, lcid, UE_mac_inst[module_idP].scheduling_info.LCGID[lcid])) {
        UE_mac_inst[module_idP].scheduling_info.SR_pending= 1;
        LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d SR for PUSCH is pending for LCGID %d with BSR level %d (%d bytes in RLC)\n",
              module_idP, frameP,subframeP,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
              UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
              UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
1643
      }
1644
    }
1645
  }
1646

1647
  // UE has no valid phy config dedicated ||  no valid/released  SR
1648
  if ((UE_mac_inst[module_idP].physicalConfigDedicated == NULL)) {
1649 1650 1651 1652
    // cancel all pending SRs
    UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
    UE_mac_inst[module_idP].ul_active=0;
    LOG_T(MAC,"[UE %d] Release all SRs \n", module_idP);
1653
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
1654 1655
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
    return(CONNECTION_OK);
1656 1657
  }

1658
  if ((UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig == NULL) ||
1659
      (UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_release)) {
1660

1661
    // initiate RA with CRNTI included in msg3 (no contention) as descibed in 36.321 sec 5.1.5
1662

1663 1664 1665 1666
    // cancel all pending SRs
    UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
    UE_mac_inst[module_idP].ul_active=0;
    LOG_T(MAC,"[UE %d] Release all SRs \n", module_idP);
1667 1668 1669
  }

  // Put this in a function
1670
  // Call PHR procedure as described in Section 5.4.6 in 36.321
1671 1672
  if (UE_mac_inst[module_idP].PHR_state == MAC_MainConfig__phr_Config_PR_setup) { // normal operation

1673 1674 1675 1676 1677 1678
    if (UE_mac_inst[module_idP].PHR_reconfigured == 1) { // upon (re)configuration of the power headroom reporting functionality by upper layers
      UE_mac_inst[module_idP].PHR_reporting_active = 1;
      UE_mac_inst[module_idP].PHR_reconfigured = 0;
    } else {
      //LOG_D(MAC,"PHR normal operation %d active %d \n", UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF, UE_mac_inst[module_idP].PHR_reporting_active);
      if ((UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF <= 0) &&
1679 1680 1681
          ((mac_xface->get_PL(module_idP,0,eNB_indexP) <  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db) ||
           (UE_mac_inst[module_idP].power_backoff_db[eNB_indexP] > UE_mac_inst[module_idP].scheduling_info.PathlossChange_db)))
        // trigger PHR and reset the timer later when the PHR report is sent
1682
      {
1683
        UE_mac_inst[module_idP].PHR_reporting_active = 1;
1684
      } else if (UE_mac_inst[module_idP].PHR_reporting_active ==0 ) {
1685
        UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF--;
1686
      }
1687

1688
      if (UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF <= 0 )
1689
        // trigger PHR and reset the timer later when the PHR report is sent
1690
      {
1691
        UE_mac_inst[module_idP].PHR_reporting_active = 1;
1692
      } else if (UE_mac_inst[module_idP].PHR_reporting_active == 0 ) {
1693
        UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF--;
1694
    }
1695
    }
1696
  } else {    // release / nothing
1697
    UE_mac_inst[module_idP].PHR_reporting_active = 0; // release PHR
1698
  }
1699

1700
  //If the UE has UL resources allocated for new transmission for this TTI here:
1701
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
1702
  stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
1703 1704 1705 1706 1707
  return(CONNECTION_OK);
}

// to be improved
#ifdef CBA
1708
extern int cba_backoff;
1709 1710
double uniform_rngen(int min, int max)
{
1711 1712 1713 1714
  double random = (double)taus()/((double)0xffffffff);
  return (max - min) * random + min;
}

1715 1716
int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen)
{
1717

1718 1719 1720 1721
  mac_rlc_status_resp_t rlc_status;
  int header_offset=4;
  int rv =0;

1722
  /*
1723 1724 1725 1726 1727
  if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64))   ||
      ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]<64))   ||
      ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]<64)) )
      //  && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive
      && (UE_mac_inst[module_idP].cba_last_access[0] <= 0) ) { // backoff
1728
      //  LOG_D(MAC,"[UE %d] Frame %d Subframe %d: the current CBA backoff is %d \n", module_idP, frameP, subframe,
1729 1730
      //  UE_mac_inst[module_idP].cba_last_access[0] );

1731
      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,40));
1732
      LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff  %d UL active state %d \n", module_idP, frameP, subframe,
1733 1734
          UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);

1735
      rv=1;
1736 1737 1738 1739 1740 1741 1742 1743
  } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 ))   ||
      ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]> 0 ))   ||
      ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]> 0 )) )
      // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive
      && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ){

      UE_mac_inst[module_idP].cba_last_access[0]-=1;
      LOG_D(MAC,"[UE %d] Frame %d Subframe %d: CBA backoff is decreased by one to %d UL active state %d \n",
1744
          module_idP, frameP, subframe,
1745 1746
          UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);

1747 1748 1749 1750
  } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] == 0 ))   &&
               ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] == 0 ))   &&
               ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] ==  0 )) )
             && (UE_mac_inst[module_idP].cba_last_access[0]> 0) ){
1751
    UE_mac_inst[module_idP].cba_last_access[0]-=1;
1752
    }*/
1753

1754
  if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]<64) ) {
1755
    return 0;
1756
  }
1757

1758 1759
  if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] <= 0 ) &&
      (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] <= 0 ) &&
1760
      (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] <= 0 ) ) {
1761
    return 0;
1762
  }
1763

1764
  if (cba_backoff == 0 ) { // apply probablisitc method
1765
    UE_mac_inst[module_idP].cba_last_access[0]= uniform_rngen(0,1);
1766 1767

    if (uniform_rngen(0,1) > 0.6 ) {
1768
      LOG_I(MAC,"[UE %d] Frame %d Subframe %d: CBA probability-based backoff (%d), UL active state %d \n", module_idP, frameP, subframe,
1769 1770
            cba_backoff,UE_mac_inst[module_idP].ul_active);

1771 1772
      rv=1;
    }
1773 1774
  } else {

1775 1776
    if (UE_mac_inst[module_idP].cba_last_access[0] <= 0) {
      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,cba_backoff));
1777

1778
      LOG_I(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff  %d/%d UL active state %d \n", module_idP, frameP, subframe,
1779 1780 1781 1782
            UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active);

      rv = 1;
      /*
1783
      rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797
      DTCH,
      0);

      if ((
      //  (rlc_status.pdus_in_buffer > 0 )           &&
      // (UE_mac_inst[module_idP].ul_active == 0)  && // check if the ul is acrtive
      (rlc_status.head_sdu_is_segmented  == 0 )          &&
      ((rlc_status.head_sdu_remaining_size_to_send + header_offset ) <= buflen )
      )){
      rv = 1;

      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,30));
      LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff  %d UL active state %d \n", module_idP, frameP, subframe,
      UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);
1798 1799 1800 1801
      */
    } else {
      UE_mac_inst[module_idP].cba_last_access[0]-=1;
      LOG_D(MAC,"[UE %d] Frame %d Subframe %d: wait for backoff to expire (%d) CBA UL active state %d \n",
1802 1803 1804
            module_idP, frameP, subframe,
            UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);
    }
1805
  }
1806

1807 1808 1809
  return rv;
  /*
    if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64))   ||
1810 1811 1812 1813 1814
    ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]<64))   ||
    ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]<64)) )
  //  && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive
  && (UE_mac_inst[module_idP].cba_last_access[0] <= 0) ) {

1815
      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,cba_backoff));
1816

1817
      LOG_I(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff  %d/%d UL active state %d \n", module_idP, frameP, subframe,
1818 1819 1820 1821
      UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active);

      rv = 1;

1822
    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
1823 1824 1825
            DTCH,
            0);

1826
    if ((
1827 1828 1829 1830 1831
   // (rlc_status.pdus_in_buffer > 0 )           &&
  // (UE_mac_inst[module_idP].ul_active == 0)  && // check if the ul is acrtive
   (rlc_status.head_sdu_is_segmented  == 0 )          &&
   ((rlc_status.head_sdu_remaining_size_to_send + header_offset ) <= buflen )
   )){
1832
      rv = 1;
1833

1834 1835
      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,30));
      LOG_D(MAC,"[UE %d] Frame %d Subframe %d: start a new CBA backoff  %d UL active state %d \n", module_idP, frameP, subframe,
1836 1837
      UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);
    } else
1838
      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,5));
1839

1840 1841

    } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 ))   ||
1842 1843 1844 1845
     ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]> 0 ))   ||
     ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]> 0 )) )
         // && (UE_mac_inst[module_idP].ul_active == 0) // check if the ul is acrtive
         && (UE_mac_inst[module_idP].cba_last_access[0]> 0) )
1846
      {
1847 1848 1849 1850 1851

  UE_mac_inst[module_idP].cba_last_access[0]-=1;
  LOG_D(MAC,"[UE %d] Frame %d Subframe %d: wait for backoff to expire (%d) CBA UL active state %d \n",
        module_idP, frameP, subframe,
        UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);
1852 1853
      }
  }
1854 1855
  */

1856 1857 1858
}
#endif

1859 1860
int get_bsr_lcgid (module_id_t module_idP)
{
1861 1862
  int lcgid, lcgid_tmp=-1;
  int num_active_lcgid = 0;
1863

1864 1865 1866 1867 1868
  for (lcgid = 0 ; lcgid < MAX_NUM_LCGID; lcgid++) {
    if (UE_mac_inst[module_idP].scheduling_info.BSR[lcgid] > 0 ) {
      lcgid_tmp = lcgid;
      num_active_lcgid+=1;
    }
1869
  }
1870

1871
  if (num_active_lcgid == 0) {
1872
    return -1;
1873
  } else if (num_active_lcgid == 1) {
1874
    return lcgid_tmp;
1875
  } else {
1876
    return MAX_NUM_LCGID;
1877
  }
1878 1879
}

1880 1881
uint8_t get_bsr_len (module_id_t module_idP, uint16_t buflen)
{
1882 1883

  int lcgid=0;
1884
  uint8_t bsr_len=0,  num_lcgid=0;
1885 1886
  int pdu = 0;

Raymond Knopp's avatar
 
Raymond Knopp committed
1887

1888
  for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++ ) {
1889
    if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 0 ) {
1890
      pdu += (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] +  bsr_len + 2); //2 = sizeof(SCH_SUBHEADER_SHORT)
1891
    }
1892

1893
    if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 128 ) { // long header size: adjust the header size
1894
      pdu += 1;
1895
    }
1896 1897 1898 1899 1900 1901 1902 1903 1904

    // current phy buff can not transport all sdu for this lcgid -> transmit a bsr for this lcgid

    if ( (pdu > buflen) &&  (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] > 0 ) ) {
      num_lcgid +=1;
      bsr_len = (num_lcgid >= 2 ) ? sizeof(BSR_LONG) :  sizeof(BSR_SHORT) ;
    }

    LOG_D(MAC,"BSR Bytes %d for lcgid %d bsr len %d num lcgid %d\n", UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid], lcgid, bsr_len, num_lcgid);
1905
  }
1906

1907
  if ( bsr_len > 0 )
1908
    LOG_D(MAC,"[UE %d] Prepare a %s (Transport Block Size %d, MAC pdu Size %d) \n",
1909 1910
          module_idP, map_int_to_str(BSR_names, bsr_len), buflen, pdu);

1911 1912 1913 1914
  return bsr_len;
}


1915 1916
boolean_t  update_bsr(module_id_t module_idP, frame_t frameP, uint8_t lcid, uint8_t lcg_id)
{
1917 1918

  mac_rlc_status_resp_t rlc_status;
Lionel Gauthier's avatar
Lionel Gauthier committed
1919
  boolean_t sr_pending = FALSE;
Raymond Knopp's avatar
 
Raymond Knopp committed
1920 1921


1922
  if ((lcg_id < 0) || (lcg_id >= MAX_NUM_LCGID) ) {
1923
    return sr_pending;
1924
  }
1925

1926
  // fixme: need a better way to reset
1927 1928 1929
  if ((lcid == DCCH) || (lcid == DTCH)) {
    UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id]=0;
    UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]=0;
1930
  }
1931

1932
  //  for (lcid =0 ; lcid < MAX_NUM_LCID; lcid++) {
1933
  if (UE_mac_inst[module_idP].scheduling_info.LCGID[lcid] == lcg_id) {
1934
    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
                                    lcid,
                                    0);

    if (rlc_status.bytes_in_buffer > 0 ) {
      sr_pending = TRUE;
      UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY;
      UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] += locate (BSR_TABLE,BSR_TABLE_SIZE, rlc_status.bytes_in_buffer);
      UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id] += rlc_status.bytes_in_buffer;
      // UE_mac_inst[module_idP].scheduling_info.BSR_short_lcid = lcid; // only applicable to short bsr
      LOG_D(MAC,"[UE %d] BSR level %d (LCGID %d, rlc buffer %d byte)\n",
            module_idP, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id],lcg_id,  UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]);
1946
    } else {
1947
      UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY;
1948
    }
1949
  }
1950

1951 1952 1953 1954
  //}
  return sr_pending;
}

1955 1956
uint8_t locate (const uint32_t *table, int size, int value)
{
1957

1958
  uint8_t ju, jm, jl;
1959 1960
  int ascend;

1961 1962 1963
  DevAssert( size > 0 );
  DevAssert( size <= 256 );

1964 1965 1966
  if (value == 0) {
    return 0;  //elseif (value > 150000) return 63;
  }
1967

1968 1969
  jl = 0;        // lower bound
  ju = size - 1; // upper bound
1970 1971 1972
  ascend = (table[ju] >= table[jl]) ? 1 : 0; // determine the order of the the table:  1 if ascending order of table, 0 otherwise

  while (ju-jl > 1) { //If we are not yet done,
1973 1974
    jm = (ju+jl) >> 1; //compute a midpoint,

1975
    if ((value >= table[jm]) == ascend) {
1976
      jl=jm; // replace the lower limit
1977
    } else {
1978
      ju=jm; //replace the upper limit
1979
    }
1980 1981

    LOG_T(MAC,"[UE] searching BSR index %d for (BSR TABLE %d < value %d)\n", jm, table[jm], value);
1982
  }
1983

1984 1985 1986 1987 1988
  if (value == table[jl]) {
    return jl;
  } else                    {
    return jl+1;  //equally  ju
  }
1989 1990 1991

}

1992 1993
int get_sf_periodicBSRTimer(uint8_t sf_offset)
{
1994 1995 1996 1997 1998

  switch (sf_offset) {
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf5:
    return 5;
    break;
1999

2000 2001 2002
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf10:
    return 10;
    break;
2003

2004 2005 2006
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf16:
    return 16;
    break;
2007

2008 2009 2010
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf20:
    return 20;
    break;
2011

2012 2013 2014
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf32:
    return 32;
    break;
2015

2016 2017 2018
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf40:
    return 40;
    break;
2019

2020 2021 2022
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf64:
    return 64;
    break;
2023

2024 2025 2026
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf80:
    return 80;
    break;
2027

2028 2029 2030
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf128:
    return 128;
    break;
2031

2032 2033 2034
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf160:
    return 160;
    break;
2035

2036 2037 2038
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf320:
    return 320;
    break;
2039

2040 2041 2042
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf640:
    return 640;
    break;
2043

2044 2045 2046
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf1280:
    return 1280;
    break;
2047

2048 2049 2050
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf2560:
    return 2560;
    break;
2051

2052 2053 2054 2055 2056 2057 2058
  case MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity:
  default:
    return -1;
    break;
  }
}

2059 2060
int get_sf_retxBSRTimer(uint8_t sf_offset)
{
2061 2062 2063 2064 2065

  switch (sf_offset) {
  case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf320:
    return 320;
    break;
2066

2067 2068 2069
  case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf640:
    return 640;
    break;
2070

2071 2072 2073
  case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf1280:
    return 1280;
    break;
2074

2075 2076 2077
  case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560:
    return 2560;
    break;
2078

2079 2080 2081
  case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf5120:
    return 5120;
    break;
2082

2083 2084 2085
  case MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240:
    return 10240;
    break;
2086

2087 2088 2089 2090 2091
  default:
    return -1;
    break;
  }
}
2092 2093
int get_ms_bucketsizeduration(uint8_t bucketsizeduration)
{
2094 2095 2096 2097 2098

  switch (bucketsizeduration) {
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50:
    return 50;
    break;
2099

2100 2101 2102
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100:
    return 100;
    break;
2103

2104 2105 2106
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms150:
    return 150;
    break;
2107

2108 2109 2110
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms300:
    return 300;
    break;
2111

2112 2113 2114
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms500:
    return 500;
    break;
2115

2116 2117 2118
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000:
    return 1000;
    break;
2119

2120 2121 2122 2123 2124 2125
  default:
    return 0;
    break;
  }
}

2126 2127
void update_phr(module_id_t module_idP,int CC_id)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2128 2129 2130 2131 2132 2133

  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
    return;
  }
2134 2135 2136 2137 2138

  UE_mac_inst[module_idP].PHR_reporting_active =0;
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
  // LOG_D(MAC,"phr %d %d\n ",UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF, UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF);
2139
}
2140 2141
uint8_t get_phr_mapping (module_id_t module_idP, int CC_id, uint8_t eNB_index)
{
2142

Raymond Knopp's avatar
 
Raymond Knopp committed
2143 2144 2145
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
2146
    return 0; // not reached
Raymond Knopp's avatar
 
Raymond Knopp committed
2147
  }
2148

2149 2150
  //power headroom reporting range is from -23 ...+40 dB, as described in 36313
  //note: mac_xface->get_Po_NOMINAL_PUSCH(module_idP) is float
2151
  if (mac_xface->get_PHR(module_idP,CC_id,eNB_index) < -23) {
2152
    return 0;
2153
  } else if (mac_xface->get_PHR(module_idP,CC_id,eNB_index) >= 40) {
2154
    return 63;
2155
  } else { // -23 to 40
Raymond Knopp's avatar
 
Raymond Knopp committed
2156
    return  (uint8_t) mac_xface->get_PHR(module_idP,CC_id,eNB_index) + PHR_MAPPING_OFFSET;
2157

2158
  }
2159
}
2160 2161
int get_sf_perioidicPHR_Timer(uint8_t perioidicPHR_Timer)
{
2162 2163 2164 2165
  return (perioidicPHR_Timer+1)*10;
}


2166 2167
int get_sf_prohibitPHR_Timer(uint8_t prohibitPHR_Timer)
{
2168 2169 2170
  return (prohibitPHR_Timer)*10;
}

2171 2172 2173
int get_db_dl_PathlossChange(uint8_t dl_PathlossChange)
{
  switch (dl_PathlossChange) {
2174 2175 2176
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1:
    return 1;
    break;
2177

2178 2179 2180
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3:
    return 3;
    break;
2181

2182 2183 2184
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB6:
    return 6;
    break;
2185

2186 2187 2188 2189 2190 2191
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_infinity:
  default:
    return -1;
    break;
  }
}