rrc_common.c 22.9 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
#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

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

Cedric Roux's avatar
Cedric Roux committed
257
258
259
  /* for no gcc warnings */
  (void)CC_id;

260
261
262
263
264
265
  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);
266
267

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

gauthier's avatar
gauthier committed
270
    for (module_id = 0; module_id < NB_UE_INST; module_id++) {
271
      UE_rrc_inst[module_id].UECap = UECap;
gauthier's avatar
gauthier committed
272
273
      UE_rrc_inst[module_id].UECapability = UECap->sdu;
      UE_rrc_inst[module_id].UECapability_size = UECap->sdu_size;
274
    }
275

276
277
#ifdef Rel10
    LOG_I(RRC,"[UE] eMBMS active state is %d \n", eMBMS_active);
278
279

    for (module_id=0; module_id<NB_UE_INST; module_id++) {
gauthier's avatar
gauthier committed
280
      UE_rrc_inst[module_id].MBMS_flag = (uint8_t)eMBMS_active;
281
    }
282
283

#endif
284
  } else {
285
    UE_rrc_inst = NULL;
286
  }
287

288
289
290
  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));
291
    LOG_I(RRC,"[eNB] handover active state is %d \n", HO_active);
292
293

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

297
#ifdef Rel10
298
    LOG_I(RRC,"[eNB] eMBMS active state is %d \n", eMBMS_active);
299
300

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
301
302
303
      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;
      }
304
    }
305
306

#endif
307
#ifdef CBA
308
309

    for (module_id=0; module_id<NB_eNB_INST; module_id++) {
310
311
312
      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;
      }
313
    }
314

315
316
317
318
319
#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
320
321
322
323
324
325

    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;
326
    }
327

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

335
336
337
338
339
340
341
342
343
344
#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
345
  Data_to_read = 0;
346
347
348
#endif //USER_MODE
}

349
350
351
352
353
354
//-----------------------------------------------------------------------------
void
rrc_top_cleanup(
  void
)
//-----------------------------------------------------------------------------
355
{
356

357
  if (NB_UE_INST > 0) {
358
    free (UE_rrc_inst);
359
  }
360

361
  if (NB_eNB_INST > 0) {
362
    free (eNB_rrc_inst);
363

364
  }
365
366
}

367

368
369
370
371
372
373
374
//-----------------------------------------------------------------------------
void
rrc_t310_expiration(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                 eNB_index
)
//-----------------------------------------------------------------------------
375
{
376

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

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

423
424
425
426
#ifdef LOCALIZATION
  double                         estimated_distance;
  protocol_ctxt_t                ctxt;
#endif
gauthier's avatar
gauthier committed
427
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
428

429
  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {
430
    // check timers
431

432
433
    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)
434
        LOG_D(RRC,
435
              "[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);
436

437
438
439
      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;
440
        // ALLOW CCCH to be used
441
442
        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
443
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
444
        return (RRC_ConnSetup_failed);
445
      }
446

447
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
448
    }
449

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

	}*/
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
      return RRC_OK;
463
    }
464

465
466
467
468
469
    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;
470
      }
471

472
473
474
      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);
      }
475

476
477
478
      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
479
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
480
481
	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n"); 
        return RRC_PHY_RESYNCH;
482
      }
483

484
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
485
    }
486

487
488
489
490
    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);
491

492
493
494
      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;
495
496
        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
497
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
498
        return(RRC_Handover_failed);
499
      }
500

501
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
502
    }
503

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

509
    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
510

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

515
516
517
    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
518
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
519
520
      return(RRC_HO_STARTED);
    }
521

522
  } else { // eNB
523
    check_handovers(ctxt_pP);
524
    // counetr, and get the value and aggregate
525
526
527

    // check for UL failure
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head)) {
528
529
530
531
532
533
534
535
536
537
538
539
540
      if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) {
	if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n",
		ue_context_p->ue_context.rnti,
		ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
		ue_context_p->ue_context.ul_failure_timer);
	}
	else {
	  LOG_I(RRC,"UE rnti %x failure timer %d/20000\n",
		ue_context_p->ue_context.rnti,
		ue_context_p->ue_context.ul_failure_timer);
	}
      }
541
542
543
544
545
546
547
548
549
      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;
	}
      }
550
551
      if (ue_context_p->ue_context.ue_release_timer>0) {
	ue_context_p->ue_context.ue_release_timer++;
knopp's avatar
knopp committed
552
553
	if (ue_context_p->ue_context.ue_release_timer >= 
	    ue_context_p->ue_context.ue_release_timer_thres) {
554
555
556
557
558
	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
	  ue_to_be_removed = ue_context_p;
	  break;
	}
      }
559
560
561
    }
    if (ue_to_be_removed)
      rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed);
562

nikaeinn's avatar
nikaeinn committed
563
#ifdef RRC_LOCALIZATION
564

565
566
567
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
568
569
570
571
572
573
574
575
576
577
578
    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) {
579
        LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
580
581
              ctxt.rnti,
              ctxt_pP->module_id,
582
              current_timestamp_ms,
583
584
585
586
587
588
              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;
589
      }
590
    }
591

592
#endif
593
594
595
    (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" */
596
  }
597

gauthier's avatar
gauthier committed
598
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
599
600
  return (RRC_OK);
}
601

602
603
604
605
606
607
608
609
//-----------------------------------------------------------------------------
long
binary_search_int(
  int elements[],
  long numElem,
  int value
)
//-----------------------------------------------------------------------------
610
{
winckel's avatar
winckel committed
611
  long first, last, middle, search = -1;
612
613
614
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
615

616
  if(value < elements[0]) {
617
    return first;
618
  }
619

620
  if(value > elements[last]) {
621
    return last;
622
  }
623

624
  while (first <= last) {
625
    if (elements[middle] < value) {
626
      first = middle+1;
627
    } else if (elements[middle] == value) {
628
629
      search = middle+1;
      break;
630
    } else {
631
      last = middle -1;
632
    }
633

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

637
  if (first > last) {
638
    LOG_E(RRC,"Error in binary search!");
639
  }
640

641
642
643
644
645
646
647
  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
*/
648
649
650
651
652
653
654
655
//-----------------------------------------------------------------------------
long
binary_search_float(
  float elements[],
  long numElem,
  float value
)
//-----------------------------------------------------------------------------
656
{
winckel's avatar
winckel committed
657
  long first, last, middle;
658
659
660
  first = 0;
  last = numElem-1;
  middle = (first+last)/2;
661

662
  if(value <= elements[0]) {
663
    return first;
664
  }
665

666
  if(value >= elements[last]) {
667
    return last;
668
  }
669

670
  while (last - first > 1) {
671
    if (elements[middle] > value) {
672
      last = middle;
673
    } else {
674
      first = middle;
675
    }
676

677
678
    middle = (first+last)/2;
  }
679

680
  if (first < 0 || first >= numElem) {
681
    LOG_E(RRC,"\n Error in binary search float!");
682
  }
683

684
685
686
  return first;
}