rrc_common.c 21.4 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

nikaeinn's avatar
nikaeinn committed
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

nikaeinn's avatar
nikaeinn committed
28
*******************************************************************************/
29 30

/*! \file rrc_common.c
31
 * \brief rrc common procedures for eNB and UE
nikaeinn's avatar
nikaeinn committed
32 33
 * \author Navid Nikaein and Raymond Knopp
 * \date 2011 - 2014
34 35
 * \version 1.0
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
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"
gauthier's avatar
gauthier committed
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

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

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

60 61
extern mui_t rrc_eNB_mui;

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

73 74 75
  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));
76 77 78 79 80 81
    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;
    }
82
  } else {
83 84
    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
85

86
    for (i = 0; i < NB_eNB_INST; i++) {
87 88 89 90 91 92 93
      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;
94 95 96 97
    }
  }
}

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

  //#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);
  /*
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
   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;
   }
   */
  rrc_rlc_register_rrc (rlcrrc_data_ind, NULL); //register with rlc

  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
147
  Rlc_info_um.rlc_mode = RLC_MODE_UM;
148 149 150
  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;
151 152
  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;

gauthier's avatar
gauthier committed
153
  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
154
  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
155 156 157 158 159
  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;
160
#ifndef NO_RRM
161

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

166 167 168 169 170 171
#endif

  return 0;
}

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

  int ret = 0;

#ifdef USER_MODE

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

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

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

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

#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);
206
  } else {
207 208 209 210 211 212 213 214 215
    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);
216
  } else {
217 218 219 220 221 222 223 224 225 226
    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRM2RRC_FIFO);
    rtf_reset(RRM2RRC_FIFO);
  }

  return(0);

#endif
}
#endif

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

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

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

gauthier's avatar
gauthier committed
252 253
  module_id_t         module_id;
  OAI_UECapability_t *UECap     = NULL;
254
  int                 CC_id;
255

256 257 258 259 260 261
  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);
262 263

    // fill UE capability
knopp's avatar
 
knopp committed
264
    UECap = fill_ue_capability (uecap_xer);
knopp's avatar
 
knopp committed
265

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

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

    for (module_id=0; module_id<NB_UE_INST; module_id++) {
gauthier's avatar
gauthier committed
276
      UE_rrc_inst[module_id].MBMS_flag = (uint8_t)eMBMS_active;
277
    }
278 279

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

284 285 286
  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));
287
    LOG_I(RRC,"[eNB] handover active state is %d \n", HO_active);
288 289

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
gauthier's avatar
gauthier committed
290
      eNB_rrc_inst[module_id].HO_flag   = (uint8_t)HO_active;
291
    }
292

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

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
297 298 299
      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;
      }
300
    }
301 302

#endif
303
#ifdef CBA
304 305

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
306 307 308
      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;
      }
309
    }
310

311 312 313 314 315
#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
316 317 318 319 320 321

    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;
322
    }
323

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

331 332 333 334 335 336 337 338 339 340
#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
341
  Data_to_read = 0;
342 343 344
#endif //USER_MODE
}

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

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

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

360
  }
361 362
}

363

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

373
  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State != RRC_CONNECTED) {
374
    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE\n");
375 376 377 378 379 380 381 382 383 384 385
    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,
386 387
                           SRB_FLAG_YES,
                           CONFIG_ACTION_REMOVE,
388
                           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
389
                           0);
390
      rrc_rlc_config_req (ctxt_pP,
391 392 393
                          SRB_FLAG_YES,
                          MBMS_FLAG_NO,
                          CONFIG_ACTION_REMOVE,
394
                          UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
395
                          Rlc_info_um);
396 397 398
      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;
399
    }
400
  } else { // Restablishment procedure
401
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
402 403
  }
}
Cedric Roux's avatar
Cedric Roux committed
404

405 406 407
//-----------------------------------------------------------------------------
RRC_status_t
rrc_rx_tx(
408
  protocol_ctxt_t* const ctxt_pP,
409 410 411 412
  const uint8_t      enb_indexP,
  const int          CC_id
)
//-----------------------------------------------------------------------------
413
{
414
  //uint8_t        UE_id;
415 416 417 418 419 420 421
  int32_t        current_timestamp_ms, ref_timestamp_ms;
  struct timeval ts;
#ifdef LOCALIZATION
  double                         estimated_distance;
  struct rrc_eNB_ue_context_s*   ue_context_p = NULL;
  protocol_ctxt_t                ctxt;
#endif
gauthier's avatar
gauthier committed
422
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
423

424
  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {
425
    // check timers
426

427 428
    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)
429
        LOG_D(RRC,
430
              "[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);
431

432 433 434
      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;
435
        // ALLOW CCCH to be used
436 437
        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
438
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
439
        return (RRC_ConnSetup_failed);
440
      }
441

442
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
443
    }
444

445
    if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
446 447
      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]) {
448
	LOG_I(RRC,"Activating T310\n");
449
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
450
      }
451
    } else { // in case we have not received SIB2 yet
452
      /*      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
453
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;
454 455 456 457

	}*/
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
      return RRC_OK;
458
    }
459

460 461 462 463 464
    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;
465
      }
466

467 468 469
      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);
      }
470

471 472 473
      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
474
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
475 476
	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n"); 
        return RRC_PHY_RESYNCH;
477
      }
478

479
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
480
    }
481

482 483 484 485
    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);
486

487 488 489
      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;
490 491
        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
492
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
493
        return(RRC_Handover_failed);
494
      }
495

496
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
497
    }
498

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

504
    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
505

506 507 508
    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);
    }
509

510 511 512
    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
513
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
514 515
      return(RRC_HO_STARTED);
    }
516

517
  } else { // eNB
518
    check_handovers(ctxt_pP);
519 520
    // counetr, and get the value and aggregate
#ifdef LOCALIZATION
521

522 523 524
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
525 526 527 528 529 530 531 532 533 534 535
    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) {
536
        LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
537 538
              ctxt.rnti,
              ctxt_pP->module_id,
539
              current_timestamp_ms,
540 541 542 543 544 545
              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;
546
      }
547
    }
548

549
#endif
550 551 552
    (void)ts; /* remove gcc warning "unused variable" */
    (void)ref_timestamp_ms; /* remove gcc warning "unused variable" */
    (void)current_timestamp_ms; /* remove gcc warning "unused variable" */
553
  }
554

gauthier's avatar
gauthier committed
555
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
556 557
  return (RRC_OK);
}
558

559 560 561 562 563 564 565 566
//-----------------------------------------------------------------------------
long
binary_search_int(
  int elements[],
  long numElem,
  int value
)
//-----------------------------------------------------------------------------
567
{
winckel's avatar
winckel committed
568
  long first, last, middle, search = -1;
569 570 571
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
572

573
  if(value < elements[0]) {
574
    return first;
575
  }
576

577
  if(value > elements[last]) {
578
    return last;
579
  }
580

581
  while (first <= last) {
582
    if (elements[middle] < value) {
583
      first = middle+1;
584
    } else if (elements[middle] == value) {
585 586
      search = middle+1;
      break;
587
    } else {
588
      last = middle -1;
589
    }
590

591 592
    middle = (first+last)/2;
  }
593

594
  if (first > last) {
595
    LOG_E(RRC,"Error in binary search!");
596
  }
597

598 599 600 601 602 603 604
  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
*/
605 606 607 608 609 610 611 612
//-----------------------------------------------------------------------------
long
binary_search_float(
  float elements[],
  long numElem,
  float value
)
//-----------------------------------------------------------------------------
613
{
winckel's avatar
winckel committed
614
  long first, last, middle;
615 616 617
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
618

619
  if(value <= elements[0]) {
620
    return first;
621
  }
622

623
  if(value >= elements[last]) {
624
    return last;
625
  }
626

627
  while (last - first > 1) {
628
    if (elements[middle] > value) {
629
      last = middle;
630
    } else {
631
      first = middle;
632
    }
633

634 635
    middle = (first+last)/2;
  }
636

637
  if (first < 0 || first >= numElem) {
638
    LOG_E(RRC,"\n Error in binary search float!");
639
  }
640

641 642 643
  return first;
}