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

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


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

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

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

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

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

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

gauthier's avatar
gauthier committed
38
 */
39

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

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

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

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

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

74 75
#include "assertions.h"

76 77 78 79 80 81 82
#define DEBUG_HEADER_PARSING 1
#define ENABLE_MAC_PAYLOAD_DEBUG

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

extern inline unsigned int taus(void);


gauthier's avatar
gauthier committed
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
gauthier's avatar
gauthier committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
  LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
  //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity;
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1;
  UE_mac_inst[module_idP].PHR_state = MAC_MainConfig__phr_Config_PR_setup;
  UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
  UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
  UE_mac_inst[module_idP].scheduling_info.ttiBundling=0;
  UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db =  get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange);
knopp's avatar
 
knopp committed
119
  
120
  for (i=0; i < MAX_NUM_LCID; i++){
knopp's avatar
 
knopp committed
121 122
    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;
gauthier's avatar
gauthier committed
123 124 125 126 127 128
      UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1;
      if (i < DTCH) // initilize all control channels lcgid to 0
        UE_mac_inst[module_idP].scheduling_info.LCGID[i]=0;
      else // initialize all the data channels lcgid to 1
        UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
      UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=0;
129
  }
130 131 132 133
#ifdef CBA
  for (i=0; i <NUM_MAX_CBA_GROUP;i++) 
    UE_mac_inst[module_idP].cba_last_access[i]= round(uniform_rngen(1,30));
#endif 
134 135
}

knopp's avatar
 
knopp committed
136

137
unsigned char *parse_header(unsigned char *mac_header,
knopp's avatar
 
knopp committed
138 139 140 141 142 143
			    unsigned char *num_ce,
			    unsigned char *num_sdu,
			    unsigned char *rx_ces,
			    unsigned char *rx_lcids,
			    unsigned short *rx_lengths,
			    unsigned short tb_length) {
144 145 146 147 148 149 150

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

  while (not_done==1) {

gauthier's avatar
gauthier committed
151 152 153
      if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
          //      printf("E=0\n");
          not_done = 0;
154
      }
gauthier's avatar
gauthier committed
155 156 157 158 159 160 161 162 163 164 165 166 167
      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;
              for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++)
                length -= rx_lengths[num_sdu_cnt];
          }
          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;
168
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
169
                  LOG_D(MAC,"[UE] parse long sdu, size %x \n",length);
170
#endif
gauthier's avatar
gauthier committed
171 172 173 174 175 176

              }  else {	//if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
                  length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
                  mac_header_ptr += 2;
              }
          }
177
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
178 179
          LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %d)\n",
              num_sdus,lcid,length,mac_header_ptr-mac_header);
180
#endif
gauthier's avatar
gauthier committed
181 182 183
          rx_lcids[num_sdus] = lcid;
          rx_lengths[num_sdus] = length;
          num_sdus++;
184
      }
gauthier's avatar
gauthier committed
185 186 187 188 189 190 191 192 193 194 195 196 197
      else {  // This is a control element subheader
          if (lcid == SHORT_PADDING) {
              mac_header_ptr++;
          }
          else {
              rx_ces[num_ces] = lcid;
              num_ces++;
              mac_header_ptr ++;
              if (lcid==TIMING_ADV_CMD)
                ce_len++;
              else if (lcid==UE_CONT_RES)
                ce_len+=6;
          }
198
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
199
          LOG_D(MAC,"[UE] ce %d lcid %d (offset now %d)\n",num_ces,lcid,mac_header_ptr-mac_header);
200
#endif
gauthier's avatar
gauthier committed
201
      }
202 203 204 205 206 207 208
  }
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
}

knopp's avatar
 
knopp committed
209
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) {
210 211 212

  // 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
gauthier's avatar
gauthier committed
213 214 215
  int MGRP       = 0; // measurement gap repetition period in ms
  int gapOffset  = -1;
  int T          = 0;
216

217
  DevCheck(module_idP < (int)NB_UE_INST, module_idP, NB_UE_INST, 0);
218

knopp's avatar
 
knopp committed
219 220 221
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
222
    return 0;
knopp's avatar
 
knopp committed
223 224
  }

225
  // determin the measurement gap
gauthier's avatar
gauthier committed
226 227 228 229 230 231 232 233 234 235 236 237
  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;
      //check the measurement gap and sr prohibit timer
238
      if ((subframe ==  gapOffset %10) && ((frameP %T) == (floor(gapOffset/10)))
nikaeinn's avatar
nikaeinn committed
239
          && (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running ==0)){
gauthier's avatar
gauthier committed
240 241 242
          UE_mac_inst[module_idP].scheduling_info.SR_pending=1;
          return(0);
      }
243
  }
244 245 246
  
  if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) && 
      (UE_mac_inst[module_idP].scheduling_info.SR_pending==1) &&
gauthier's avatar
gauthier committed
247 248 249
      (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER <
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)))
  ){
250 251 252 253 254 255
    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",
	  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);
    
gauthier's avatar
gauthier committed
256 257 258 259 260 261 262
      UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++;
      // 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;
      } else
        UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
263
      LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
264
          module_idP,rnti,frameP,subframe,
gauthier's avatar
gauthier committed
265 266 267 268 269 270 271
          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
272 273
  }
  else{
gauthier's avatar
gauthier committed
274 275 276 277 278 279
      // notify RRC to relase PUCCH/SRS
      // clear any configured dl/ul
      // initiate RA
      UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
      UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
      return(0);
280 281 282
  }
}

283
void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index) {
284 285 286 287 288 289

  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;

290
  start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
291 292 293 294 295 296
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);

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

#if defined(USER_MODE) && defined(OAI_EMU)
  if (oai_emulation.info.opt_enabled) {
gauthier's avatar
gauthier committed
297 298
      trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
          UE_mac_inst[module_idP].subframe, 0, 0);
299 300 301 302 303 304
  }
#endif

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

#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
305
  LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP,
306
      frameP,eNB_index,num_ce,num_sdu);
307 308 309 310 311 312
#endif

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
  LOG_T(MAC,"[eNB %d] First 32 bytes of DLSCH : \n");
  for (i=0;i<32;i++)
    LOG_T(MAC,"%x.",sdu[i]);
313
  LOG_T(MAC,"\n");
314 315 316
#endif

  for (i=0;i<num_ce;i++) {
gauthier's avatar
gauthier committed
317
      //    printf("ce %d : %d\n",i,rx_ces[i]);
318 319 320
      switch (rx_ces[i]) {
      case UE_CONT_RES:

gauthier's avatar
gauthier committed
321
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n",
322
            module_idP,frameP,payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4],payload_ptr[5]);
gauthier's avatar
gauthier committed
323 324 325 326 327 328 329 330 331 332
        if (UE_mac_inst[module_idP].RA_active == 1) {
            LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n");
            UE_mac_inst[module_idP].RA_active=0;
            // check if RA procedure has finished completely (no contention)
            tx_sdu = &UE_mac_inst[module_idP].CCCH_pdu.payload[3];
            //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits)
            // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or SCH_SUBHEADER_SHORT)
            for (i=0;i<6;i++)
              if (tx_sdu[i] != payload_ptr[i]) {
                  LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP);
knopp's avatar
 
knopp committed
333
                  mac_xface->ra_failed(module_idP,CC_id,eNB_index);
gauthier's avatar
gauthier committed
334 335 336 337 338 339
                  UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
                  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
                  return;
              }
            LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n");
            UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
knopp's avatar
 
knopp committed
340
            mac_xface->ra_succeeded(module_idP,CC_id,eNB_index);
gauthier's avatar
gauthier committed
341 342 343
        }
        payload_ptr+=6;
        break;
344 345
      case TIMING_ADV_CMD:
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
346
        LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]);
347
#endif
348
        mac_xface->process_timing_advance(module_idP,CC_id,payload_ptr[0]);
gauthier's avatar
gauthier committed
349 350
        payload_ptr++;
        break;
351 352
      case DRX_CMD:
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
353
        LOG_D(MAC,"[UE] CE %d : UE DRX :",i);
354
#endif
gauthier's avatar
gauthier committed
355 356
        payload_ptr++;
        break;
357 358 359 360
      }
  }
  for (i=0;i<num_sdu;i++) {
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
361
      LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
362
#endif
gauthier's avatar
gauthier committed
363 364
      if (rx_lcids[i] == CCCH) {

365
          LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n",module_idP,frameP, eNB_index, rx_lengths[i]);
366 367

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
gauthier's avatar
gauthier committed
368 369
          int j;
          for (j=0;j<rx_lengths[i];j++)
gauthier's avatar
gauthier committed
370
            LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]);
gauthier's avatar
gauthier committed
371
          LOG_T(MAC,"\n");
372
#endif
gauthier's avatar
gauthier committed
373
          mac_rrc_data_ind(module_idP,
374
              frameP,
gauthier's avatar
gauthier committed
375
              CCCH,
gauthier's avatar
gauthier committed
376
              (uint8_t *)payload_ptr,rx_lengths[i],0,eNB_index,0);
377

gauthier's avatar
gauthier committed
378 379
      }
      else if (rx_lcids[i] == DCCH) {
380
          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]);
gauthier's avatar
gauthier committed
381 382
          mac_rlc_data_ind(eNB_index,
              module_idP,
383
              frameP,
gauthier's avatar
gauthier committed
384 385
              ENB_FLAG_NO,
              MBMS_FLAG_NO,
gauthier's avatar
gauthier committed
386 387 388 389 390 391 392
              DCCH,
              (char *)payload_ptr,
              rx_lengths[i],
              1,
              NULL);
      }
      else if (rx_lcids[i] == DCCH1) {
393
          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]);
gauthier's avatar
gauthier committed
394 395
          mac_rlc_data_ind(eNB_index,
              module_idP,
396
              frameP,
gauthier's avatar
gauthier committed
397 398
              ENB_FLAG_NO,
              MBMS_FLAG_NO,
gauthier's avatar
gauthier committed
399 400 401 402 403 404 405
              DCCH1,
              (char *)payload_ptr,
              rx_lengths[i],
              1,
              NULL);
      }
      else if (rx_lcids[i] == DTCH) {
406
          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]);
407 408

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
gauthier's avatar
gauthier committed
409 410 411 412
          int j;
          for (j=0;j<rx_lengths[i];j++)
            LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]);
          LOG_T(MAC,"\n");
413 414
#endif

gauthier's avatar
gauthier committed
415 416
          mac_rlc_data_ind(eNB_index,
              module_idP,
417
              frameP,
gauthier's avatar
gauthier committed
418 419
              ENB_FLAG_NO,
              MBMS_FLAG_NO,
gauthier's avatar
gauthier committed
420 421 422 423 424 425 426
              DTCH,
              (char *)payload_ptr,
              rx_lengths[i],
              1,
              NULL);
      }
      payload_ptr+= rx_lengths[i];
427 428
  }
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
429
  stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
430 431
}

knopp's avatar
 
knopp committed
432
void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len) {
433

434
  start_meas(&UE_mac_inst[module_idP].rx_si);
435 436
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);

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

gauthier's avatar
gauthier committed
439
  mac_rrc_data_ind(module_idP,
440
      frameP,
gauthier's avatar
gauthier committed
441
      BCCH,
gauthier's avatar
gauthier committed
442
      (uint8_t *)pdu,
gauthier's avatar
gauthier committed
443 444 445 446
      len,
      0,
      eNB_index,
      0);
447
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
448
  stop_meas(&UE_mac_inst[module_idP].rx_si);
449 450 451 452
}

#ifdef Rel10
unsigned char *parse_mch_header(unsigned char *mac_header,
knopp's avatar
 
knopp committed
453 454 455 456
				unsigned char *num_sdu,
				unsigned char *rx_lcids,
				unsigned short *rx_lengths,
				unsigned short tb_length) {
457 458 459
  unsigned char not_done=1, num_sdus=0, lcid, i;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length;
knopp's avatar
 
knopp committed
460
  
461
  while (not_done == 1) {
gauthier's avatar
gauthier committed
462 463
      if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
          not_done = 0;
464
      }
gauthier's avatar
gauthier committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
      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);
              for (i=0; i<num_sdus; i++)
                length -= rx_lengths[i];
          }
          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;
              }
          }
          rx_lcids[num_sdus] = lcid;
          rx_lengths[num_sdus] = length;
          num_sdus++;
      }
      else {// subheader for padding
          //     if (lcid == SHORT_PADDING)
          mac_header_ptr++;
491 492 493 494 495 496 497
      }
  }
  *num_sdu = num_sdus;
  return(mac_header_ptr);
}

// this function is for sending mch_sdu from phy to mac
498
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) {
499 500

  unsigned char num_sdu, i, *payload_ptr;
501
  unsigned char rx_lcids[NB_RB_MAX];
502 503
  unsigned short rx_lengths[NB_RB_MAX];

504
  start_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
505
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN);
506

507
  LOG_D(MAC,"[UE %d] Frame %d : process the mch PDU for sync area %d \n",module_idP,frameP, sync_area);
gauthier's avatar
gauthier committed
508 509
  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);
510 511

  payload_ptr = parse_mch_header(sdu, &num_sdu, rx_lcids, rx_lengths, sdu_len);
gauthier's avatar
gauthier committed
512
  LOG_D(MAC,"[UE %d] parse_mch_header, found %d sdus\n",module_idP,num_sdu);
513 514

  for (i=0; i<num_sdu; i++) {
gauthier's avatar
gauthier committed
515 516
      if (rx_lcids[i] == MCH_SCHDL_INFO) {
          if (UE_mac_inst[module_idP].mcch_status==1) {
517
              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]);
gauthier's avatar
gauthier committed
518 519 520 521 522
              // ??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;
          }
523
      }
gauthier's avatar
gauthier committed
524
      else if (rx_lcids[i] == MCCH_LCHANID) {
525
          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]);
gauthier's avatar
gauthier committed
526
          mac_rrc_data_ind(module_idP,
527
              frameP,
gauthier's avatar
gauthier committed
528 529
              MCCH,
              payload_ptr, rx_lengths[i], 0, eNB_index, sync_area);
530
      }
gauthier's avatar
gauthier committed
531 532
      else if (rx_lcids[i] == MTCH) {
          if (UE_mac_inst[module_idP].msi_status==1) {
533
              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]);
gauthier's avatar
gauthier committed
534 535

              mac_rlc_data_ind(
536
                  0,
gauthier's avatar
gauthier committed
537
                  module_idP,
538
                  frameP,
gauthier's avatar
gauthier committed
539 540
                  ENB_FLAG_NO,
                  MBMS_FLAG_YES,
541
                  MTCH, /*+ (maxDRB + 3),*/
gauthier's avatar
gauthier committed
542 543 544 545 546 547 548
                  (char *)payload_ptr,
                  rx_lengths[i],
                  1,
                  NULL);

          }
      } else {
549 550 551 552 553 554
          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],
gauthier's avatar
gauthier committed
555 556 557 558
              UE_mac_inst[module_idP].mcch_status, eNB_index);
      }

      payload_ptr += rx_lengths[i];
559 560
  }

561
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT);
562
  stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
563 564
}

gauthier's avatar
gauthier committed
565
int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index){
gauthier's avatar
gauthier committed
566
  // currently there is one-to-one mapping between sf allocation pattern and sync area
567
  if (mbsfn_sync_area > MAX_MBSFN_AREA){
gauthier's avatar
gauthier committed
568 569
      LOG_W(MAC,"[UE %d] MBSFN synchronization area %d out of range for eNB %d\n ", module_idP, mbsfn_sync_area, eNB_index);
      return -1;
570
  }
gauthier's avatar
gauthier committed
571
  else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL)
572
    return mbsfn_sync_area;
573
  else {
gauthier's avatar
gauthier committed
574 575
      LOG_W(MAC,"[UE %d] MBSFN Subframe Config pattern %d not found \n ", module_idP, mbsfn_sync_area);
      return -1;
576 577
  }
}
578

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

winckel's avatar
winckel committed
581
  int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1;
582
  int mcch_flag=0, mtch_flag=0, msi_flag=0;
gauthier's avatar
gauthier committed
583 584
  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
585
  int mch_scheduling_period = -1;
586 587 588

  start_meas(&UE_mac_inst[module_idP].ue_query_mch);

gauthier's avatar
gauthier committed
589 590
  if (UE_mac_inst[module_idP].pmch_Config[0])
    mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9);
591

592
  for (i=0;
gauthier's avatar
gauthier committed
593 594 595 596 597 598 599 600 601 602 603
      i< UE_mac_inst[module_idP].num_active_mbsfn_area;
      i++ ){
      // assume, that there is always a mapping
      if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1)
        return -1; // continue;
      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);

      LOG_D(MAC,"[UE %d] Frame %d subframe %d: Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d,mac sched period (%d,%d))\n",
604
          module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area,
gauthier's avatar
gauthier committed
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
          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);

      // 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;
622
      }
gauthier's avatar
gauthier committed
623

624 625
      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
gauthier's avatar
gauthier committed
626 627 628

              if (UE_mac_inst[module_idP].pmch_Config[0]) {
                  //  Find the first subframe in this MCH to transmit MSI
629
                  if (frameP % mch_scheduling_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) {
gauthier's avatar
gauthier committed
630 631 632 633 634 635 636 637 638 639 640 641 642 643
                      while (ii == 0) {
                          ii = UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos);
                          msi_pos++;
                      }
                  }
              }

              // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
              switch (subframe) {
              case 1:
                if (mac_xface->lte_frame_parms->frame_type == FDD) {
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) {
                        if (msi_pos == 1)
                          msi_flag = 1;
644
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
645 646 647 648 649 650 651 652 653 654 655 656
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 2:
                if (mac_xface->lte_frame_parms->frame_type == FDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) {
                        if (msi_pos == 2)
                          msi_flag = 1;
657
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
658 659 660 661 662 663 664 665 666 667 668 669
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 3:
                if (mac_xface->lte_frame_parms->frame_type == TDD){// TDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) {
                        if (msi_pos == 1)
                          msi_flag = 1;
670
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
671 672 673 674 675 676 677 678 679
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) )
                          mcch_flag = 1;
                        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) {
                        if (msi_pos == 3)
                          msi_flag = 1;
680
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
681 682 683 684 685 686 687 688 689 690 691 692
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 4:
                if (mac_xface->lte_frame_parms->frame_type == TDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) {
                        if (msi_pos == 2)
                          msi_flag = 1;
693
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
694 695 696 697 698 699 700 701 702 703 704 705
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 6:
                if (mac_xface->lte_frame_parms->frame_type == FDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) {
                        if (msi_pos == 4)
                          msi_flag = 1;
706
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
707 708 709 710 711 712 713 714 715 716 717 718
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 7:
                if (mac_xface->lte_frame_parms->frame_type == TDD){ // TDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) {
                        if (msi_pos == 3)
                          msi_flag = 1;
719
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
720 721 722 723 724 725 726 727 728
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) )
                          mcch_flag = 1;
                        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) {
                        if (msi_pos == 5)
                          msi_flag = 1;
729
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
730 731 732 733 734 735 736 737 738 739 740 741
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 8:
                if (mac_xface->lte_frame_parms->frame_type == TDD){ //TDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) {
                        if (msi_pos == 4)
                          msi_flag = 1;
742
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
743 744 745 746 747 748 749 750 751
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) )
                          mcch_flag = 1;
                        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) {
                        if (msi_pos == 6)
                          msi_flag = 1;
752
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
753 754 755 756 757 758 759 760 761 762 763 764
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 9:
                if (mac_xface->lte_frame_parms->frame_type == TDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) {
                        if (msi_pos == 5)
                          msi_flag = 1;
765
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
766 767 768 769 770 771 772 773 774 775
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) )
                          mcch_flag = 1;
                        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",
776
                      module_idP, frameP, subframe,i,j,msi_flag,mcch_flag,mtch_flag);
gauthier's avatar
gauthier committed
777 778 779 780 781

                  *sync_area=i;
                  break;
              }
          }
782
          else {// four-frameP format
gauthier's avatar
gauthier committed
783
          }
784 785
      }
  } // end of for
gauthier's avatar
gauthier committed
786

787
  stop_meas(&UE_mac_inst[module_idP].ue_query_mch);
788

789 790 791
  if ( (mcch_flag==1))// || (msi_flag==1))
    *mcch_active=1;

gauthier's avatar
gauthier committed
792 793 794 795
  if ( (mcch_flag==1) || ((msi_flag==1) && (UE_mac_inst[module_idP].mcch_status==1)) ){
      return mcch_mcs;
  } else if ((mtch_flag==1) && (UE_mac_inst[module_idP].msi_status==1))
    return UE_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9;
796
  else
797 798 799 800 801
    return -1;
}

#endif

gauthier's avatar
gauthier committed
802
unsigned char generate_ulsch_header(uint8_t *mac_header,
knopp's avatar
 
knopp committed
803 804 805 806 807 808 809 810 811 812
				    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) {
813 814 815 816 817 818 819 820 821 822 823 824 825 826

  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
  for (i=0;i<num_sdus;i++)
    LOG_T(MAC,"[UE] sdu %d : lcid %d length %d",i,sdu_lcids[i],sdu_lengths[i]);
  LOG_T(MAC,"\n");
#endif
  ce_ptr = &mac_header_control_elements[0];

  if ((short_padding == 1) || (short_padding == 2)) {
gauthier's avatar
gauthier committed
827 828 829 830 831
      mac_header_ptr->R    = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = SHORT_PADDING;
      first_element=1;
      last_size=1;
832 833
  }
  if (short_padding == 2) {
gauthier's avatar
gauthier committed
834 835 836 837 838 839
      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;
840 841 842
  }

  if (power_headroom) {
gauthier's avatar
gauthier committed
843 844 845 846 847 848 849 850 851 852 853 854 855 856
      if (first_element>0) {
          mac_header_ptr->E = 1;
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = POWER_HEADROOM;
      last_size=1;
      *((POWER_HEADROOM_CMD *)ce_ptr)=(*power_headroom);
      ce_ptr+=sizeof(POWER_HEADROOM_CMD);
      LOG_D(MAC, "phr header size %d\n",sizeof(POWER_HEADROOM_CMD));
857 858 859 860
  }

  if (crnti) {
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
861
      LOG_D(MAC,"[UE] CRNTI : %x (first_element %d)\n",*crnti,first_element);
862
#endif
gauthier's avatar
gauthier committed
863 864 865 866 867 868 869 870 871 872 873
      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;
gauthier's avatar
gauthier committed
874 875
      *((uint16_t *)ce_ptr)=(*crnti);
      ce_ptr+=sizeof(uint16_t);
gauthier's avatar
gauthier committed
876
      //    printf("offset %d\n",ce_ptr-mac_header_control_elements);
877 878 879
  }

  if (truncated_bsr) {
gauthier's avatar
gauthier committed
880 881 882
      if (first_element>0) {
          mac_header_ptr->E = 1;
          /*
883 884 885 886
      printf("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);
gauthier's avatar
gauthier committed
887 888 889 890 891 892
           */
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
893
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
894
      LOG_D(MAC,"[UE] Scheduler Truncated BSR Header\n");
895
#endif
gauthier's avatar
gauthier committed
896 897 898 899 900 901 902 903
      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);
904 905
  }
  else if (short_bsr) {
gauthier's avatar
gauthier committed
906 907 908
      if (first_element>0) {
          mac_header_ptr->E = 1;
          /*
909 910 911 912
      printf("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);
gauthier's avatar
gauthier committed
913 914 915 916 917 918
           */
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
919
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
920
      LOG_D(MAC,"[UE] Scheduler SHORT BSR Header\n");
921
#endif
gauthier's avatar
gauthier committed
922 923 924 925 926 927 928 929
      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);
930 931
  }
  else if (long_bsr) {
gauthier's avatar
gauthier committed
932 933 934
      if (first_element>0) {
          mac_header_ptr->E = 1;
          /*
935 936 937 938
      printf("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);
gauthier's avatar
gauthier committed
939 940 941 942 943 944
           */
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
945
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
946
      LOG_D(MAC,"[UE] Scheduler Long BSR Header\n");
947
#endif
gauthier's avatar
gauthier committed
948 949 950 951 952 953 954 955 956 957 958 959 960
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = LONG_BSR;
      last_size=1;

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

      //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
961 962 963 964 965
  }
  //  printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

  for (i=0;i<num_sdus;i++) {
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
966
      LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]);
967
#endif
gauthier's avatar
gauthier committed
968 969
      if ((first_element>0)) {
          mac_header_ptr->E = 1;
970
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
971 972 973 974
          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);
975
#endif
gauthier's avatar
gauthier committed
976 977 978 979 980
          mac_header_ptr+=last_size;
          //      printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
      }
      else {
          first_element=1;
981

gauthier's avatar
gauthier committed
982 983 984 985 986 987 988 989
      }
      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;
990
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
991 992
          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",
gauthier's avatar
gauthier committed
993
              ((uint16_t*)mac_header_ptr)[0],
gauthier's avatar
gauthier committed
994 995 996 997 998
              ((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);
999
#endif
gauthier's avatar
gauthier committed
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
      }
      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;
1010
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
1011
          LOG_D(MAC,"[UE] long sdu\n");
1012
#endif
gauthier's avatar
gauthier committed
1013
      }
1014 1015
  }
  if (post_padding>0) {// we have lots of padding at the end of the packet
gauthier's avatar
gauthier committed
1016 1017 1018 1019 1020 1021 1022
      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++;
1023 1024
  }
  else { // no end of packet padding
gauthier's avatar
gauthier committed
1025 1026 1027
      // 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 ++
1028
  }
gauthier's avatar
gauthier committed
1029

1030
  if ((ce_ptr-mac_header_control_elements) > 0) {
gauthier's avatar
gauthier committed
1031 1032
      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);
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
  }
#ifdef DEBUG_HEADER_PARSING
  LOG_T(MAC," [UE %d] header : ", crnti);
  for (i=0;i<((unsigned char*)mac_header_ptr - mac_header);i++)
    LOG_T(MAC,"%2x.",mac_header[i]);
  LOG_T(MAC,"\n");
#endif
  return((unsigned char*)mac_header_ptr - mac_header);

}

knopp's avatar
 
knopp committed
1044
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) {
1045 1046

  mac_rlc_status_resp_t rlc_status;
gauthier's avatar
gauthier committed
1047 1048
  uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0;
  uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0;
1049
  uint8_t bsr_header_len=0, bsr_ce_len=0, bsr_len=0;
gauthier's avatar
gauthier committed
1050 1051 1052 1053 1054 1055
  uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
  uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uint8_t sdu_lcids[8]    = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uint8_t payload_offset=0,num_sdus=0;
  uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
  uint16_t sdu_length_total=0;
1056 1057 1058 1059 1060 1061 1062
  BSR_SHORT bsr_short;
  BSR_LONG bsr_long;
  BSR_SHORT *bsr_s=&bsr_short;
  BSR_LONG  *bsr_l=&bsr_long;
  POWER_HEADROOM_CMD phr;
  POWER_HEADROOM_CMD *phr_p=&phr;
  unsigned short short_padding=0, post_padding=0;
Cedric Roux's avatar
Cedric Roux committed
1063
  int lcgid;
1064 1065 1066
  int j; // used for padding
  // Compute header length

knopp's avatar
 
knopp committed
1067 1068 1069 1070 1071 1072
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
    return;
  }

1073
  start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu);
1074
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_IN);
1075

Cedric Roux's avatar
Cedric Roux committed
1076
#ifdef CBA
1077
  if (*access_mode==CBA_ACCESS){
1078 1079
      LOG_D(MAC,"[UE %d] frameP %d subframe %d try CBA transmission\n",
          module_idP, frameP, subframe);
gauthier's avatar
gauthier committed
1080
      //if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DTCH] == LCID_EMPTY)
1081
      if (cba_access(module_idP,frameP,subframe,eNB_index,buflen)==0){
gauthier's avatar
gauthier committed
1082 1083 1084 1085
          *access_mode=POSTPONED_ACCESS;
          vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GET_SDU, VCD_FUNCTION_OUT);
          return;
      }
1086
      LOG_I(MAC,"[UE %d] frameP %d subframe %d CBA transmission oppurtunity, tbs %d\n",
1087
          module_idP, frameP, subframe,buflen);
1088 1089 1090 1091 1092 1093 1094 1095
  }
#endif
  dcch_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
  dcch1_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
  // hypo length,in case of long header skip the padding byte
  dtch_header_len=(buflen > 128 ) ? 3 : 2 ; //sizeof(SCH_SUBHEADER_LONG)-1 : sizeof(SCH_SUBHEADER_SHORT);
  bsr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
  phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
gauthier's avatar
gauthier committed
1096
  phr_ce_len