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

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


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

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

21 22 23
  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

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

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

/*! \file rrc_common.c
31
 * \brief rrc common procedures for eNB and UE
32 33
 * \author Navid Nikaein and Raymond Knopp
 * \date 2011 - 2014
34 35
 * \version 1.0
 * \company Eurecom
36
 * \email:  navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
37
 */
38 39 40 41 42

#include "defs.h"
#include "extern.h"
#include "LAYER2/MAC/extern.h"
#include "COMMON/openair_defs.h"
43
#include "COMMON/platform_types.h"
44 45 46 47
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "LAYER2/RLC/rlc.h"
#include "COMMON/mac_rrc_primitives.h"
#include "UTIL/LOG/log.h"
48
#include "asn1_msg.h"
49
#include "pdcp.h"
50
#include "UTIL/LOG/vcd_signal_dumper.h"
51
#include "rrc_eNB_UE_context.h"
52

53
#ifdef LOCALIZATION
54 55 56
#include <sys/time.h>
#endif

57 58 59 60
#define DEBUG_RRC 1
extern eNB_MAC_INST *eNB_mac_inst;
extern UE_MAC_INST *UE_mac_inst;

61 62
extern mui_t rrc_eNB_mui;

63
//configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
64 65 66 67 68 69
//-----------------------------------------------------------------------------
void
openair_rrc_on(
  const protocol_ctxt_t* const ctxt_pP
)
//-----------------------------------------------------------------------------
70
{
71
  unsigned short i;
72
  int            CC_id;
73

74 75 76
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
77 78 79 80 81 82
    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
      rrc_config_buffer (&eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SI, BCCH, 1);
      eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].SI.Active = 1;
      rrc_config_buffer (&eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0, CCCH, 1);
      eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Active = 1;
    }
83
  } else {
84 85
    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
86

87
    for (i = 0; i < NB_eNB_INST; i++) {
88 89 90 91 92 93 94
      LOG_D(RRC, PROTOCOL_RRC_CTXT_FMT" Activating CCCH (eNB %d)\n",
            PROTOCOL_RRC_CTXT_ARGS(ctxt_pP), i);
      UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Srb_id = CCCH;
      memcpy (&UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Lchan_desc[0], &CCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
      memcpy (&UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Lchan_desc[1], &CCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
      rrc_config_buffer (&UE_rrc_inst[ctxt_pP->module_id].Srb0[i], CCCH, 1);
      UE_rrc_inst[ctxt_pP->module_id].Srb0[i].Active = 1;
95 96 97 98
    }
  }
}

99 100 101 102 103 104
//-----------------------------------------------------------------------------
int
rrc_init_global_param(
  void
)
//-----------------------------------------------------------------------------
105
{
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

  //#ifdef USER_MODE
  //  Rrc_xface = (RRC_XFACE*)malloc16(sizeof(RRC_XFACE));
  //#endif //USRE_MODE

  //  Rrc_xface->openair_rrc_top_init = openair_rrc_top_init;
  //  Rrc_xface->openair_rrc_eNB_init = openair_rrc_eNB_init;
  //  Rrc_xface->openair_rrc_UE_init  = openair_rrc_ue_init;
  //  Rrc_xface->mac_rrc_data_ind     = mac_rrc_data_ind;
  //Rrc_xface->mac_rrc_data_req     = mac_rrc_data_req;
  // Rrc_xface->rrc_data_indP        = (void *)rlcrrc_data_ind;
  //  Rrc_xface->rrc_rx_tx            = rrc_rx_tx;
  //  Rrc_xface->mac_rrc_meas_ind     = mac_rrc_meas_ind;
  //  Rrc_xface->get_rrc_status       = get_rrc_status;

  //Rrc_xface->rrc_get_status = ...

  //  Mac_rlc_xface->mac_out_of_sync_ind=mac_out_of_sync_ind;

#ifndef NO_RRM
  //  Rrc_xface->fn_rrc=fn_rrc;
#endif
  //  LOG_D(RRC, "[RRC]INIT_GLOBAL_PARAM: Mac_rlc_xface %p, rrc_rlc_register %p,rlcrrc_data_ind%p\n",Mac_rlc_xface,Mac_rlc_xface->rrc_rlc_register_rrc,rlcrrc_data_ind);
  /*
130 131 132 133 134 135
   if((Mac_rlc_xface==NULL) || (Mac_rlc_xface->rrc_rlc_register_rrc==NULL) ||
   (rlcrrc_data_ind==NULL)) {
   LOG_E(RRC,"Data structured is not initialized \n");
   return -1;
   }
   */
136
  rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc
137 138 139 140 141 142 143 144 145 146 147

  DCCH_LCHAN_DESC.transport_block_size = 4;
  DCCH_LCHAN_DESC.max_transport_blocks = 16;
  DCCH_LCHAN_DESC.Delay_class = 1;
  DTCH_DL_LCHAN_DESC.transport_block_size = 52;
  DTCH_DL_LCHAN_DESC.max_transport_blocks = 20;
  DTCH_DL_LCHAN_DESC.Delay_class = 1;
  DTCH_UL_LCHAN_DESC.transport_block_size = 52;
  DTCH_UL_LCHAN_DESC.max_transport_blocks = 20;
  DTCH_UL_LCHAN_DESC.Delay_class = 1;

gauthier's avatar
gauthier committed
148
  Rlc_info_um.rlc_mode = RLC_MODE_UM;
149 150 151
  Rlc_info_um.rlc.rlc_um_info.timer_reordering = 5;
  Rlc_info_um.rlc.rlc_um_info.sn_field_length = 10;
  Rlc_info_um.rlc.rlc_um_info.is_mXch = 0;
152 153
  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;

gauthier's avatar
gauthier committed
154
  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
155
  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
156 157 158 159 160
  Rlc_info_am_config.rlc.rlc_am_info.poll_pdu = 8;
  Rlc_info_am_config.rlc.rlc_am_info.poll_byte = 1000;
  Rlc_info_am_config.rlc.rlc_am_info.t_poll_retransmit = 15;
  Rlc_info_am_config.rlc.rlc_am_info.t_reordering = 50;
  Rlc_info_am_config.rlc.rlc_am_info.t_status_prohibit = 10;
161
#ifndef NO_RRM
162

163
  if (L3_xface_init ()) {
164
    return (-1);
165
  }
166

167 168 169 170 171 172
#endif

  return 0;
}

#ifndef NO_RRM
173 174 175 176 177 178
//-----------------------------------------------------------------------------
int
L3_xface_init(
  void
)
//-----------------------------------------------------------------------------
179
{
180 181 182 183 184

  int ret = 0;

#ifdef USER_MODE

185
  int sock;
186 187
  LOG_D(RRC, "[L3_XFACE] init de l'interface \n");

188
  if (open_socket (&S_rrc, RRC_RRM_SOCK_PATH, RRM_RRC_SOCK_PATH, 0) == -1) {
189
    return (-1);
190
  }
191

192 193 194
  if (S_rrc.s == -1) {
    return (-1);
  }
195

196 197 198
  socket_setnonblocking (S_rrc.s);
  msg ("Interface Connected... RRM-RRC\n");
  return 0;
199 200 201 202 203 204 205 206

#else

  ret=rtf_create(RRC2RRM_FIFO,32768);

  if (ret < 0) {
    msg("[openair][MAC][INIT] Cannot create RRC2RRM fifo %d (ERROR %d)\n",RRC2RRM_FIFO,ret);
    return(-1);
207
  } else {
208 209 210 211 212 213 214 215 216
    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRC2RRM_FIFO);
    rtf_reset(RRC2RRM_FIFO);
  }

  ret=rtf_create(RRM2RRC_FIFO,32768);

  if (ret < 0) {
    msg("[openair][MAC][INIT] Cannot create RRM2RRC fifo %d (ERROR %d)\n",RRM2RRC_FIFO,ret);
    return(-1);
217
  } else {
218 219 220 221 222 223 224 225 226 227
    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRM2RRC_FIFO);
    rtf_reset(RRM2RRC_FIFO);
  }

  return(0);

#endif
}
#endif

228 229 230 231 232 233 234 235
//-----------------------------------------------------------------------------
void
rrc_config_buffer(
  SRB_INFO* Srb_info,
  uint8_t Lchan_type,
  uint8_t Role
)
//-----------------------------------------------------------------------------
236
{
237 238 239 240 241 242

  Srb_info->Rx_buffer.payload_size = 0;
  Srb_info->Tx_buffer.payload_size = 0;
}

/*------------------------------------------------------------------------------*/
243 244 245 246 247 248 249 250
void
openair_rrc_top_init(
  int eMBMS_active,
  char* uecap_xer,
  uint8_t cba_group_active,
  uint8_t HO_active
)
//-----------------------------------------------------------------------------
251
{
252

253 254
  module_id_t         module_id;
  OAI_UECapability_t *UECap     = NULL;
255
  int                 CC_id;
256

257 258 259 260 261 262
  LOG_D(RRC, "[OPENAIR][INIT] Init function start: NB_UE_INST=%d, NB_eNB_INST=%d\n", NB_UE_INST, NB_eNB_INST);

  if (NB_UE_INST > 0) {
    UE_rrc_inst = (UE_RRC_INST*) malloc16(NB_UE_INST*sizeof(UE_RRC_INST));
    memset (UE_rrc_inst, 0, NB_UE_INST * sizeof(UE_RRC_INST));
    LOG_D(RRC, "ALLOCATE %d Bytes for UE_RRC_INST @ %p\n", (unsigned int)(NB_UE_INST*sizeof(UE_RRC_INST)), UE_rrc_inst);
263 264

    // fill UE capability
265
    UECap = fill_ue_capability (uecap_xer);
266

267
    for (module_id = 0; module_id < NB_UE_INST; module_id++) {
268
      UE_rrc_inst[module_id].UECap = UECap;
269 270
      UE_rrc_inst[module_id].UECapability = UECap->sdu;
      UE_rrc_inst[module_id].UECapability_size = UECap->sdu_size;
271
    }
272

273 274
#ifdef Rel10
    LOG_I(RRC,"[UE] eMBMS active state is %d \n", eMBMS_active);
275 276

    for (module_id=0; module_id<NB_UE_INST; module_id++) {
277
      UE_rrc_inst[module_id].MBMS_flag = (uint8_t)eMBMS_active;
278
    }
279 280

#endif
281
  } else {
282
    UE_rrc_inst = NULL;
283
  }
284

285 286 287
  if (NB_eNB_INST > 0) {
    eNB_rrc_inst = (eNB_RRC_INST*) malloc16(NB_eNB_INST*sizeof(eNB_RRC_INST));
    memset (eNB_rrc_inst, 0, NB_eNB_INST * sizeof(eNB_RRC_INST));
288
    LOG_I(RRC,"[eNB] handover active state is %d \n", HO_active);
289 290

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
291
      eNB_rrc_inst[module_id].HO_flag   = (uint8_t)HO_active;
292
    }
293

294
#ifdef Rel10
295
    LOG_I(RRC,"[eNB] eMBMS active state is %d \n", eMBMS_active);
296 297

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
298 299 300
      for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
        eNB_rrc_inst[module_id].carrier[CC_id].MBMS_flag = (uint8_t)eMBMS_active;
      }
301
    }
302 303

#endif
304
#ifdef CBA
305 306

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
307 308 309
      for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
        eNB_rrc_inst[module_id].carrier[CC_id].num_active_cba_groups = cba_group_active;
      }
310
    }
311

312 313 314 315 316
#endif
#ifdef LOCALIZATION
    /* later set this from xml or enb.config file*/
    struct timeval ts; // time struct
    gettimeofday(&ts, NULL); // get the current epoch timestamp
317 318 319 320 321 322

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
      eNB_rrc_inst[module_id].reference_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
      initialize(&eNB_rrc_inst[module_id].loc_list);
      eNB_rrc_inst[module_id].loc_type=0;
      eNB_rrc_inst[module_id].aggregation_period_ms = 5000;
323
    }
324

325
#endif
326 327
    LOG_D(RRC,
          "ALLOCATE %d Bytes for eNB_RRC_INST @ %p\n", (unsigned int)(NB_eNB_INST*sizeof(eNB_RRC_INST)), eNB_rrc_inst);
328
  } else {
329
    eNB_rrc_inst = NULL;
330
  }
331

332 333 334 335 336 337 338 339 340 341
#ifndef NO_RRM
#ifndef USER_MODE

  Header_buf=(char*)malloc16(sizeof(msg_head_t));
  Data=(char*)malloc16(2400);
  Header_read_idx=0;
  Data_read_idx=0;
  Header_size=sizeof(msg_head_t);

#endif //NO_RRM
342
  Data_to_read = 0;
343 344 345
#endif //USER_MODE
}

346 347 348 349 350 351
//-----------------------------------------------------------------------------
void
rrc_top_cleanup(
  void
)
//-----------------------------------------------------------------------------
352
{
353

354
  if (NB_UE_INST > 0) {
355
    free (UE_rrc_inst);
356
  }
357

358
  if (NB_eNB_INST > 0) {
359
    free (eNB_rrc_inst);
360

361
  }
362 363
}

364

365 366 367 368 369 370 371
//-----------------------------------------------------------------------------
void
rrc_t310_expiration(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                 eNB_index
)
//-----------------------------------------------------------------------------
372
{
373

374
  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State != RRC_CONNECTED) {
375
    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE\n");
376 377 378 379 380 381 382 383 384 385 386
    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_IDLE;
    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].UE_index = 0xffff;
    UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Rx_buffer.payload_size = 0;
    UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size = 0;
    UE_rrc_inst[ctxt_pP->module_id].Srb1[eNB_index].Srb_info.Rx_buffer.payload_size = 0;
    UE_rrc_inst[ctxt_pP->module_id].Srb1[eNB_index].Srb_info.Tx_buffer.payload_size = 0;

    if (UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Active == 1) {
      msg ("[RRC Inst %d] eNB_index %d, Remove RB %d\n ", ctxt_pP->module_id, eNB_index,
           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id);
      rrc_pdcp_config_req (ctxt_pP,
387 388
                           SRB_FLAG_YES,
                           CONFIG_ACTION_REMOVE,
389
                           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
390
                           0);
391
      rrc_rlc_config_req (ctxt_pP,
392 393 394
                          SRB_FLAG_YES,
                          MBMS_FLAG_NO,
                          CONFIG_ACTION_REMOVE,
395
                          UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
396
                          Rlc_info_um);
397 398 399
      UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Active = 0;
      UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Status = IDLE;
      UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Next_check_frame = 0;
400
    }
401
  } else { // Restablishment procedure
402
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
403 404
  }
}
405

406 407 408
//-----------------------------------------------------------------------------
RRC_status_t
rrc_rx_tx(
409
  protocol_ctxt_t* const ctxt_pP,
410 411 412 413
  const uint8_t      enb_indexP,
  const int          CC_id
)
//-----------------------------------------------------------------------------
414
{
415 416 417
  uint8_t        UE_id;
  int32_t        current_timestamp_ms, ref_timestamp_ms;
  struct timeval ts;
418 419
  struct rrc_eNB_ue_context_s   *ue_context_p = NULL,*ue_to_be_removed = NULL;

420 421 422 423
#ifdef LOCALIZATION
  double                         estimated_distance;
  protocol_ctxt_t                ctxt;
#endif
gauthier's avatar
gauthier committed
424
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
425

426
  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {
427
    // check timers
428

429 430
    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_active == 1) {
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt % 10) == 0)
431
        LOG_D(RRC,
432
              "[UE %d][RAPROC] Frame %d T300 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt);
433

434 435 436
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt
          == T300[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t300]) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_active = 0;
437
        // ALLOW CCCH to be used
438 439
        UE_rrc_inst[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
        rrc_ue_generate_RRCConnectionRequest (ctxt_pP, enb_indexP);
gauthier's avatar
gauthier committed
440
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
441
        return (RRC_ConnSetup_failed);
442
      }
443

444
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
445
    }
446

447
    if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
448 449
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt
          == N310[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n310]) {
450
	LOG_I(RRC,"Activating T310\n");
451
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
452
      }
453
    } else { // in case we have not received SIB2 yet
454
      /*      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
455
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;
456 457 458 459

	}*/
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
      return RRC_OK;
460
    }
461

462 463 464 465 466
    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active == 1) {
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N311_cnt
          == N311[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n311]) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N311_cnt = 0;
467
      }
468

469 470 471
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt % 10) == 0) {
        LOG_D(RRC, "[UE %d] Frame %d T310 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt);
      }
472

473 474 475
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt    == T310[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t310]) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
        rrc_t310_expiration (ctxt_pP, enb_indexP);
gauthier's avatar
gauthier committed
476
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
477 478
	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n"); 
        return RRC_PHY_RESYNCH;
479
      }
480

481
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
482
    }
483

484 485 486 487
    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_active==1) {
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt % 10) == 0)
        LOG_D(RRC,"[UE %d][RAPROC] Frame %d T304 Count %d ms\n",ctxt_pP->module_id,ctxt_pP->frame,
              UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt);
488

489 490 491
      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt == 0) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_active = 0;
        UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
492 493
        LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n");
        //Implement 36.331, section 5.3.5.6 here
gauthier's avatar
gauthier committed
494
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
495
        return(RRC_Handover_failed);
496
      }
497

498
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
499
    }
500

501
    // Layer 3 filtering of RRC measurements
502 503
    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0] != NULL) {
      ue_meas_filtering(ctxt_pP,enb_indexP);
504
    }
505

506
    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
507

508 509 510
    if (UE_rrc_inst[ctxt_pP->module_id].Info[0].handoverTarget > 0) {
      LOG_I(RRC,"[UE %d] Frame %d : RRC handover initiated\n", ctxt_pP->module_id, ctxt_pP->frame);
    }
511

512 513 514
    if((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State == RRC_HO_EXECUTION)   &&
        (UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId != 0xFF)) {
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State= RRC_IDLE;
gauthier's avatar
gauthier committed
515
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
516 517
      return(RRC_HO_STARTED);
    }
518

519
  } else { // eNB
520
    check_handovers(ctxt_pP);
521
    // counetr, and get the value and aggregate
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536

    // check for UL failure
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head)) {
      if (ue_context_p->ue_context.ul_failure_timer>0) {
	ue_context_p->ue_context.ul_failure_timer++;
	if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
	  // remove UE after 20 seconds after MAC has indicated UL failure
	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
	  ue_to_be_removed = ue_context_p;
	  break;
	}
      }
    }
    if (ue_to_be_removed)
      rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed);
537
#ifdef LOCALIZATION
538

539 540 541
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
542 543 544 545 546 547 548 549 550 551 552
    ref_timestamp_ms = eNB_rrc_inst[ctxt_pP->module_id].reference_timestamp_ms;
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head)) {
      ctxt = *ctxt_pP;
      ctxt.rnti = ue_context_p->ue_context.rnti;
      estimated_distance = rrc_get_estimated_ue_distance(
                             &ctxt,
                             CC_id,
                             eNB_rrc_inst[ctxt_pP->module_id].loc_type);

      if ((current_timestamp_ms - ref_timestamp_ms > eNB_rrc_inst[ctxt_pP->module_id].aggregation_period_ms) &&
          estimated_distance != -1) {
553
        LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
554 555
              ctxt.rnti,
              ctxt_pP->module_id,
556
              current_timestamp_ms,
557 558 559 560 561 562
              ctxt_pP->frame,
              estimated_distance);
        LOG_D(LOCALIZE, " RRC status %d\n", ue_context_p->ue_context.Status);
        push_front(&eNB_rrc_inst[ctxt_pP->module_id].loc_list,
                   estimated_distance);
        eNB_rrc_inst[ctxt_pP->module_id].reference_timestamp_ms = current_timestamp_ms;
563
      }
564
    }
565

566
#endif
567
  }
568

gauthier's avatar
gauthier committed
569
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
570 571
  return (RRC_OK);
}
572

573 574 575 576 577 578 579 580
//-----------------------------------------------------------------------------
long
binary_search_int(
  int elements[],
  long numElem,
  int value
)
//-----------------------------------------------------------------------------
581
{
winckel's avatar
winckel committed
582
  long first, last, middle, search = -1;
583 584 585
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
586

587
  if(value < elements[0]) {
588
    return first;
589
  }
590

591
  if(value > elements[last]) {
592
    return last;
593
  }
594

595
  while (first <= last) {
596
    if (elements[middle] < value) {
597
      first = middle+1;
598
    } else if (elements[middle] == value) {
599 600
      search = middle+1;
      break;
601
    } else {
602
      last = middle -1;
603
    }
604

605 606
    middle = (first+last)/2;
  }
607

608
  if (first > last) {
609
    LOG_E(RRC,"Error in binary search!");
610
  }
611

612 613 614 615 616 617 618
  return search;
}

/* This is a binary search routine which operates on an array of floating
   point numbers and returns the index of the range the value lies in
   Used for RSRP and RSRQ measurement mapping. Can potentially be used for other things
*/
619 620 621 622 623 624 625 626
//-----------------------------------------------------------------------------
long
binary_search_float(
  float elements[],
  long numElem,
  float value
)
//-----------------------------------------------------------------------------
627
{
winckel's avatar
winckel committed
628
  long first, last, middle;
629 630 631
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
632

633
  if(value <= elements[0]) {
634
    return first;
635
  }
636

637
  if(value >= elements[last]) {
638
    return last;
639
  }
640

641
  while (last - first > 1) {
642
    if (elements[middle] > value) {
643
      last = middle;
644
    } else {
645
      first = middle;
646
    }
647

648 649
    middle = (first+last)/2;
  }
650

651
  if (first < 0 || first >= numElem) {
652
    LOG_E(RRC,"\n Error in binary search float!");
653
  }
654

655 656 657
  return first;
}