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

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
   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;
   }
   */
135
  rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc
136 137 138 139 140 141 142 143 144 145 146

  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

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

266
    for (module_id = 0; module_id < NB_UE_INST; module_id++) {
267
      UE_rrc_inst[module_id].UECap = UECap;
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++) {
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++) {
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
  }
}
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 415 416
  uint8_t        UE_id;
  int32_t        current_timestamp_ms, ref_timestamp_ms;
  struct timeval ts;
417 418
  struct rrc_eNB_ue_context_s*   ue_context_p = NULL;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

505
    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
506

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

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

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

    // 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 == 1000) {
	  // remove UE after 1 second after MAC has indicated UL failure
	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
	  
	}
      }


    }
535
#ifdef LOCALIZATION
536

537 538 539
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
540 541 542 543 544 545 546 547 548 549 550
    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) {
551
        LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
552 553
              ctxt.rnti,
              ctxt_pP->module_id,
554
              current_timestamp_ms,
555 556 557 558 559 560
              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;
561
      }
562
    }
563

564
#endif
565
  }
566

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

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

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

589
  if(value > elements[last]) {
590
    return last;
591
  }
592

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

603 604
    middle = (first+last)/2;
  }
605

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

610 611 612 613 614 615 616
  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
*/
617 618 619 620 621 622 623 624
//-----------------------------------------------------------------------------
long
binary_search_float(
  float elements[],
  long numElem,
  float value
)
//-----------------------------------------------------------------------------
625
{
winckel's avatar
winckel committed
626
  long first, last, middle;
627 628 629
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
630

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

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

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

646 647
    middle = (first+last)/2;
  }
648

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

653 654 655
  return first;
}