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

/*! \file ue_procedures.c
23
 * \brief procedures related to UE
24 25 26
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \version 1
27 28
 * \email: navid.nikaein@eurecom.fr
 * @ingroup _mac
29

30
 */
31

32 33 34 35
#ifdef EXMIMO
#include <pthread.h>
#endif

36 37
#include "extern.h"
#include "defs.h"
38
#include "proto.h"
39
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
40
# include "SIMULATION/PHY_EMULATION/impl_defs.h"
41
#else
Cedric Roux's avatar
Cedric Roux committed
42 43
# include "SCHED/defs.h"
# include "PHY/impl_defs_top.h"
44 45 46
#endif
#include "PHY_INTERFACE/extern.h"
#include "COMMON/mac_rrc_primitives.h"
Cedric Roux's avatar
Cedric Roux committed
47 48

#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
49 50 51
#include "RRC/LITE/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
Cedric Roux's avatar
Cedric Roux committed
52
#include "UTIL/OPT/opt.h"
53 54
#include "OCG.h"
#include "OCG_extern.h"
55
#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
Cedric Roux's avatar
Cedric Roux committed
56

57
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
58
# include "SIMULATION/simulation_defs.h"
59
#endif
60
#include "pdcp.h"
61

62 63 64 65
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

66 67
#include "assertions.h"

68 69
#include "SIMULATION/TOOLS/defs.h" // for taus

70
#define DEBUG_HEADER_PARSING 1
71
#define ENABLE_MAC_PAYLOAD_DEBUG 1
72

fnabet's avatar
fnabet committed
73 74
extern uint8_t usim_test;

75 76
extern UL_IND_t *UL_INFO;

77 78
extern uint8_t  nfapi_mode;

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


95 96
void ue_init_mac(module_id_t module_idP)
{
97 98
  int i;
  // default values as deined in 36.331 sec 9.2.2
99 100
  LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
  //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
Cedric Roux's avatar
Cedric Roux committed
101 102
  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= RetxBSR_Timer_r12_sf10240;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=PeriodicBSR_Timer_r12_infinity;
103 104 105 106 107 108 109 110 111
  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;
fnabet's avatar
fnabet committed
112 113
  UE_mac_inst[module_idP].scheduling_info.extendedBSR_Sizes_r10=0;
  UE_mac_inst[module_idP].scheduling_info.extendedPHR_r10=0;
114 115
  UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
calvin wang's avatar
calvin wang committed
116
  // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW.
hbilel's avatar
hbilel committed
117 118
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  MAC_UE_BSR_TIMER_NOT_RUNNING;
  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  MAC_UE_BSR_TIMER_NOT_RUNNING;
119
  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
120

121 122 123
  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);
fnabet's avatar
fnabet committed
124
  UE_mac_inst[module_idP].PHR_reporting_active = 0;
125 126

  for (i=0; i < MAX_NUM_LCID; i++) {
Raymond Knopp's avatar
 
Raymond Knopp committed
127 128
    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;
129 130
    UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1;

131
    if (i < DTCH) { // initilize all control channels lcgid to 0
132
      UE_mac_inst[module_idP].scheduling_info.LCGID[i]=0;
133
    } else { // initialize all the data channels lcgid to 1
134
      UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
135
    }
136

fnabet's avatar
fnabet committed
137
    UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=LCID_EMPTY;
hbilel's avatar
hbilel committed
138
    UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0;
139
  }
140

141 142
  if(nfapi_mode == 3) {
	  pthread_mutex_init(&UE_mac_inst[module_idP].UL_INFO_mutex,NULL);
143
	  UE_mac_inst[module_idP].UE_mode[0] = NOT_SYNCHED; //PRACH;
144 145 146 147 148 149 150
	  UE_mac_inst[module_idP].first_ULSCH_Tx =0;
	  UE_mac_inst[module_idP].dl_config_req = NULL;
	  UE_mac_inst[module_idP].ul_config_req = NULL;
	  UE_mac_inst[module_idP].hi_dci0_req = NULL;
	  UE_mac_inst[module_idP].tx_req = NULL;
  }

151
#ifdef CBA
152

153
  for (i=0; i <NUM_MAX_CBA_GROUP; i++) {
154
    UE_mac_inst[module_idP].cba_last_access[i]= round(uniform_rngen(1,30));
155
  }
156 157

#endif
158 159
}

Raymond Knopp's avatar
 
Raymond Knopp committed
160

161
unsigned char *parse_header(unsigned char *mac_header,
162 163 164 165 166 167 168
                            unsigned char *num_ce,
                            unsigned char *num_sdu,
                            unsigned char *rx_ces,
                            unsigned char *rx_lcids,
                            unsigned short *rx_lengths,
                            unsigned short tb_length)
{
169

fnabet's avatar
fnabet committed
170
  unsigned char not_done=1,num_ces=0,num_cont_res = 0,num_padding = 0,num_sdus=0,lcid, num_sdu_cnt;
171 172 173 174 175
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length,ce_len=0;

  while (not_done==1) {

176 177 178 179 180 181 182 183 184 185 186 187 188
    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;

189
        for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++) {
190
          length -= rx_lengths[num_sdu_cnt];
191
        }
192 193 194 195
      } 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;
196
#ifdef DEBUG_HEADER_PARSING
197
          LOG_D(MAC,"[UE] parse long sdu, size %x \n",length);
198
#endif
199

200 201 202 203 204 205
        }  else { //if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;
        }
      }

206
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
207
      LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %ld)\n",
208
            num_sdus,lcid,length,mac_header_ptr-mac_header);
209
#endif
210 211 212 213 214
      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
    } else { // This is a control element subheader
      if (lcid == SHORT_PADDING) {
fnabet's avatar
fnabet committed
215
    	num_padding ++;
216 217 218 219 220 221
        mac_header_ptr++;
      } else {
        rx_ces[num_ces] = lcid;
        num_ces++;
        mac_header_ptr ++;

222
        if (lcid==TIMING_ADV_CMD) {
223
          ce_len++;
224
        } else if (lcid==UE_CONT_RES) {
fnabet's avatar
fnabet committed
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

        	// FNA: check MAC Header is one of thoses defined in Annex B of 36.321
        	// Check there is only 1 Contention Resolution
        	if (num_cont_res) {
        		LOG_W(MAC,"[UE] Msg4 Wrong received format: More than 1 Contention Resolution\n");
        		// exit parsing
        		return NULL;

        	}

        	// UE_CONT_RES shall never be the last subheader unless this is the only MAC subheader
        	if ((not_done == 0) && ((num_sdus) || (num_ces > 1) || (num_padding))) {
        		LOG_W(MAC,"[UE] Msg4 Wrong received format: Contention Resolution after num_ces=%d num_sdus=%d num_padding=%d\n",num_ces,num_sdus,num_padding);
        		// exit parsing
        		return NULL;
        	}
          num_cont_res ++;
242
          ce_len+=6;
243
        }
244
      }
245

246
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
247
      LOG_D(MAC,"[UE] ce %d lcid %d (offset now %ld)\n",num_ces,lcid,mac_header_ptr-mac_header);
248
#endif
249
    }
250
  }
251

252 253 254 255 256 257
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
}

258 259
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)
{
260 261 262

  // 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
263 264 265
  int MGRP       = 0; // measurement gap repetition period in ms
  int gapOffset  = -1;
  int T          = 0;
266

267
  DevCheck(module_idP < (int)NB_UE_INST, module_idP, NB_UE_INST, 0);
268

269 270
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
271

272
  // determin the measurement gap
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
  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);
    }
293
  }
294 295

  if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) &&
296
      (UE_mac_inst[module_idP].scheduling_info.SR_pending==1) &&
297
      (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER <
298 299
       (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)))
     ) {
300
    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",
301
          module_idP,rnti,frameP,subframe,
302 303 304 305
          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);

306
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++;
307

308 309 310 311
    // 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;
312
    } else {
313
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
314
    }
315 316 317 318 319 320 321 322 323 324 325 326 327

    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
hbilel's avatar
hbilel committed
328 329 330 331
      if (UE_mac_inst[module_idP].scheduling_info.SR_pending){
          // release all pucch resource
          UE_mac_inst[module_idP].physicalConfigDedicated = NULL;
          UE_mac_inst[module_idP].ul_active=0;
332
          UE_mac_inst[module_idP].BSR_reporting_active=BSR_TRIGGER_NONE;
hbilel's avatar
hbilel committed
333 334 335

          LOG_I(MAC,"[UE %d] Release all SRs \n", module_idP);
      }
336 337 338
    UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
    return(0);
339 340 341
  }
}

342 343
//------------------------------------------------------------------------------
void
fnabet's avatar
fnabet committed
344 345
ue_send_sdu(
  module_id_t module_idP,
346 347
	    uint8_t CC_id,
	    frame_t frameP,
348
        sub_frame_t subframeP,
349 350
	    uint8_t* sdu,
	    uint16_t sdu_len,
fnabet's avatar
fnabet committed
351 352 353 354
  uint8_t eNB_index
)
//------------------------------------------------------------------------------
{
355 356 357 358 359

  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;
gabrielC's avatar
gabrielC committed
360
#if UE_TIMING_TRACE
361
  start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
gabrielC's avatar
gabrielC committed
362
#endif
363
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
364

365
  LOG_D(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]);
366

367
  if (opt_enabled) {
368
    trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
369
        frameP, subframeP, 0, 0);
navid's avatar
navid committed
370 371
    LOG_D(OPT,"[UE %d][DLSCH] Frame %d trace pdu for rnti %x  with size %d\n",
          module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len);
372 373 374 375 376
  }

  payload_ptr = parse_header(sdu,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_len);

#ifdef DEBUG_HEADER_PARSING
377
  LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP,
378
        frameP,eNB_index,num_ce,num_sdu);
379 380 381
#endif

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
Cedric Roux's avatar
Cedric Roux committed
382
  LOG_T(MAC,"[UE %d] First 32 bytes of DLSCH : \n", module_idP);
383

384
  for (i=0; i<32; i++) {
385
    LOG_T(MAC,"%x.",sdu[i]);
386
  }
387

388
  LOG_T(MAC,"\n");
389 390
#endif

fnabet's avatar
fnabet committed
391 392
  if (payload_ptr != NULL) {

393 394 395 396
  for (i=0; i<num_ce; i++) {
    //    printf("ce %d : %d\n",i,rx_ces[i]);
    switch (rx_ces[i]) {
    case UE_CONT_RES:
397

398
      LOG_I(MAC,"[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n",
399
            module_idP,frameP,payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4],payload_ptr[5]);
400 401

      if (UE_mac_inst[module_idP].RA_active == 1) {
Cedric Roux's avatar
Cedric Roux committed
402
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", module_idP, frameP);
403 404 405 406 407 408 409 410
        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]) {
411 412 413 414 415 416 417 418 419 420
        	  LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP);
        	  if(nfapi_mode == 3) { // Panos: phy_stub mode
        		  // Panos: Modification for phy_stub mode operation here. We only need to make sure that the ue_mode is back to
        		  // PRACH state.
        		  UE_mac_inst[module_idP].UE_mode[eNB_index] = PRACH;
        		  //ra_failed(module_idP,CC_id,eNB_index);UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
        	  }
        	  else { // Full stack mode
        		  ra_failed(module_idP,CC_id,eNB_index);
        	  }
421
            VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
422 423 424
            return;
          }

Cedric Roux's avatar
Cedric Roux committed
425
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n", module_idP, frameP);
426
        UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
427

428 429 430 431 432 433 434 435
        if(nfapi_mode == 3) // phy_stub mode
        {
        	//Panos: Modification for phy_stub mode operation here. We only need to change the ue_mode to PUSCH
        	UE_mac_inst[module_idP].UE_mode[eNB_index] = PUSCH;
        }
        else { // Full stack mode
        	ra_succeeded(module_idP,CC_id,eNB_index);
        }
436 437 438 439 440 441
      }

      payload_ptr+=6;
      break;

    case TIMING_ADV_CMD:
442
#ifdef DEBUG_HEADER_PARSING
443
      LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]);
444
#endif
445
      // Panos: Eliminate call to process_timing_advance for the phy_stub UE operation mode. Is this correct?
446 447 448 449
      if (nfapi_mode!=3)
      {
    	  process_timing_advance(module_idP,CC_id,payload_ptr[0]);
      }
450 451 452 453
      payload_ptr++;
      break;

    case DRX_CMD:
454
#ifdef DEBUG_HEADER_PARSING
455
      LOG_D(MAC,"[UE] CE %d : UE DRX :",i);
456
#endif
457 458 459
      payload_ptr++;
      break;
    }
460
  }
461 462

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

467 468
    if (rx_lcids[i] == CCCH) {

469 470 471 472 473 474
      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]);
475 476

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
477
      int j;
478

479
      for (j=0; j<rx_lengths[i]; j++) {
480
        LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]);
481
      }
482 483 484 485

      LOG_T(MAC,"\n");
#endif
      mac_rrc_data_ind(module_idP,
486
                       CC_id,
487
                       frameP,subframeP,
488
                       UE_mac_inst[module_idP].crnti,
489
                       CCCH,
490 491 492 493 494
                       (uint8_t*)payload_ptr,
                       rx_lengths[i],
                       ENB_FLAG_NO,
                       eNB_index,
                       0);
495

496
    } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) {
497
      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]);
498 499
      mac_rlc_data_ind(module_idP,
                       UE_mac_inst[module_idP].crnti,
500
		       eNB_index,
501 502 503
                       frameP,
                       ENB_FLAG_NO,
                       MBMS_FLAG_NO,
504
                       rx_lcids[i],
505 506 507 508
                       (char *)payload_ptr,
                       rx_lengths[i],
                       1,
                       NULL);
509

510
    } else if ((rx_lcids[i]  < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) {
511

512
      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]);
513 514

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
515
      int j;
516 517
      for (j=0;j<rx_lengths[i];j++)
	LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]);
518
      LOG_T(MAC,"\n");
519
#endif
520
      mac_rlc_data_ind(module_idP,
521
		       UE_mac_inst[module_idP].crnti,
522 523
		       eNB_index,
		       frameP,
524 525 526 527 528 529 530 531 532
		       ENB_FLAG_NO,
		       MBMS_FLAG_NO,
		       rx_lcids[i],
		       (char *)payload_ptr,
		       rx_lengths[i],
		       1,
		       NULL);
    } else {
      LOG_E(MAC,"[UE %d] Frame %d : unknown LCID %d (eNB %d)\n", module_idP, frameP,rx_lcids[i], eNB_index);
533 534
    }
    payload_ptr+= rx_lengths[i];
535
  }
fnabet's avatar
fnabet committed
536
  } // end if (payload_ptr != NULL)
537

538
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
539
#if UE_TIMING_TRACE
540
  stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
gabrielC's avatar
gabrielC committed
541
#endif
542 543
}

544 545
void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len)
{
gabrielC's avatar
gabrielC committed
546 547 548
#if UE_TIMING_TRACE
    start_meas(&UE_mac_inst[module_idP].rx_si);
#endif
549
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);
550

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

553
  mac_rrc_data_ind(module_idP,
554
                   CC_id,
555
                   frameP,0, // unknown subframe
556
                   SI_RNTI,
557 558 559
                   BCCH,
                   (uint8_t *)pdu,
                   len,
560
                   ENB_FLAG_NO,
561 562
                   eNB_index,
                   0);
563
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
564
#if UE_TIMING_TRACE
565
  stop_meas(&UE_mac_inst[module_idP].rx_si);
gabrielC's avatar
gabrielC committed
566
#endif
navid's avatar
navid committed
567 568 569 570 571 572 573
  if (opt_enabled == 1) {
    trace_pdu(0,
	      (uint8_t *)pdu,
	      len,
	      module_idP,
	      4,
	      0xffff,
574 575
	      UE_mac_inst[module_idP].rxFrame,
	      UE_mac_inst[module_idP].rxSubframe,
navid's avatar
navid committed
576 577 578 579 580
	      0,
	      0);
    LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
	    module_idP, frameP, CC_id, 0xffff, len);
  }
581 582
}

583 584
void ue_decode_p(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len)
{
gabrielC's avatar
gabrielC committed
585 586 587
#if UE_TIMING_TRACE
    start_meas(&UE_mac_inst[module_idP].rx_p);
#endif
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN);

  LOG_D(MAC,"[UE %d] Frame %d Sending Paging message to RRC (LCID Id %d,len %d)\n",module_idP,frameP,PCCH,len);

  mac_rrc_data_ind(module_idP,
                   CC_id,
                   frameP,0, // unknown subframe
                   P_RNTI,
                   PCCH,
                   (uint8_t *)pdu,
                   len,
                   ENB_FLAG_NO,
                   eNB_index,
                   0);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
603
#if UE_TIMING_TRACE
604
  stop_meas(&UE_mac_inst[module_idP].rx_p);
gabrielC's avatar
gabrielC committed
605
#endif
606 607 608 609 610 611 612
  if (opt_enabled == 1) {
    trace_pdu(0,
	      (uint8_t *)pdu,
	      len,
	      module_idP,
	      4,
	      P_RNTI,
613 614
	      UE_mac_inst[module_idP].rxFrame,
	      UE_mac_inst[module_idP].rxSubframe,
615 616 617 618 619 620 621
	      0,
	      0);
    LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
	    module_idP, frameP, CC_id, P_RNTI, len);
  }
}

Cedric Roux's avatar
Cedric Roux committed
622
#if defined(Rel10) || defined(Rel14)
623
unsigned char *parse_mch_header(unsigned char *mac_header,
624 625 626 627 628
                                unsigned char *num_sdu,
                                unsigned char *rx_lcids,
                                unsigned short *rx_lengths,
                                unsigned short tb_length)
{
629 630 631
  unsigned char not_done=1, num_sdus=0, lcid, i;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length;
632

633
  while (not_done == 1) {
634 635 636 637 638 639 640 641 642 643 644
    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);

645
        for (i=0; i<num_sdus; i++) {
646
          length -= rx_lengths[i];
647
        }
648 649 650 651 652 653 654 655 656
      } 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;
        }
657
      }
658 659 660 661 662 663 664 665

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

668 669 670 671 672
  *num_sdu = num_sdus;
  return(mac_header_ptr);
}

// this function is for sending mch_sdu from phy to mac
673 674
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)
{
675 676

  unsigned char num_sdu, i, *payload_ptr;
677
  unsigned char rx_lcids[NB_RB_MAX];
678
  unsigned short rx_lengths[NB_RB_MAX];
gabrielC's avatar
gabrielC committed
679
#if UE_TIMING_TRACE
680
  start_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
gabrielC's avatar
gabrielC committed
681
#endif
682
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN);
683

684
  LOG_D(MAC,"[UE %d] Frame %d : process the mch PDU for sync area %d \n",module_idP,frameP, sync_area);
685 686
  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);
687 688

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

  for (i=0; i<num_sdu; i++) {
692 693 694 695 696 697 698
    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;
699
      }
700 701 702
    } 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,
703
                       CC_id,
704
                       frameP,0, // unknown subframe
705
                       M_RNTI,
706 707 708 709 710 711 712 713
                       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,
714
          UE_mac_inst[module_idP].crnti,
715 716
          eNB_index,
	  frameP,
717 718 719 720 721 722 723
          ENB_FLAG_NO,
          MBMS_FLAG_YES,
          MTCH, /*+ (maxDRB + 3),*/
          (char *)payload_ptr,
          rx_lengths[i],
          1,
          NULL);
724 725

      }
726 727 728 729 730 731 732 733 734
    } 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);
    }
735

736
    payload_ptr += rx_lengths[i];
737 738
  }

739
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
740
#if UE_TIMING_TRACE
741
  stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
gabrielC's avatar
gabrielC committed
742
#endif
743 744
}

Raymond Knopp's avatar
Raymond Knopp committed
745 746 747 748 749 750 751

void ue_send_sl_sdu(module_id_t module_idP,
		    uint8_t CC_id,
		    frame_t frameP,
		    sub_frame_t subframeP,
		    uint8_t* sdu,
		    uint16_t sdu_len,
752 753
		    uint8_t eNB_index,
		    sl_discovery_flag_t sl_discovery_flag
Raymond Knopp's avatar
Raymond Knopp committed
754 755
		    ) {

756 757
  int rlc_sdu_len;
  char *rlc_sdu;
758
  int lcid;
759
  uint32_t destinationL2Id =0x00000000;
760
  uint32_t sourceL2Id = 0x00000000;
761

762 763
  if (sl_discovery_flag == SL_DISCOVERY_FLAG_NO) {

764 765 766 767 768 769
  // Notes: 1. no control elements are supported yet
  //        2. we exit with error if LCID != 3
  //        3. we exit with error if E=1 (more than one SDU/CE)
  // extract header
  SLSCH_SUBHEADER_24_Bit_DST_LONG *longh = (SLSCH_SUBHEADER_24_Bit_DST_LONG *)sdu;
  AssertFatal(longh->E==0,"E is non-zero\n");
770
  //AssertFatal(((longh->LCID==3)|(longh->LCID==10)|(longh->LCID==4)),"LCID is %d (not 3, 4 or 10)\n",longh->LCID);
771 772
  //filter incoming packet based on destination address
  destinationL2Id = (longh->DST07<<16) | (longh->DST815 <<8) | (longh->DST1623);
773
  sourceL2Id = (longh->SRC07<<16) | (longh->SRC815 <<8) | (longh->SRC1623);
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
774

775
  //in case of 1-n communication, verify that UE belongs to that group
776
  int i = 0;
777
  int j = 0;
778
  for (i=0; i< MAX_NUM_LCID; i++)
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
779
     if ((UE_mac_inst[module_idP].sl_info[i].groupL2Id == destinationL2Id) && (UE_mac_inst[module_idP].sl_info[i].sourceL2Id != sourceL2Id)) {
780 781 782 783 784 785
        lcid = UE_mac_inst[module_idP].sl_info[i].LCID;
        break;
     }

  for (j = 0; j< MAX_NUM_LCID; j++){
     if ((longh->LCID < MAX_NUM_LCID_DATA) && (j < MAX_NUM_LCID_DATA)){
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
786
        if ((UE_mac_inst[module_idP].sl_info[j].destinationL2Id == sourceL2Id) && (UE_mac_inst[module_idP].sl_info[j].sourceL2Id == destinationL2Id)) {
787 788 789 790 791
           lcid = UE_mac_inst[module_idP].sl_info[j].LCID;
           break;
        }
     }
     if ((longh->LCID >= MAX_NUM_LCID_DATA) && (j >= MAX_NUM_LCID_DATA)){
792
        //PC5-S (receive message after transmitting, e.g, security-command...)
793 794
        if ((UE_mac_inst[module_idP].sl_info[j].sourceL2Id == destinationL2Id) && (UE_mac_inst[module_idP].sl_info[j].destinationL2Id == 0)) {
           if (UE_mac_inst[module_idP].sl_info[j].LCID > 0) lcid = UE_mac_inst[module_idP].sl_info[j].LCID;
795 796 797 798
           break;
        }
     }
  }
799
/*
800 801 802 803
  int k = 0;
  if (j == MAX_NUM_LCID) {
     for (k = MAX_NUM_LCID_DATA; k < MAX_NUM_LCID; k++){
        //PC5-S (default RX)
804 805
        if ((UE_mac_inst[module_idP].sl_info[k].sourceL2Id == destinationL2Id) && (UE_mac_inst[module_idP].sl_info[k].destinationL2Id == 0)) 
        {
806 807 808 809 810 811
           lcid = UE_mac_inst[module_idP].sl_info[k].LCID;
           break;
        }
     }
  }

812
*/
813

814
  //match the destinationL2Id with UE L2Id or groupL2ID
815
    if (!(((destinationL2Id == UE_mac_inst[module_idP].sourceL2Id) && (j < MAX_NUM_LCID)) | ((destinationL2Id == UE_mac_inst[module_idP].sourceL2Id) && (longh->LCID >= MAX_NUM_LCID_DATA)) | (i < MAX_NUM_LCID))){
816 817 818
       LOG_D( MAC, "[Destination Id is neither matched with Source Id nor with Group Id, drop the packet!!! \n");
       return;
    }
819

820
    LOG_I( MAC, "DestinationL2Id:  0x%08x, sl_rbid %d, longh->LCID %d  \n", destinationL2Id, lcid, longh->LCID );
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
821

822

823 824 825 826 827 828 829 830
  if (longh->F==1) {
    rlc_sdu_len = ((longh->L_MSB<<8)&0x7F00)|(longh->L_LSB&0xFF);
    rlc_sdu = sdu+sizeof(SLSCH_SUBHEADER_24_Bit_DST_LONG);
  }
  else {
    rlc_sdu_len = ((SLSCH_SUBHEADER_24_Bit_DST_SHORT *)sdu)->L;
    rlc_sdu = sdu+sizeof(SLSCH_SUBHEADER_24_Bit_DST_SHORT);
  }
Raymond Knopp's avatar
Raymond Knopp committed
831 832 833 834 835 836 837
  mac_rlc_data_ind(
		   module_idP,
		   0x1234,
		   eNB_index,
		   frameP,
		   ENB_FLAG_NO,
		   MBMS_FLAG_NO,
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
838
		   lcid, //3/10
839 840
		   rlc_sdu,
		   rlc_sdu_len,
Raymond Knopp's avatar
Raymond Knopp committed
841 842
		   1,
		   NULL);
843
  } else { //SL_DISCOVERY
844
     uint16_t len = sdu_len;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
845
     LOG_D( MAC, "SL DISCOVERY \n");
846 847 848 849 850 851
     mac_rrc_data_ind(module_idP,
                      CC_id,
                      frameP,subframeP,
                      UE_mac_inst[module_idP].crnti,
                      SL_DISCOVERY,
                      sdu, //(uint8_t*)&UE_mac_inst[Mod_id].SL_Discovery[0].Rx_buffer.Payload[0],
William Johnson's avatar
William Johnson committed
852
                      len,
853 854 855 856 857
                      ENB_FLAG_NO,
                      eNB_index,
                      0);

  }
Raymond Knopp's avatar
Raymond Knopp committed
858 859 860
}


861 862
int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index)
{
863
  // currently there is one-to-one mapping between sf allocation pattern and sync area
864 865
  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 );
866
    return -1;
867
  } else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) {
868
    return mbsfn_sync_area;
869
  } else {
870
    LOG_W( MAC, "[UE %"PRIu8"] MBSFN Subframe Config pattern %"PRIu8" not found \n", module_idP, mbsfn_sync_area );
871
    return -1;
872 873
  }
}
874

875 876
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)
{
877

winckel's avatar
winckel committed
878
  int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1;
879
  int mcch_flag=0, mtch_flag=0, msi_flag=0;
880 881
  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
882
  int mch_scheduling_period = -1;
883

884
  int frame_FDD=1;
885

886

gabrielC's avatar
gabrielC committed
887
#if UE_TIMING_TRACE
888
  start_meas(&UE_mac_inst[module_idP].ue_query_mch);
gabrielC's avatar
gabrielC committed
889
#endif
890

891
  if (UE_mac_inst[module_idP].pmch_Config[0]) {
892
    mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9);
893
  }
894

895
  for (i=0;
896 897 898
       i< UE_mac_inst[module_idP].num_active_mbsfn_area;
       i++ ) {
    // assume, that there is always a mapping
899
    if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1) {
900
      return -1; // continue;
901
    }
902 903 904 905 906 907

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

908
    LOG_D(MAC,
Cedric Roux's avatar
Cedric Roux committed
909
          "[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,%ld))\n",
910
          module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area,
911 912 913
          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);

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
    // 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++;
            }
          }
        }

946 947
	if (UE_mac_inst[module_idP].tdd_Config == NULL) frame_FDD=1;
	else frame_FDD=0;
948 949 950
        // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
        switch (subframe) {
        case 1:
951
          if (frame_FDD==1) {
952
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) {
953
              if (msi_pos == 1) {
954
                msi_flag = 1;
955
              }
956

957
	      if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
958
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) ) {
959
                mcch_flag = 1;
960
              }
961 962 963 964 965 966 967 968

              mtch_flag = 1;
            }
          }

          break;

        case 2:
969
          if (frame_FDD==1) {
970
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) {
971
              if (msi_pos == 2) {
972
                msi_flag = 1;
973
              }
974 975

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
976
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) ) {
977
                mcch_flag = 1;
978
              }
979 980 981 982

              mtch_flag = 1;
            }
          }
983

984 985 986
          break;

        case 3:
987
          if (frame_FDD==0) { //TDD
988
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) {
989
              if (msi_pos == 1) {
990
                msi_flag = 1;
991
              }
992 993

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
994
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) ) {
995
                mcch_flag = 1;
996
              }
997 998 999 1000 1001

              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) {
1002
              if (msi_pos == 3) {
1003
                msi_flag = 1;
1004
              }
1005 1006

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1007
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) ) {
1008
                mcch_flag = 1;
1009
              }
1010 1011 1012 1013 1014 1015 1016 1017

              mtch_flag = 1;
            }
          }

          break;

        case 4:
1018
          if (frame_FDD==0) {
1019
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) {
1020
              if (msi_pos == 2) {
1021
                msi_flag = 1;
1022
              }
1023 1024

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1025
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) ) {
1026
                mcch_flag = 1;
1027
              }
1028 1029 1030 1031 1032 1033 1034 1035

              mtch_flag = 1;
            }
          }

          break;

        case 6:
1036
          if (frame_FDD==1) {
1037
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) {
1038
              if (msi_pos == 4) {
1039
                msi_flag = 1;
1040
              }
1041 1042

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1043
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) ) {
1044
                mcch_flag = 1;
1045
              }
1046 1047 1048

              mtch_flag = 1;
            }
1049
          }
1050 1051 1052 1053

          break;

        case 7:
1054
          if (frame_FDD==0) { // TDD
1055
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) {
1056
              if (msi_pos == 3) {
1057
                msi_flag = 1;
1058
              }
1059 1060

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1061
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) ) {
1062
                mcch_flag = 1;
1063
              }
1064 1065 1066 1067 1068

              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) {
1069
              if (msi_pos == 5) {
1070
                msi_flag = 1;
1071
              }
1072 1073

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1074
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) ) {
1075
                mcch_flag = 1;
1076
              }
1077 1078 1079

              mtch_flag = 1;
            }
1080
          }
1081 1082 1083 1084

          break;

        case 8:
1085
          if (frame_FDD==0) { //TDD
1086
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) {
1087
              if (msi_pos == 4) {
1088
                msi_flag = 1;
1089
              }
1090 1091

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1092
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) ) {
1093
                mcch_flag = 1;
1094
              }
1095 1096 1097 1098 1099

              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) {
1100
              if (msi_pos == 6) {
1101
                msi_flag = 1;
1102
              }
1103 1104

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1105
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) ) {
1106
                mcch_flag = 1;
1107
              }
1108 1109 1110 1111 1112 1113 1114 1115

              mtch_flag = 1;
            }
          }

          break;

        case 9:
1116
          if (frame_FDD==0) {
1117
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) {
1118
              if (msi_pos == 5) {
1119
                msi_flag = 1;
1120
              }
1121 1122

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
1123
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) ) {
1124
                mcch_flag = 1;
1125
              }
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142

              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
1143
      }
1144
    }
1145
  } // end of for
gabrielC's avatar
gabrielC committed
1146
#if UE_TIMING_TRACE
1147
  stop_meas(&UE_mac_inst[module_idP].ue_query_mch);
gabrielC's avatar
gabrielC committed
1148
#endif
1149

1150
  if ( (mcch_flag==1)) { // || (msi_flag==1))
1151
    *mcch_active=1;
1152
  }
1153

1154 1155
  if ( (mcch_flag==1) || ((msi_flag==1) && (UE_mac_inst[module_idP].mcch_status==1)) ) {
    return mcch_mcs;
1156
  } else if ((mtch_flag==1) && (UE_mac_inst[module_idP].msi_status==1)) {
1157
    return UE_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9;
1158
  } else {
1159
    return -1;
1160
  }
1161 1162 1163 1164
}

#endif

1165
unsigned char generate_ulsch_header(uint8_t *mac_header,
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
                                    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)
{
1177 1178 1179 1180 1181 1182 1183

  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
1184

1185
  for (i=0; i<num_sdus; i++) {
1186
    LOG_T(MAC,"[UE] sdu %d : lcid %d length %d",i,sdu_lcids[i],sdu_lengths[i]);
1187
  }
1188

1189 1190 1191 1192 1193
  LOG_T(MAC,"\n");
#endif
  ce_ptr = &mac_header_control_elements[0];

  if ((short_padding == 1) || (short_padding == 2)) {
1194 1195 1196 1197 1198
    mac_header_ptr->R    = 0;
    mac_header_ptr->E    = 0;
    mac_header_ptr->LCID = SHORT_PADDING;
    first_element=1;
    last_size=1;
1199
  }
1200

1201
  if (short_padding == 2) {
1202 1203 1204 1205 1206 1207
    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;
1208 1209 1210
  }

  if (power_headroom) {
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
    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);
Cedric Roux's avatar
Cedric Roux committed
1224
    LOG_D(MAC, "phr header size %zu\n",sizeof(POWER_HEADROOM_CMD));
1225 1226 1227 1228
  }

  if (crnti) {
#ifdef DEBUG_HEADER_PARSING
1229
    LOG_D(MAC,"[UE] CRNTI : %x (first_element %d)\n",*crnti,first_element);
1230
#endif
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245

    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);
1246 1247 1248
  }

  if (truncated_bsr) {
1249 1250 1251
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
1252
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
1253 1254 1255 1256 1257 1258 1259 1260 1261
      ((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;
    }

1262
#ifdef DEBUG_HEADER_PARSING
1263
    LOG_D(MAC,"[UE] Scheduler Truncated BSR Header\n");
1264
#endif
1265 1266 1267 1268 1269 1270 1271
    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);
1272

1273 1274 1275 1276
  } else if (short_bsr) {
    if (first_element>0) {
      mac_header_ptr->E = 1;
      /*
1277
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
1278 1279 1280 1281 1282 1283 1284 1285 1286
      ((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;
    }

1287
#ifdef DEBUG_HEADER_PARSING
1288
    LOG_D(MAC,"[UE] Scheduler SHORT BSR Header\n");
1289
#endif
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
    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;
      /*
1302
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
1303 1304 1305 1306 1307 1308 1309 1310 1311
      ((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;
    }

1312
#ifdef DEBUG_HEADER_PARSING
1313
    LOG_D(MAC,"[UE] Scheduler Long BSR Header\n");
1314
#endif
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
    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);
    ce_ptr += BSR_LONG_SIZE;

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

1328 1329
  //  printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

1330
  for (i=0; i<num_sdus; i++) {
1331
#ifdef DEBUG_HEADER_PARSING
1332
    LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]);
1333
#endif
1334

1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
    if ((i == (num_sdus - 1)) && ((short_padding) || (post_padding == 0))) {
        if (first_element>0) {
            mac_header_ptr->E = 1;
      #ifdef DEBUG_HEADER_PARSING
            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);
      #endif
            mac_header_ptr+=last_size;
        }
        mac_header_ptr->R    = 0;
        mac_header_ptr->E    = 0;
        mac_header_ptr->LCID = sdu_lcids[i];
1349
    }
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
    else {
        if ((first_element>0)) {
          mac_header_ptr->E = 1;
    #ifdef DEBUG_HEADER_PARSING
          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);
    #endif
          mac_header_ptr+=last_size;
          //      printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
        } else {
          first_element=1;
1363

1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395
        }

        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;
    #ifdef DEBUG_HEADER_PARSING
          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);
    #endif
        } 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;
    #ifdef DEBUG_HEADER_PARSING
          LOG_D(MAC,"[UE] long sdu\n");
    #endif
        }
1396
    }
1397
  }
1398

1399
  if (post_padding>0) {// we have lots of padding at the end of the packet
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410
    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 ++
1411
  }
1412

1413

1414
  if ((ce_ptr-mac_header_control_elements) > 0) {
1415 1416
    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);
1417
  }
1418

1419
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
1420
  LOG_T(MAC," [UE] header : ");
1421

1422
  for (i=0; i<((unsigned char*)mac_header_ptr - mac_header); i++) {
1423
    LOG_T(MAC,"%2x.",mac_header[i]);
1424
  }
1425

1426 1427 1428 1429 1430 1431
  LOG_T(MAC,"\n");
#endif
  return((unsigned char*)mac_header_ptr - mac_header);

}

1432 1433
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)
{
1434

hbilel's avatar
hbilel committed
1435 1436
  uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ;
  uint16_t buflen_remain = 0;
1437
  uint8_t bsr_len=0,bsr_ce_len=0,bsr_header_len=0;
1438
  uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
1439
  uint8_t lcid=0,lcid_rlc_pdu_count=0;
hbilel's avatar
hbilel committed
1440
  boolean_t is_lcid_processed = FALSE;
1441
  boolean_t is_all_lcid_processed = FALSE;
1442 1443 1444 1445 1446
  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;
calvin wang's avatar
calvin wang committed
1447
  BSR_SHORT bsr_short,bsr_truncated;
1448 1449 1450
  BSR_LONG bsr_long;
  BSR_SHORT *bsr_s=&bsr_short;
  BSR_LONG  *bsr_l=&bsr_long;
calvin wang's avatar
calvin wang committed
1451
  BSR_SHORT *bsr_t=&bsr_truncated;
1452 1453
  POWER_HEADROOM_CMD phr;
  POWER_HEADROOM_CMD *phr_p=&phr;
fnabet's avatar
fnabet committed
1454
  unsigned short short_padding=0, post_padding=0, padding_len=0;
1455 1456
  int j; // used for padding
  // Compute header length
hbilel's avatar
hbilel committed
1457
  int lcg_id = 0;
1458 1459
  int lcg_id_bsr_trunc = 0;
  int highest_priority = 16;
hbilel's avatar
hbilel committed
1460
  int num_lcg_id_with_data = 0;
1461
  rlc_buffer_occupancy_t lcid_buffer_occupancy_old=0, lcid_buffer_occupancy_new=0;
1462

hbilel's avatar
hbilel committed
1463 1464
  LOG_D(MAC,"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n",
                        module_idP, frameP, subframe, buflen);
1465

1466

1467 1468
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
1469

gabrielC's avatar
gabrielC committed
1470
#if UE_TIMING_TRACE
1471
  start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
gabrielC's avatar
gabrielC committed
1472
#endif
1473
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_IN);
1474

Cedric Roux's avatar
Cedric Roux committed
1475
#ifdef CBA
1476 1477 1478

  if (*access_mode==CBA_ACCESS) {
    LOG_D(MAC,"[UE %d] frameP %d subframe %d try CBA transmission\n",
1479
          module_idP, frameP, subframe);
1480 1481 1482 1483

    //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;
1484
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
1485 1486 1487 1488
      return;
    }

    LOG_I(MAC,"[UE %d] frameP %d subframe %d CBA transmission oppurtunity, tbs %d\n",
1489
          module_idP, frameP, subframe,buflen);
1490
  }
1491

1492
#endif
hbilel's avatar
hbilel committed
1493
  bsr_header_len = 0;
1494
  phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
1495

hbilel's avatar
hbilel committed
1496 1497 1498 1499 1500 1501 1502 1503
  while (lcg_id < MAX_NUM_LCGID) {
     if  (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){
         num_lcg_id_with_data ++;
     }
     lcg_id ++;
  }

  if (num_lcg_id_with_data){
GabrirelCouturier's avatar
GabrirelCouturier committed
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
      LOG_D(MAC,"[UE %d] MAC Tx data pending at frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n",
                            module_idP,
                            frameP,
                            subframe,
                            num_lcg_id_with_data,
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0],
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1],
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2],
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3],
                            UE_mac_inst[module_idP].BSR_reporting_active, buflen);
hbilel's avatar
hbilel committed
1514 1515

  }
GabrirelCouturier's avatar
GabrirelCouturier committed
1516 1517 1518
  //Restart ReTxBSR Timer at new grant indication (36.321)
  if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING){
      UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
hbilel's avatar
hbilel committed
1519
  }
GabrirelCouturier's avatar
GabrirelCouturier committed
1520

hbilel's avatar
hbilel committed
1521
  // periodicBSR-Timer expires, trigger BSR
Cedric Roux's avatar
Cedric Roux committed
1522
  if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity)
hbilel's avatar
hbilel committed
1523
            && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF == 0)){
1524 1525
        // Trigger BSR Periodic
      UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PERIODIC;
hbilel's avatar
hbilel committed
1526

1527
      LOG_D(MAC,"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
hbilel's avatar
hbilel committed
1528 1529 1530 1531
                       module_idP, frameP, subframe, buflen);

    }

1532 1533
  //Compute BSR Length if Regular or Periodic BSR is triggered
  //WARNING: if BSR long is computed, it may be changed to BSR short during or after multiplexing if there remains less than 1 LCGROUP with data after Tx
hbilel's avatar
hbilel committed
1534
  if (UE_mac_inst[module_idP].BSR_reporting_active){
GabrirelCouturier's avatar
GabrirelCouturier committed
1535

1536 1537
	  AssertFatal ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING) == 0 , "Inconsistent BSR Trigger=%d !\n",
			  UE_mac_inst[module_idP].BSR_reporting_active);
GabrirelCouturier's avatar
GabrirelCouturier committed
1538

1539 1540 1541 1542 1543
      if (buflen >= 4){
    	  //A Regular or Periodic BSR can only be sent if TBS >= 4 as transmitting only a BSR is not allowed if UE has data to transmit
    	  bsr_header_len = 1;

          if (num_lcg_id_with_data <= 1){
hbilel's avatar
hbilel committed
1544 1545 1546
              bsr_ce_len = sizeof(BSR_SHORT); //1 byte
          }
          else{
fnabet's avatar
fnabet committed
1547
              bsr_ce_len = BSR_LONG_SIZE; //3 bytes
hbilel's avatar
hbilel committed
1548 1549 1550 1551
          }
      }
  }

1552
  bsr_len = bsr_ce_len + bsr_header_len;
1553

fnabet's avatar
fnabet committed
1554
  phr_ce_len = (UE_mac_inst[module_idP].PHR_reporting_active == 1) ? 1 /* sizeof(POWER_HEADROOM_CMD)*/: 0;
1555
  if ((phr_ce_len > 0) && ((phr_ce_len + phr_header_len + bsr_len) <= buflen)){
1556 1557
    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",
1558
          module_idP, phr_len, phr_ce_len, phr_header_len, buflen);
1559
  } else {
1560
    phr_len=0;
1561 1562
    phr_header_len = 0;
    phr_ce_len = 0;
1563
  }
1564 1565

  // check for UL bandwidth requests and add SR control element
1566 1567

  // check for UL bandwidth requests and add SR control element
1568 1569

  // Check for DCCH first
1570 1571
// TO DO: Multiplex in the order defined by the logical channel prioritization
for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid++) {
hbilel's avatar
hbilel committed
1572
  if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
1573

1574
      lcid_rlc_pdu_count = 0;
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591
      is_lcid_processed	= FALSE;
      lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP,
              	  	  	  	  	  	  	  	  	  	  	  	  	  UE_mac_inst[module_idP].crnti,
																  eNB_index,
																  frameP,
																  subframe,
																  ENB_FLAG_NO,
																  lcid);

      lcid_buffer_occupancy_new = lcid_buffer_occupancy_old;

      AssertFatal (lcid_buffer_occupancy_new == UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid], "LCID=%d RLC has BO %d bytes but MAC has stored %d bytes\n",
      					lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);

      AssertFatal (lcid_buffer_occupancy_new <= UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], "LCID=%d RLC has more BO %d bytes than BSR = %d bytes\n",
      					lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);

1592

hbilel's avatar
hbilel committed
1593 1594
      //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
      //Adjust at the end of the loop
1595
      while ((!is_lcid_processed) && (lcid_buffer_occupancy_new) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
1596

fnabet's avatar
fnabet committed
1597 1598 1599 1600 1601 1602 1603
    	  // Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU
    	  if ((usim_test == 0) && (lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) {

    		  // Skip SRB2 multiplex if at least one SRB1 SDU is already multiplexed
    		  break;
    	  }

1604
          buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
hbilel's avatar
hbilel committed
1605 1606


1607 1608 1609 1610 1611 1612
		  LOG_D(MAC, "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to "
				"send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
				module_idP,frameP, lcid,lcid_buffer_occupancy_new,buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);


		  sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
1613 1614 1615 1616 1617 1618 1619
							   UE_mac_inst[module_idP].crnti,
							   eNB_index,
							   frameP,
							   ENB_FLAG_NO,
							   MBMS_FLAG_NO,
							   lcid,
							   buflen_remain,
1620 1621 1622 1623 1624 1625
							   (char *)&ulsch_buff[sdu_length_total]
#ifdef Rel14
                        ,0,
                         0
#endif
                         );
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679


		  AssertFatal (buflen_remain >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
					lcid,sdu_lengths[num_sdus],buflen_remain);


		  if (sdu_lengths[num_sdus])
		  {
			  sdu_length_total += sdu_lengths[num_sdus];
			  sdu_lcids[num_sdus] = lcid;
			  LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LcId%d\n",module_idP,sdu_lengths[num_sdus],lcid);

			  if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
				  //No more remaining TBS after this PDU
				  //exit the function
				  rlc_pdu_header_len_last = 1;
				  is_lcid_processed = TRUE;
				  is_all_lcid_processed = TRUE;
			  }
			  else {
				  rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;

				  //Change to 1 byte if it does not fit in the TBS, ie last PDU
				  if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
					  rlc_pdu_header_len_last = 1;
					  is_lcid_processed = TRUE;
					  is_all_lcid_processed = TRUE;
				  }
			  }

			  //Update number of SDU
			  num_sdus ++;

			  //Update total MAC Header size for RLC PDUs and save last one
			  total_rlc_pdu_header_len += rlc_pdu_header_len_last;

			  lcid_rlc_pdu_count ++;
		  }
		  else
		  {
			  /* avoid infinite loop ... */
			  is_lcid_processed = TRUE;
		  }

          /* Get updated BO after multiplexing this PDU */
          lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP,
                        	  	  	  	  	  	  	  	  	  	  	  	  	  UE_mac_inst[module_idP].crnti,
          																  eNB_index,
          																  frameP,
          																  subframe,
          																  ENB_FLAG_NO,
          																  lcid);

          is_lcid_processed = (is_lcid_processed) || (lcid_buffer_occupancy_new <= 0);
1680
   }
1681

1682
    //Update Buffer remain and BSR bytes after transmission
1683

1684 1685
    AssertFatal (lcid_buffer_occupancy_new <=  lcid_buffer_occupancy_old, "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n",
    		lcid_buffer_occupancy_new,lcid_buffer_occupancy_old,lcid,lcid_rlc_pdu_count,frameP,subframe);
1686

1687 1688
    UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new;
    UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] += (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old);
1689

1690 1691 1692 1693 1694 1695
    //Update the number of LCGID with data as BSR shall reflect status after BSR transmission
    if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0))
    {
        num_lcg_id_with_data --;
        // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
        if ((bsr_len) && (num_lcg_id_with_data == 1))
hbilel's avatar
hbilel committed
1696
        {
1697 1698
            bsr_ce_len = sizeof(BSR_SHORT);
            bsr_len = bsr_ce_len + bsr_header_len;
hbilel's avatar
hbilel committed
1699
        }
1700
    }
hbilel's avatar
hbilel committed
1701 1702


1703 1704
    UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
   }
hbilel's avatar
hbilel committed
1705 1706
 }

fnabet's avatar
fnabet committed
1707

1708

1709 1710 1711
  // Compute BSR Values and update Nb LCGID with data after multiplexing
  num_lcg_id_with_data = 0;
  lcg_id_bsr_trunc = 0;
hbilel's avatar
hbilel committed
1712 1713
  for (lcg_id=0;lcg_id<MAX_NUM_LCGID;lcg_id++){
      UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id] = locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]);
1714 1715 1716 1717 1718

      if  (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id]){
          num_lcg_id_with_data ++;
          lcg_id_bsr_trunc = lcg_id;
      }
1719
  }
hbilel's avatar
hbilel committed
1720

1721

GabrirelCouturier's avatar
GabrirelCouturier committed
1722 1723
  if (bsr_ce_len) {
      //Print updated BSR when sent
hbilel's avatar
hbilel committed
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
      LOG_D(MAC,"[UE %d] Remaining Buffer after Tx frame%d subframe %d nb LCG =%d Bytes for LCG0=%d LCG1=%d LCG2=%d LCG3=%d BSR Trigger status =%d TBS=%d\n",
                            module_idP,
                            frameP,
                            subframe,
                            num_lcg_id_with_data,
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[0],
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[1],
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[2],
                            UE_mac_inst[module_idP].scheduling_info.BSR_bytes[3],
                            UE_mac_inst[module_idP].BSR_reporting_active, buflen);

      LOG_D(MAC,"[UE %d] Frame %d Subframe %d TX BSR Regular or Periodic size=%d BSR0=%d BSR1=%d BSR2=%d BSR3=%d\n",module_idP,frameP,subframe,bsr_ce_len,
GabrirelCouturier's avatar
GabrirelCouturier committed
1736 1737 1738 1739
              UE_mac_inst[module_idP].scheduling_info.BSR[0],
              UE_mac_inst[module_idP].scheduling_info.BSR[1],
              UE_mac_inst[module_idP].scheduling_info.BSR[2],
              UE_mac_inst[module_idP].scheduling_info.BSR[3]);
1740 1741 1742
  }


1743
  // build PHR and update the timers
1744
  if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) {
1745 1746 1747 1748 1749 1750 1751 1752
	  if (nfapi_mode == 3){ //phy_stub mode
		  //Panos: Substitute with a static value for the MAC layer abstraction (phy_stub mode)
		  phr_p->PH = 40;
	  }
	  else { // Full stack mode
		  phr_p->PH = get_phr_mapping(module_idP,CC_id,eNB_index);
	  }

Raymond Knopp's avatar
 
Raymond Knopp committed
1753 1754
    phr_p->R  = 0;
    LOG_D(MAC,"[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n",
1755
          module_idP,frameP, get_PHR(module_idP,CC_id,eNB_index), phr_p->PH,POWER_HEADROOM);
Raymond Knopp's avatar
 
Raymond Knopp committed
1756
    update_phr(module_idP,CC_id);
1757
  } else {
1758
    phr_p=NULL;
1759
  }
1760

1761

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

1764

1765
  // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order
hbilel's avatar
hbilel committed
1766
  // Check for max padding size, ie MAC Hdr for last RLC PDU = 1
1767 1768 1769 1770 1771 1772
  /* For Padding BSR:
     -	if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader:
         -	if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission;
         -	else report Short BSR.
     -	else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR.
   */
hbilel's avatar
hbilel committed
1773
  if (sdu_length_total) {
1774
      padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1);
1775
  }
hbilel's avatar
hbilel committed
1776 1777 1778 1779
  else {
      padding_len = buflen - (bsr_len + phr_len);
  }

1780

1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836
   if ((padding_len) && (bsr_len == 0))
   {
	   /* if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR*/
     if (padding_len >= (1+BSR_LONG_SIZE))
     {
    	 bsr_ce_len = BSR_LONG_SIZE;
    	 bsr_header_len = 1;
         // Trigger BSR Padding
       UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING;


     } else if (padding_len >= (1+sizeof(BSR_SHORT))) {
    	 bsr_ce_len = sizeof(BSR_SHORT);
    	 bsr_header_len = 1;

    	 if (num_lcg_id_with_data > 1)
    	 {
    	  // REPORT TRUNCATED BSR
       	  //Get LCGID of highest priority LCID with data
    		 for (lcid=DCCH; lcid < MAX_NUM_LCID ; lcid++) {
    			 if (UE_mac_inst[module_idP].logicalChannelConfig[lcid] != NULL) {
        			 lcg_id = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];

        			 if ((lcg_id < MAX_NUM_LCGID) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcg_id])
        					 && (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)) {
        				 highest_priority = UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority;
        				 lcg_id_bsr_trunc = lcg_id;
        			 }
    			 }
    		 }
    	 }
    	 else
    	 {
    		 //Report SHORT BSR, clear bsr_t
    		 bsr_t = NULL;
    	 }

       // Trigger BSR Padding
       UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PADDING;
     }
 	 bsr_len = bsr_header_len + bsr_ce_len;
   }

   //Fill BSR Infos
   if (bsr_ce_len == 0 ) {
     bsr_s = NULL;
     bsr_l = NULL;
     bsr_t = NULL;
   } else if (bsr_ce_len == BSR_LONG_SIZE) {
     bsr_s = NULL;
     bsr_t = 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];

hbilel's avatar
hbilel committed
1837
     LOG_D(MAC, "[UE %d] Frame %d subframe %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,subframe,
1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
    	   UE_mac_inst[module_idP].BSR_reporting_active,
           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]);

   } else if (bsr_ce_len == sizeof(BSR_SHORT)) {
     bsr_l = NULL;
     if ((bsr_t != NULL) && (UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_PADDING)) {
    	 //Truncated BSR
    	 bsr_s = NULL;
    	 bsr_t->LCGID = lcg_id_bsr_trunc;
    	 bsr_t->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];

hbilel's avatar
hbilel committed
1852
         LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
hbilel's avatar
hbilel committed
1853
               module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
1854 1855 1856 1857 1858 1859 1860 1861

     }
     else
     {
    	 bsr_t = NULL;
         bsr_s->LCGID = lcg_id_bsr_trunc;
         bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];

hbilel's avatar
hbilel committed
1862
         LOG_D(MAC,"[UE %d] Frame %d subframe %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
hbilel's avatar
hbilel committed
1863
               module_idP, frameP, subframe, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
1864 1865 1866
     }
   }

hbilel's avatar
hbilel committed
1867 1868 1869
// 1-bit padding or 2-bit padding  special padding subheader
// Check for max padding size, ie MAC Hdr for last RLC PDU = 1
   if (sdu_length_total) {
1870
       padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - rlc_pdu_header_len_last + sdu_length_total + 1);
hbilel's avatar
hbilel committed
1871 1872 1873 1874 1875
   }
   else {
       padding_len = buflen - (bsr_len + phr_len);
   }

fnabet's avatar
fnabet committed
1876 1877 1878
  if (padding_len <= 2) {
    short_padding = padding_len;
    // only add padding header
1879
    post_padding = 0;
hbilel's avatar
hbilel committed
1880 1881
    //update total MAC Hdr size for RLC data
    if (sdu_length_total) {
1882
        total_rlc_pdu_header_len = total_rlc_pdu_header_len - rlc_pdu_header_len_last + 1;
hbilel's avatar
hbilel committed
1883
        rlc_pdu_header_len_last = 1;
1884
   }
hbilel's avatar
hbilel committed
1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896
  }
  else if (sdu_length_total) {
      post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
      // If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding
      if (post_padding == 0) {
          total_rlc_pdu_header_len -= rlc_pdu_header_len_last;
          padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
          short_padding = padding_len;
          total_rlc_pdu_header_len ++;
      }
  }
  else {
fnabet's avatar
fnabet committed
1897
    if (padding_len == buflen) {// nona mac pdu
1898 1899 1900 1901 1902
      *access_mode=CANCELED_ACCESS;
    }

    short_padding = 0;

hbilel's avatar
hbilel committed
1903
    post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
1904
  }
1905

1906 1907
  // Generate header
  // if (num_sdus>0) {
1908

1909
  payload_offset = generate_ulsch_header(ulsch_buffer,  // mac header
1910 1911 1912 1913 1914 1915
                                         num_sdus,      // num sdus
                                         short_padding,            // short pading
                                         sdu_lengths,  // sdu length
                                         sdu_lcids,    // sdu lcid
                                         phr_p,  // power headroom
                                         NULL,  // crnti
calvin wang's avatar
calvin wang committed
1916
                                         bsr_t,  // truncated bsr
1917 1918 1919 1920
                                         bsr_s, // short bsr
                                         bsr_l,
                                         post_padding); // long_bsr

1921
  LOG_D(MAC,
hbilel's avatar
hbilel committed
1922 1923
        "[UE %d] Generate header :bufflen %d  sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,  total_rlc_pdu_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, total_rlc_pdu_header_len,
1924
        short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset);
1925
  // cycle through SDUs and place in ulsch_buffer
hbilel's avatar
hbilel committed
1926 1927 1928
  if (sdu_length_total) {
      memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
  }
1929

1930
  // fill remainder of DLSCH with random data
1931 1932 1933 1934
  if (post_padding) {
      for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
        ulsch_buffer[payload_offset+sdu_length_total+j] = (char)(taus()&0xff);
      }
1935
  }
Cedric Roux's avatar
Cedric Roux committed
1936
  LOG_D(MAC,"[UE %d][SR] Gave SDU to PHY, clearing any scheduling request\n", module_idP);
1937 1938
  UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
  UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
1939 1940 1941 1942

  /* Actions when a BSR is sent */
  if (bsr_ce_len)
  {
hbilel's avatar
hbilel committed
1943 1944 1945
      LOG_D(MAC,"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n",
              module_idP, bsr_ce_len, bsr_header_len, buflen);

1946 1947 1948
	  // Reset ReTx BSR Timer
	  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);

Cedric Roux's avatar
Cedric Roux committed
1949
	  LOG_D(MAC,"[UE %d] MAC ReTx BSR Timer Reset =%d\n", module_idP,
1950 1951 1952
			  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF);

	  // Reset Periodic Timer except when BSR is truncated
Cedric Roux's avatar
Cedric Roux committed
1953
	  if ((bsr_t == NULL) && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer != PeriodicBSR_Timer_r12_infinity))
1954 1955 1956
	  {
		  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);

hbilel's avatar
hbilel committed
1957
		  LOG_D(MAC,"[UE %d] MAC Periodic BSR Timer Reset =%d\n",
Cedric Roux's avatar
Cedric Roux committed
1958
		        module_idP, UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF);
1959 1960 1961 1962 1963

	  }

	  // Reset BSR Trigger flags
	  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
calvin wang's avatar
calvin wang committed
1964
  }
1965

1966
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
1967
#if UE_TIMING_TRACE
1968
  stop_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
gabrielC's avatar
gabrielC committed
1969
#endif
1970

1971

navid's avatar
navid committed
1972
  if (opt_enabled) {
1973
    trace_pdu(0, ulsch_buffer, buflen, module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
Cedric Roux's avatar
Cedric Roux committed
1974
    LOG_D(OPT,"[UE %d][ULSCH] Frame %d subframe %d trace pdu for rnti %x  with size %d\n",
1975
          module_idP, frameP, subframe, UE_mac_inst[module_idP].crnti, buflen);
navid's avatar
navid committed
1976
  }
1977 1978
}

1979 1980


1981
//------------------------------------------------------------------------------
1982 1983 1984 1985 1986 1987 1988
// 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

1989 1990 1991
UE_L2_STATE_t
ue_scheduler(
  const module_id_t    module_idP,
1992 1993 1994 1995
  const frame_t        rxFrameP,
  const sub_frame_t    rxSubframeP,
  const frame_t        txFrameP,
  const sub_frame_t    txSubframeP,
1996 1997 1998 1999
  const lte_subframe_t directionP,
  const uint8_t        eNB_indexP,
  const int            CC_id)
//------------------------------------------------------------------------------
2000
{
2001 2002
  int lcid; // lcid index
  int TTI= 1;
winckel's avatar
winckel committed
2003 2004
  int bucketsizeduration = -1;
  int bucketsizeduration_max = -1;
2005
  // mac_rlc_status_resp_t rlc_status[MAX_NUM_LCGID]; // 4
2006
  // int8_t lcg_id;
2007
  struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL;
2008
  protocol_ctxt_t   ctxt;
GabrirelCouturier's avatar
GabrirelCouturier committed
2009

2010
#if defined(ENABLE_ITTI)
2011 2012 2013 2014
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
2015
#endif
gabrielC's avatar
gabrielC committed
2016
#if UE_TIMING_TRACE
2017
  start_meas(&UE_mac_inst[module_idP].ue_scheduler);
gabrielC's avatar
gabrielC committed
2018
#endif
2019
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_IN);
2020

2021
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_NO, UE_mac_inst[module_idP].crnti, txFrameP, txSubframeP,eNB_indexP);
2022 2023
#if defined(ENABLE_ITTI)

2024 2025 2026
  do {
    // Checks if a message has been sent to MAC sub-task
    itti_poll_msg (TASK_MAC_UE, &msg_p);
2027

2028 2029 2030
    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);
2031

2032 2033 2034 2035 2036
      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);
2037

2038 2039
        // TODO process CCCH data req.
        break;
2040 2041


2042 2043 2044
      default:
        LOG_E(MAC, "Received unexpected message %s\n", msg_name);
        break;
2045
      }
2046 2047 2048 2049

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

2052 2053
#endif

2054 2055
  //Mac_rlc_xface->frameP=frameP;
  //Rrc_xface->Frame_index=Mac_rlc_xface->frameP;
2056
  //if (subframe%5 == 0)
2057
  //LG#ifdef EXMIMO
2058
  pdcp_run(&ctxt);
2059
  //#endif
2060 2061 2062 2063
  UE_mac_inst[module_idP].txFrame    = txFrameP;
  UE_mac_inst[module_idP].txSubframe = txSubframeP;
  UE_mac_inst[module_idP].rxFrame    = rxFrameP;
  UE_mac_inst[module_idP].rxSubframe = rxSubframeP;
2064 2065

#ifdef CELLULAR
2066
  rrc_rx_tx(module_idP, txFrameP, 0, eNB_indexP);
2067
#else
2068

2069
  switch (rrc_rx_tx(&ctxt,
2070 2071
                    eNB_indexP,
                    CC_id)) {
2072 2073
  case RRC_OK:
    break;
2074

2075 2076
  case RRC_ConnSetup_failed:
    LOG_E(MAC,"RRCConnectionSetup failed, returning to IDLE state\n");
2077
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
2078
#if UE_TIMING_TRACE
2079
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
gabrielC's avatar
gabrielC committed
2080
#endif
2081 2082
    return(CONNECTION_LOST);
    break;
2083

2084 2085
  case RRC_PHY_RESYNCH:
    LOG_E(MAC,"RRC Loss of synch, returning PHY_RESYNCH\n");
2086
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
2087
#if UE_TIMING_TRACE
2088
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
gabrielC's avatar
gabrielC committed
2089
#endif
2090
    return(PHY_RESYNCH);
2091

2092
  case RRC_Handover_failed:
2093
    LOG_N(MAC,"Handover failure for UE %d eNB_index %d\n",module_idP,eNB_indexP);
2094
    //Invalid...need to add another MAC UE state for re-connection procedure
2095
    phy_config_afterHO_ue(module_idP,0,eNB_indexP,(MobilityControlInfo_t *)NULL,1);
2096 2097
    //return(3);
    break;
2098

2099 2100
  case RRC_HO_STARTED:
    LOG_I(MAC,"RRC handover, Instruct PHY to start the contention-free PRACH and synchronization\n");
2101
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
2102
#if UE_TIMING_TRACE
2103
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
gabrielC's avatar
gabrielC committed
2104
#endif
2105
    return(PHY_HO_PRACH);
2106

2107 2108 2109
  default:
    break;
  }
2110

2111
#endif
2112 2113

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

2116
    if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
2117
      rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon;
2118
    } else {
2119
      LOG_E(MAC,"FATAL: radioResourceConfigCommon is NULL!!!\n");
2120
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
2121

2122
      stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
2123
      AssertFatal(1==0,"");
2124

gabrielC's avatar
gabrielC committed
2125
#if UE_TIMING_TRACE
2126
      stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
gabrielC's avatar
gabrielC committed
2127
#endif
2128 2129
      //return(RRC_OK);
    }
2130

Cedric Roux's avatar
Cedric Roux committed
2131
    LOG_I(MAC,"Frame %d: Contention resolution timer %d/%ld\n",txFrameP,UE_mac_inst[module_idP].RA_contention_resolution_cnt,
2132 2133
          ((1+rach_ConfigCommon->ra_SupervisionInfo.mac_ContentionResolutionTimer)<<3));

2134 2135 2136 2137 2138 2139 2140 2141
    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);
2142
      ra_failed(module_idP,0,eNB_indexP);
2143
    }
2144 2145 2146
  }


2147
  // Get RLC status info and update Bj for all lcids that are active
fnabet's avatar
fnabet committed
2148
  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++ ) {
2149
    if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]) {
2150 2151 2152 2153 2154 2155 2156
      // 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);
2157
          AssertFatal(1==0,"");
2158 2159
        }

2160
        if ( UE_mac_inst[module_idP].scheduling_info.Bj[lcid] > bucketsizeduration_max ) {
2161
          UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = bucketsizeduration_max;
2162
        } else {
2163
          UE_mac_inst[module_idP].scheduling_info.Bj[lcid] = bucketsizeduration;
2164
        }
2165 2166
      }

2167

2168
      /*
2169 2170 2171
      if (lcid == DCCH) {
        LOG_D(MAC,"[UE %d][SR] Frame %d subframe %d Pending data for SRB1=%d for LCGID %d \n",
        module_idP, txFrameP,txSubframeP,UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
2172
//         UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]);
2173
      }
2174
      */
2175
    }
2176
  }
2177

2178
  // Call BSR procedure as described in Section 5.4.5 in 36.321
GabrirelCouturier's avatar
GabrirelCouturier committed
2179

2180 2181 2182 2183 2184 2185
  // First check ReTxBSR Timer because it is always configured
  // Decrement ReTxBSR Timer if it is running and not null
  if ((UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING)
          && (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF != 0)){
      UE_mac_inst[module_idP].scheduling_info.retxBSR_SF --;
  }
GabrirelCouturier's avatar
GabrirelCouturier committed
2186

2187 2188 2189 2190
  // Decrement Periodic Timer if it is running and not null
  if ((UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != MAC_UE_BSR_TIMER_NOT_RUNNING)
            && (UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF != 0)){
        UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF--;
2191
    }
GabrirelCouturier's avatar
GabrirelCouturier committed
2192

2193
  //Check whether Regular BSR is triggered
hbilel's avatar
hbilel committed
2194
  if (update_bsr(module_idP,txFrameP, txSubframeP,eNB_indexP) == TRUE) {
2195 2196 2197 2198 2199 2200
  // 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
    UE_mac_inst[module_idP].scheduling_info.SR_pending= 1;
    // Regular BSR trigger
    UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_REGULAR;
    LOG_D(MAC,"[UE %d][BSR] Regular BSR Triggered Frame %d subframe %d SR for PUSCH is pending\n",
hbilel's avatar
hbilel committed
2201
          module_idP, txFrameP,txSubframeP);
2202
  }
2203

2204
  // UE has no valid phy config dedicated ||  no valid/released  SR
2205
  if ((UE_mac_inst[module_idP].physicalConfigDedicated == NULL)) {
2206 2207 2208 2209
    // 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);
2210
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
2211
#if UE_TIMING_TRACE
2212
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
gabrielC's avatar
gabrielC committed
2213
#endif
2214
    return(CONNECTION_OK);
2215 2216
  }

2217
  if ((UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig == NULL) ||
2218
      (UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->present == SchedulingRequestConfig_PR_release)) {
2219

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

2222 2223 2224 2225
    // 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);
2226 2227 2228
  }

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

2232 2233 2234 2235 2236 2237
    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) &&
2238
          ((get_PL(module_idP,0,eNB_indexP) <  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db) ||
2239 2240
           (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
2241
      {
2242
        UE_mac_inst[module_idP].PHR_reporting_active = 1;
2243
      } else if (UE_mac_inst[module_idP].PHR_reporting_active ==0 ) {
2244
        UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF--;
2245
      }
2246

2247
      if (UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF <= 0 )
2248
        // trigger PHR and reset the timer later when the PHR report is sent
2249
      {
2250
        UE_mac_inst[module_idP].PHR_reporting_active = 1;
2251
      } else if (UE_mac_inst[module_idP].PHR_reporting_active == 0 ) {
2252
        UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF--;
2253
      }
2254
    }
2255
  } else {    // release / nothing
2256
    UE_mac_inst[module_idP].PHR_reporting_active = 0; // release PHR
2257
  }
2258

2259
  //If the UE has UL resources allocated for new transmission for this TTI here:
2260
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SCHEDULER, VCD_FUNCTION_OUT);
gabrielC's avatar
gabrielC committed
2261 2262 2263
#if UE_TIMING_TRACE
    stop_meas(&UE_mac_inst[module_idP].ue_scheduler);
#endif
2264 2265 2266 2267 2268
  return(CONNECTION_OK);
}

// to be improved
#ifdef CBA
2269
extern int cba_backoff;
2270 2271
double uniform_rngen(int min, int max)
{
2272 2273 2274 2275
  double random = (double)taus()/((double)0xffffffff);
  return (max - min) * random + min;
}

2276 2277
int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen)
{
2278

2279 2280 2281 2282
  mac_rlc_status_resp_t rlc_status;
  int header_offset=4;
  int rv =0;

2283
  /*
2284 2285 2286 2287 2288
  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
2289
      //  LOG_D(MAC,"[UE %d] Frame %d Subframe %d: the current CBA backoff is %d \n", module_idP, frameP, subframe,
2290 2291
      //  UE_mac_inst[module_idP].cba_last_access[0] );

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

2296
      rv=1;
2297 2298 2299 2300 2301 2302 2303 2304
  } 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",
2305
          module_idP, frameP, subframe,
2306 2307
          UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);

2308 2309 2310 2311
  } 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) ){
2312
    UE_mac_inst[module_idP].cba_last_access[0]-=1;
2313
    }*/
2314

2315
  if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0]<64) ) {
2316
    return 0;
2317
  }
2318

2319 2320
  if ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1] <= 0 ) &&
      (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2] <= 0 ) &&
2321
      (UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3] <= 0 ) ) {
2322
    return 0;
2323
  }
2324

2325
  if (cba_backoff == 0 ) { // apply probablisitc method
2326
    UE_mac_inst[module_idP].cba_last_access[0]= uniform_rngen(0,1);
2327 2328

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

2332 2333
      rv=1;
    }
2334 2335
  } else {

2336 2337
    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));
2338

2339
      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,
2340 2341 2342 2343
            UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active);

      rv = 1;
      /*
2344
      rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358
      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);
2359 2360 2361 2362
      */
    } 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",
2363 2364 2365
            module_idP, frameP, subframe,
            UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);
    }
2366
  }
2367

2368 2369 2370
  return rv;
  /*
    if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]>0)&&(UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]<64))   ||
2371 2372 2373 2374 2375
    ((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) ) {

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

2378
      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,
2379 2380 2381 2382
      UE_mac_inst[module_idP].cba_last_access[0], cba_backoff,UE_mac_inst[module_idP].ul_active);

      rv = 1;

2383
    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, // eNB_index
2384 2385 2386
            DTCH,
            0);

2387
    if ((
2388 2389 2390 2391 2392
   // (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 )
   )){
2393
      rv = 1;
2394

2395 2396
      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,
2397 2398
      UE_mac_inst[module_idP].cba_last_access[0], UE_mac_inst[module_idP].ul_active);
    } else
2399
      UE_mac_inst[module_idP].cba_last_access[0]= round(uniform_rngen(1,5));
2400

2401 2402

    } else if (( ((UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1]> 0 ))   ||
2403 2404 2405 2406
     ((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) )
2407
      {
2408 2409 2410 2411 2412

  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);
2413 2414
      }
  }
2415 2416
  */

2417 2418 2419 2420
}
#endif


2421
boolean_t  update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP,eNB_index_t eNB_index)
2422
{
2423 2424

  mac_rlc_status_resp_t rlc_status;
2425 2426 2427 2428 2429
  boolean_t bsr_regular_triggered = FALSE;
  uint8_t lcid;
  uint8_t lcgid;
  uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined
  uint16_t lcgid_buffer_remain[MAX_NUM_LCGID] = {0,0,0,0};
2430
  int32_t lcid_bytes_in_buffer[MAX_NUM_LCID];
2431 2432 2433 2434 2435 2436 2437 2438
  /* Array for ordering LCID with data per decreasing priority order */
  uint8_t lcid_reordered_array[MAX_NUM_LCID]=
  {MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID,MAX_NUM_LCID};
  uint8_t pos_next = 0;
  uint8_t highest_priority = 16;
  uint8_t array_index = 0;

  // Reset All BSR Infos
hbilel's avatar
hbilel committed
2439
  lcid_bytes_in_buffer[0] = 0;
2440 2441 2442 2443 2444
  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
  {
	  // Reset transmission status
	  lcid_bytes_in_buffer[lcid] = 0;
	  UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid]=LCID_EMPTY;
2445
  }
2446

hbilel's avatar
hbilel committed
2447
  for (lcgid=0; lcgid < MAX_NUM_LCGID; lcgid++)
2448 2449 2450 2451
  {
	  // Reset Buffer Info
	  UE_mac_inst[module_idP].scheduling_info.BSR[lcgid]=0;
	  UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid]=0;
2452
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2453

2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466
  //Get Buffer Occupancy and fill lcid_reordered_array
  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
  {
	  if (UE_mac_inst[module_idP].logicalChannelConfig[lcid])
	  {
		  	lcgid = UE_mac_inst[module_idP].scheduling_info.LCGID[lcid];

		  	// Store already available data to transmit per Group
		  	if (lcgid < MAX_NUM_LCGID)
		  	{
			  	lcgid_buffer_remain[lcgid] += UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid];
		  	}

2467
		    rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
2468
		                                    lcid,
2469 2470 2471 2472 2473
		                                    0xFFFF //TBS is not used in RLC at this step, set a special value for debug
#ifdef Rel14
                                          ,0, 0
#endif
                                          );
2474 2475 2476 2477 2478

		    lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer;

		    if (rlc_status.bytes_in_buffer > 0)
		    {
hbilel's avatar
hbilel committed
2479 2480
		          LOG_D(MAC,"[UE %d] PDCCH Tick : LCID%d LCGID%d has data to transmit =%d bytes at frame %d subframe %d\n",
		                              module_idP, lcid,lcgid,rlc_status.bytes_in_buffer,frameP,subframeP);
2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511

		         UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_NOT_EMPTY;
		         //Update BSR_bytes and position in lcid_reordered_array only if Group is defined
		         if (lcgid < MAX_NUM_LCGID)
		         {
		        	 num_lcid_with_data ++;
			         // sum lcid buffer which has same lcgid
			         UE_mac_inst[module_idP].scheduling_info.BSR_bytes[lcgid] += rlc_status.bytes_in_buffer;

			         //Fill in the array
			         array_index = 0;
			         do
					{
			        	 if (UE_mac_inst[module_idP].logicalChannelConfig[lcid]->ul_SpecificParameters->priority <= highest_priority)
			        	 {
			        		 //Insert if priority is higher or equal (lower or equal in value)
			        		 for (pos_next=num_lcid_with_data-1; pos_next > array_index; pos_next--)
			        		 {
			        			 lcid_reordered_array[pos_next] = lcid_reordered_array[pos_next - 1];

			        		 }
			        		 lcid_reordered_array[array_index] = lcid;
			        		 break;

			        	 }
			        	 array_index ++;
					}
			         while ((array_index < num_lcid_with_data) && (array_index < MAX_NUM_LCID));
		         }
		    }
	  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2512

2513
  }
2514

2515 2516 2517
  // Check whether a regular BSR can be triggered according to the first cases in 36.321
  if (num_lcid_with_data)
  {
hbilel's avatar
hbilel committed
2518 2519 2520
          LOG_D(MAC,"[UE %d] PDCCH Tick at frame %d subframe %d: NumLCID with data=%d Reordered LCID0=%d LCID1=%d LCID2=%d\n",
                            module_idP, frameP, subframeP,num_lcid_with_data,lcid_reordered_array[0],lcid_reordered_array[1],lcid_reordered_array[2]);

2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534
	  for (array_index=0; array_index < num_lcid_with_data; array_index++)
	  {
		  lcid = lcid_reordered_array[array_index];
	      /* UL data, for a logical channel which belongs to a LCG, becomes available for transmission in the RLC entity
	         either the data belongs to a logical channel with higher priority than the priorities of the logical channels
	         which belong to any LCG and for which data is already available for transmission
	      */
		  if ((UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] == 0)
			/* or there is no data available for any of the logical channels which belong to a LCG */
			||(lcgid_buffer_remain[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)
			)
		  {
			  bsr_regular_triggered = TRUE;

hbilel's avatar
hbilel committed
2535 2536
		      LOG_D(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d subframe %d\n",
		                      module_idP, lcid,UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],frameP, subframeP);
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546

			  break;
		  }
	  }

	  // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission
	  if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF == 0)
	  {
		  bsr_regular_triggered = TRUE;

hbilel's avatar
hbilel committed
2547 2548 2549 2550
		  if ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_REGULAR) == 0) {
		        LOG_I(MAC,"[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d subframe %d\n",
		                          module_idP, frameP, subframeP);
		  }
2551 2552

	  }
2553
  }
2554

2555 2556 2557 2558
  //Store Buffer Occupancy in remain buffers for next TTI
  for (lcid=DCCH; lcid < MAX_NUM_LCID; lcid++)
  {
	  UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_bytes_in_buffer[lcid];
2559
  }
2560

2561
  return bsr_regular_triggered;
2562 2563
}

fnabet's avatar
fnabet committed
2564
uint8_t locate_BsrIndexByBufferSize (const uint32_t *table, int size, int value)
2565
{
2566

2567
  uint8_t ju, jm, jl;
2568 2569
  int ascend;

2570 2571 2572
  DevAssert( size > 0 );
  DevAssert( size <= 256 );

2573 2574 2575
  if (value == 0) {
    return 0;  //elseif (value > 150000) return 63;
  }
2576

2577 2578
  jl = 0;        // lower bound
  ju = size - 1; // upper bound
2579 2580 2581
  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,
2582 2583
    jm = (ju+jl) >> 1; //compute a midpoint,

2584
    if ((value >= table[jm]) == ascend) {
2585
      jl=jm; // replace the lower limit
2586
    } else {
2587
      ju=jm; //replace the upper limit
2588
    }
2589 2590

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

2593 2594 2595 2596 2597
  if (value == table[jl]) {
    return jl;
  } else                    {
    return jl+1;  //equally  ju
  }
2598 2599 2600

}

2601 2602
int get_sf_periodicBSRTimer(uint8_t sf_offset)
{
2603 2604

  switch (sf_offset) {
Cedric Roux's avatar
Cedric Roux committed
2605
  case PeriodicBSR_Timer_r12_sf5:
2606 2607
    return 5;
    break;
2608

Cedric Roux's avatar
Cedric Roux committed
2609
  case PeriodicBSR_Timer_r12_sf10:
2610 2611
    return 10;
    break;
2612

Cedric Roux's avatar
Cedric Roux committed
2613
  case PeriodicBSR_Timer_r12_sf16:
2614 2615
    return 16;
    break;
2616

Cedric Roux's avatar
Cedric Roux committed
2617
  case PeriodicBSR_Timer_r12_sf20:
2618 2619
    return 20;
    break;
2620

Cedric Roux's avatar
Cedric Roux committed
2621
  case PeriodicBSR_Timer_r12_sf32:
2622 2623
    return 32;
    break;
2624

Cedric Roux's avatar
Cedric Roux committed
2625
  case PeriodicBSR_Timer_r12_sf40:
2626 2627
    return 40;
    break;
2628

Cedric Roux's avatar
Cedric Roux committed
2629
  case PeriodicBSR_Timer_r12_sf64:
2630 2631
    return 64;
    break;
2632

Cedric Roux's avatar
Cedric Roux committed
2633
  case PeriodicBSR_Timer_r12_sf80:
2634 2635
    return 80;
    break;
2636

Cedric Roux's avatar
Cedric Roux committed
2637
  case PeriodicBSR_Timer_r12_sf128:
2638 2639
    return 128;
    break;
2640

Cedric Roux's avatar
Cedric Roux committed
2641
  case PeriodicBSR_Timer_r12_sf160:
2642 2643
    return 160;
    break;
2644

Cedric Roux's avatar
Cedric Roux committed
2645
  case PeriodicBSR_Timer_r12_sf320:
2646 2647
    return 320;
    break;
2648

Cedric Roux's avatar
Cedric Roux committed
2649
  case PeriodicBSR_Timer_r12_sf640:
2650 2651
    return 640;
    break;
2652

Cedric Roux's avatar
Cedric Roux committed
2653
  case PeriodicBSR_Timer_r12_sf1280:
2654 2655
    return 1280;
    break;
2656

Cedric Roux's avatar
Cedric Roux committed
2657
  case PeriodicBSR_Timer_r12_sf2560:
2658 2659
    return 2560;
    break;
2660

Cedric Roux's avatar
Cedric Roux committed
2661
  case PeriodicBSR_Timer_r12_infinity:
2662
  default:
calvin wang's avatar
calvin wang committed
2663
    return 0xFFFF;
2664 2665 2666 2667
    break;
  }
}

2668 2669
int get_sf_retxBSRTimer(uint8_t sf_offset)
{
2670 2671

  switch (sf_offset) {
Cedric Roux's avatar
Cedric Roux committed
2672
  case RetxBSR_Timer_r12_sf320:
2673 2674
    return 320;
    break;
2675

Cedric Roux's avatar
Cedric Roux committed
2676
  case RetxBSR_Timer_r12_sf640:
2677 2678
    return 640;
    break;
2679

Cedric Roux's avatar
Cedric Roux committed
2680
  case RetxBSR_Timer_r12_sf1280:
2681 2682
    return 1280;
    break;
2683

Cedric Roux's avatar
Cedric Roux committed
2684
  case RetxBSR_Timer_r12_sf2560:
2685 2686
    return 2560;
    break;
2687

Cedric Roux's avatar
Cedric Roux committed
2688
  case RetxBSR_Timer_r12_sf5120:
2689 2690
    return 5120;
    break;
2691

Cedric Roux's avatar
Cedric Roux committed
2692
  case RetxBSR_Timer_r12_sf10240:
2693 2694
    return 10240;
    break;
2695

2696 2697 2698 2699 2700
  default:
    return -1;
    break;
  }
}
2701 2702
int get_ms_bucketsizeduration(uint8_t bucketsizeduration)
{
2703 2704 2705 2706 2707

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

2709 2710 2711
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms100:
    return 100;
    break;
2712

2713 2714 2715
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms150:
    return 150;
    break;
2716

2717 2718 2719
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms300:
    return 300;
    break;
2720

2721 2722 2723
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms500:
    return 500;
    break;
2724

2725 2726 2727
  case LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms1000:
    return 1000;
    break;
2728

2729 2730 2731 2732 2733 2734
  default:
    return 0;
    break;
  }
}

2735 2736
void update_phr(module_id_t module_idP,int CC_id)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
2737

2738 2739
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
2740 2741 2742 2743 2744

  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);
2745
}
2746 2747
uint8_t get_phr_mapping (module_id_t module_idP, int CC_id, uint8_t eNB_index)
{
2748

2749 2750
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
2751

2752 2753
  //power headroom reporting range is from -23 ...+40 dB, as described in 36313
  //note: mac_xface->get_Po_NOMINAL_PUSCH(module_idP) is float
2754
  if (get_PHR(module_idP,CC_id,eNB_index) < -23) {
2755
    return 0;
2756
  } else if (get_PHR(module_idP,CC_id,eNB_index) >= 40) {
2757
    return 63;
2758
  } else { // -23 to 40
2759
    return  (uint8_t) get_PHR(module_idP,CC_id,eNB_index) + PHR_MAPPING_OFFSET;
2760

2761
  }
2762
}
2763 2764
int get_sf_perioidicPHR_Timer(uint8_t perioidicPHR_Timer)
{
2765 2766 2767 2768
  return (perioidicPHR_Timer+1)*10;
}


2769 2770
int get_sf_prohibitPHR_Timer(uint8_t prohibitPHR_Timer)
{
2771 2772 2773
  return (prohibitPHR_Timer)*10;
}

2774 2775 2776
int get_db_dl_PathlossChange(uint8_t dl_PathlossChange)
{
  switch (dl_PathlossChange) {
2777 2778 2779
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1:
    return 1;
    break;
2780

2781 2782 2783
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB3:
    return 3;
    break;
2784

2785 2786 2787
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB6:
    return 6;
    break;
2788

2789 2790 2791 2792 2793 2794
  case MAC_MainConfig__phr_Config__setup__dl_PathlossChange_infinity:
  default:
    return -1;
    break;
  }
}
2795 2796 2797 2798 2799 2800 2801 2802


SLSS_t *ue_get_slss(module_id_t Mod_id,int CC_id,frame_t frame_tx,sub_frame_t subframe_tx) {

  return((SLSS_t*)NULL);
}

SLDCH_t *ue_get_sldch(module_id_t Mod_id,int CC_id,frame_t frame_tx,sub_frame_t subframe_tx) {
2803

2804 2805
    UE_MAC_INST *ue = &UE_mac_inst[Mod_id];
    SLDCH_t *sldch = &UE_mac_inst[Mod_id].sldch;
2806 2807

    sldch->payload_length = mac_rrc_data_req(Mod_id,
2808 2809 2810 2811
            CC_id,
            frame_tx,
            SL_DISCOVERY,
            1,
2812
            (char*)(sldch->payload), //&UE_mac_inst[Mod_id].SL_Discovery[0].Tx_buffer.Payload[0],
2813 2814 2815 2816
            0,
            0, //eNB_indexP
            0);

2817

2818 2819 2820 2821
   if (sldch->payload_length >0 ) {
     LOG_I(MAC,"Got %d bytes from RRC for SLDCH @ %p\n",sldch->payload_length,sldch);
     return (sldch);
   }
2822
   else
2823

2824
   return((SLDCH_t*)NULL);
2825 2826 2827 2828 2829
}


SLSCH_t *ue_get_slsch(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframeP) {

2830 2831 2832 2833 2834
   mac_rlc_status_resp_t rlc_status, rlc_status_data;
   uint32_t absSF = (frameP*10)+subframeP;
   UE_MAC_INST *ue = &UE_mac_inst[module_idP];
   int rvtab[4] = {0,2,3,1};
   int sdu_length;
2835
   //uint8_t sl_lcids[2] = {3, 10}; //list of lcids for SL - hardcoded
2836 2837 2838 2839 2840 2841 2842 2843
   int i = 0;

   // Note: this is hard-coded for now for the default SL configuration (4 SF PSCCH, 36 SF PSSCH)
   SLSCH_t *slsch = &UE_mac_inst[module_idP].slsch;

   LOG_D(MAC,"Checking SLSCH for absSF %d\n",absSF);
   if ((absSF%40) == 0) { // fill PSCCH data later in first subframe of SL period
      ue->sltx_active = 0;
2844
/*
2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859
      for (i = 0; i < MAX_NUM_LCID; i++){
         if (ue->SL_LCID[i] > 0) {
            for (int j = 0; j < ue->numCommFlows; j++){
               if ((ue->sourceL2Id > 0) && (ue->destinationList[j] >0) ){
                  rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
                        ue->SL_LCID[i], 0xFFFF, ue->sourceL2Id, ue->destinationList[j]);
                  if (rlc_status.bytes_in_buffer > 2){
                     LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer\n",frameP,subframeP,rlc_status.bytes_in_buffer);
                     // Fill in group id for off-network communications
                     ue->sltx_active = 1;
                     //store LCID, destinationL2Id
                     ue->slsch_lcid =  ue->SL_LCID[i];
                     ue->destinationL2Id = ue->destinationList[j];
                     break;
                  }
2860
               }
2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875

               if ((ue->sourceL2Id > 0) && (ue->groupList[j] >0) ){
                  rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
                        ue->SL_LCID[i], 0xFFFF, ue->sourceL2Id, ue->groupList[j]);
                  if (rlc_status.bytes_in_buffer > 2){
                     LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer\n",frameP,subframeP,rlc_status.bytes_in_buffer);
                     // Fill in group id for off-network communications
                     ue->sltx_active = 1;
                     //store LCID, destinationL2Id
                     ue->slsch_lcid =  ue->SL_LCID[i];
                     ue->destinationL2Id = ue->groupList[j];
                     break;
                  }
               }

2876 2877 2878 2879
            }
         }
         if ( ue->sltx_active == 1) break;
      }
2880 2881 2882
      */
      for (i = 0; i < MAX_NUM_LCID; i++){
               if (ue->sl_info[i].LCID > 0) {
2883 2884
                 // for (int j = 0; j < ue->numCommFlows; j++){
                     if ((ue->sourceL2Id > 0) && (ue->sl_info[i].destinationL2Id >0) ){
2885
                        rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
2886
                              ue->sl_info[i].LCID, 0xFFFF, ue->sourceL2Id, ue->sl_info[i].destinationL2Id );
2887
                        if (rlc_status.bytes_in_buffer > 2){
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
2888 2889
                           LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer \n",frameP,subframeP,rlc_status.bytes_in_buffer);

2890 2891 2892 2893
                           // Fill in group id for off-network communications
                           ue->sltx_active = 1;
                           //store LCID, destinationL2Id
                           ue->slsch_lcid =  ue->sl_info[i].LCID;
2894
                           ue->destinationL2Id = ue->sl_info[i].destinationL2Id;
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
2895
                           LOG_I(MAC,"LCID %d, source L2ID  0x%08x, destinationL2Id: 0x%08x \n",ue->slsch_lcid, ue->sourceL2Id, ue->destinationL2Id);
2896 2897 2898 2899
                           break;
                        }
                     }

2900
                     if ((ue->sourceL2Id > 0) && (ue->sl_info[i].groupL2Id >0) ){
2901
                        rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
2902
                              ue->sl_info[i].LCID, 0xFFFF, ue->sourceL2Id, ue->sl_info[i].groupL2Id);
2903 2904 2905 2906 2907 2908
                        if (rlc_status.bytes_in_buffer > 2){
                           LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer\n",frameP,subframeP,rlc_status.bytes_in_buffer);
                           // Fill in group id for off-network communications
                           ue->sltx_active = 1;
                           //store LCID, destinationL2Id
                           ue->slsch_lcid =  ue->sl_info[i].LCID;
2909
                           ue->destinationL2Id = ue->sl_info[i].groupL2Id;
2910
                           LOG_I(MAC,"LCID %d, source L2ID  0x%08x, groupL2Id: 0x%08x \n",ue->slsch_lcid, ue->sourceL2Id, ue->destinationL2Id);
2911 2912 2913 2914
                           break;
                        }
                     }

2915
                 // }
2916 2917 2918
               }
               if ( ue->sltx_active == 1) break;
            }
2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989
   } // we're not in the SCCH period
   else if (((absSF & 3) == 0 ) &&
         (ue->sltx_active == 1)) { // every 4th subframe, check for new data from RLC
      // 10 PRBs, mcs 19
      int TBS = 4584/8;
      int req;


      if (TBS <= rlc_status.bytes_in_buffer) req = TBS;
      else req = rlc_status.bytes_in_buffer;

      if (req>0) {
         sdu_length = mac_rlc_data_req(module_idP,
               0x1234,
               0,
               frameP,
               ENB_FLAG_NO,
               MBMS_FLAG_NO,
               ue->slsch_lcid,
               req,
               (char*)(ue->slsch_pdu.payload + sizeof(SLSCH_SUBHEADER_24_Bit_DST_LONG))
#ifdef Rel14
               ,ue->sourceL2Id,
               ue->destinationL2Id
#endif
         );

         // Notes: 1. hard-coded to 24-bit destination format for now
         if (sdu_length > 0) {

            LOG_I(MAC,"SFN.SF %d.%d : got %d bytes from Sidelink buffer (%d requested)\n",frameP,subframeP,sdu_length,req);
            LOG_I(MAC,"sourceL2Id: 0x%08x \n",ue->sourceL2Id);
            LOG_I(MAC,"groupL2Id/destinationL2Id: 0x%08x \n",ue->destinationL2Id);

            slsch->payload = (unsigned char*)ue->slsch_pdu.payload;
            if (sdu_length < 128) {
               slsch->payload++;
               SLSCH_SUBHEADER_24_Bit_DST_SHORT *shorth= (SLSCH_SUBHEADER_24_Bit_DST_SHORT *)slsch->payload;
               shorth->F = 0;
               shorth->L = sdu_length;
               shorth->E = 0;
               shorth->LCID = ue->slsch_lcid;
               shorth->SRC07 = (ue->sourceL2Id>>16) & 0x000000ff;
               shorth->SRC815 = (ue->sourceL2Id>>8) & 0x000000ff;
               shorth->SRC1623 = ue->sourceL2Id & 0x000000ff;
               shorth->DST07 = (ue->destinationL2Id >>16) & 0x000000ff;
               shorth->DST815 = (ue->destinationL2Id >>8) & 0x000000ff;
               shorth->DST1623 = ue->destinationL2Id & 0x000000ff;
               shorth->V = 0x1;
            }
            else {
               SLSCH_SUBHEADER_24_Bit_DST_LONG *longh= (SLSCH_SUBHEADER_24_Bit_DST_LONG *)slsch->payload;
               longh->F = 1;
               longh->L_LSB = sdu_length&0xff;
               longh->L_MSB = (sdu_length>>8)&0x7f;
               longh->E = 0;
               longh->LCID = ue->slsch_lcid;
               longh->SRC07 = (ue->sourceL2Id >>16) & 0x000000ff;
               longh->SRC815 = (ue->sourceL2Id>>8) & 0x000000ff;
               longh->SRC1623 = ue->sourceL2Id & 0x000000ff;
               longh->DST07 = (ue->destinationL2Id >>16) & 0x000000ff;
               longh->DST815 = (ue->destinationL2Id>>8) & 0x000000ff;
               longh->DST1623 = ue->destinationL2Id & 0x000000ff;
               longh->V = 0x1;
            }
            slsch->rvidx = 0;
            slsch->payload_length = TBS;
            // fill in SLSCH configuration
            return(&ue->slsch);
         }
         else ue->sltx_active = 0;
2990 2991
      }

2992 2993 2994 2995 2996
   } else if ((absSF%40)>3 && ue->sltx_active == 1) { // handle retransmission of SDU
      LOG_I(MAC,"SFN.SF %d.%d : retransmission\n",frameP,subframeP);
      slsch->rvidx = rvtab[absSF&3];
      return(&ue->slsch);
   }
2997

2998 2999
  return(NULL);
}