rrc_common.c 25.8 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22
/*! \file rrc_common.c
23
 * \brief rrc common procedures for eNB and UE
24 25
 * \author Navid Nikaein and Raymond Knopp
 * \date 2011 - 2014
26 27
 * \version 1.0
 * \company Eurecom
28
 * \email:  navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
29
 */
30 31 32 33 34

#include "defs.h"
#include "extern.h"
#include "LAYER2/MAC/extern.h"
#include "COMMON/openair_defs.h"
35
#include "COMMON/platform_types.h"
36 37 38 39
#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"
40
#include "asn1_msg.h"
41
#include "pdcp.h"
42
#include "UTIL/LOG/vcd_signal_dumper.h"
43
#include "rrc_eNB_UE_context.h"
44
#include "common/ran_context.h"
45

46 47 48 49
#if defined(ENABLE_USE_MME)
# include "rrc_eNB_S1AP.h"
#endif

50
#ifdef LOCALIZATION
51 52 53
#include <sys/time.h>
#endif

54
#define DEBUG_RRC 1
55
extern RAN_CONTEXT_t RC;
56 57
extern UE_MAC_INST *UE_mac_inst;

58 59
extern mui_t rrc_eNB_mui;

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

71 72 73
  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));
74
    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
75 76 77 78
      rrc_config_buffer (&RC.rrc[ctxt_pP->module_id]->carrier[CC_id].SI, BCCH, 1);
      RC.rrc[ctxt_pP->module_id]->carrier[CC_id].SI.Active = 1;
      rrc_config_buffer (&RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0, CCCH, 1);
      RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Srb0.Active = 1;
79
    }
80
  } else {
81 82
    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
83

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

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

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

  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;

Lionel Gauthier's avatar
Lionel Gauthier committed
145
  Rlc_info_um.rlc_mode = RLC_MODE_UM;
146 147 148
  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;
149 150
  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;

Lionel Gauthier's avatar
Lionel Gauthier committed
151
  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
152
  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
153 154 155 156 157
  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;
158

159
  return 0;
160 161
}

162 163 164 165 166 167 168 169
//-----------------------------------------------------------------------------
void
rrc_config_buffer(
  SRB_INFO* Srb_info,
  uint8_t Lchan_type,
  uint8_t Role
)
//-----------------------------------------------------------------------------
170
{
171 172 173 174 175

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

176

177 178 179 180 181 182 183
//-----------------------------------------------------------------------------
void
rrc_t310_expiration(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                 eNB_index
)
//-----------------------------------------------------------------------------
184
{
185

186
  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State != RRC_CONNECTED) {
187
    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE\n");
188 189 190 191 192 193 194 195 196 197 198
    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,
199 200
                           SRB_FLAG_YES,
                           CONFIG_ACTION_REMOVE,
201
                           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
202
                           0);
203
      rrc_rlc_config_req (ctxt_pP,
204 205 206
                          SRB_FLAG_YES,
                          MBMS_FLAG_NO,
                          CONFIG_ACTION_REMOVE,
207
                          UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
208
                          Rlc_info_um);
209 210 211
      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;
212
    }
213
  } else { // Restablishment procedure
214
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
215 216
  }
}
Cedric Roux's avatar
Cedric Roux committed
217

218 219 220
//-----------------------------------------------------------------------------
RRC_status_t
rrc_rx_tx(
221
  protocol_ctxt_t* const ctxt_pP,
222 223 224 225
  const uint8_t      enb_indexP,
  const int          CC_id
)
//-----------------------------------------------------------------------------
226
{
227
  //uint8_t        UE_id;
228 229
  int32_t        current_timestamp_ms, ref_timestamp_ms;
  struct timeval ts;
230 231
  struct rrc_eNB_ue_context_s   *ue_context_p = NULL,*ue_to_be_removed = NULL;

232 233 234 235
#ifdef LOCALIZATION
  double                         estimated_distance;
  protocol_ctxt_t                ctxt;
#endif
236
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
237

238
  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {
239
    // check timers
240

241 242
    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)
243
        LOG_D(RRC,
244
              "[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);
245

246 247 248
      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;
249
        // ALLOW CCCH to be used
250 251
        UE_rrc_inst[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
        rrc_ue_generate_RRCConnectionRequest (ctxt_pP, enb_indexP);
252
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
253
        return (RRC_ConnSetup_failed);
254
      }
255

256
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
257
    }
258

259
    if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
260 261
      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]) {
262
	LOG_I(RRC,"Activating T310\n");
263
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
264
      }
265
    } else { // in case we have not received SIB2 yet
266
      /*      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
267
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;
268 269 270 271

	}*/
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
      return RRC_OK;
272
    }
273

274 275 276 277 278
    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;
279
      }
280

281 282 283
      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);
      }
284

285 286 287
      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);
288
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
289 290
	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n"); 
        return RRC_PHY_RESYNCH;
291
      }
292

293
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
294
    }
295

296 297 298 299
    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);
300

301 302 303
      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;
Cedric Roux's avatar
Cedric Roux committed
304 305
        LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n",
              ctxt_pP->module_id);
306
        //Implement 36.331, section 5.3.5.6 here
307
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
308
        return(RRC_Handover_failed);
309
      }
310

311
      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
312
    }
313

314
    // Layer 3 filtering of RRC measurements
315 316
    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0] != NULL) {
      ue_meas_filtering(ctxt_pP,enb_indexP);
317
    }
318

319
    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
320

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

325 326 327
    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;
328
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
329 330
      return(RRC_HO_STARTED);
    }
331

332
  } else { // eNB
333
    check_handovers(ctxt_pP);
334
    // counetr, and get the value and aggregate
335 336

    // check for UL failure
337
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
338 339
      if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) {
	if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
340
	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/8\n",
341 342 343 344 345
		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 {
346
	  LOG_I(RRC,"UE rnti %x failure timer %d/8\n",
347 348 349 350
		ue_context_p->ue_context.rnti,
		ue_context_p->ue_context.ul_failure_timer);
	}
      }
351 352
      if (ue_context_p->ue_context.ul_failure_timer>0) {
	ue_context_p->ue_context.ul_failure_timer++;
353
	if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
354 355 356 357 358 359
	  // 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;
	}
      }
360 361 362 363 364 365
      if (ue_context_p->ue_context.ue_release_timer_s1>0) {
        ue_context_p->ue_context.ue_release_timer_s1++;
        if (ue_context_p->ue_context.ue_release_timer_s1 >=
            ue_context_p->ue_context.ue_release_timer_thres_s1) {
          LOG_I(RRC,"Removing UE %x instance Because of UE_CONTEXT_RELEASE_COMMAND not received after %d ms from sending request\n",
        		  ue_context_p->ue_context.rnti, ue_context_p->ue_context.ue_release_timer_thres_s1);
366
//          ue_context_p->ue_context.ue_release_timer_s1 = 0;
Xu Bo's avatar
Xu Bo committed
367
#if defined(ENABLE_USE_MME)
368 369
#if defined(ENABLE_ITTI)
          rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p);
370
#if 0
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
          {
            int      e_rab;
            MessageDef *msg_delete_tunnels_p = NULL;
            uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
            MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
            msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
            memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
            // do not wait response
            GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
            for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
              GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
                ue_context_p->ue_context.enb_gtp_ebi[e_rab];
              // erase data
              ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
              memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
              ue_context_p->ue_context.enb_gtp_ebi[e_rab]  = 0;
            }
            itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
            MSC_LOG_TX_MESSAGE(
                    MSC_RRC_ENB,
                    MSC_S1AP_ENB,
                    NULL,0,
                    "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
                    eNB_ue_s1ap_id);

            struct rrc_ue_s1ap_ids_s    *rrc_ue_s1ap_ids = NULL;
            rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(
                    RC.rrc[ctxt_pP->module_id],
                    0,
                    eNB_ue_s1ap_id);
            if (NULL != rrc_ue_s1ap_ids) {
              rrc_eNB_S1AP_remove_ue_ids(
                         RC.rrc[ctxt_pP->module_id],
                         rrc_ue_s1ap_ids);
            }
          }
Xu Bo's avatar
Xu Bo committed
407
#endif
408
#endif
409
#else
410
          ue_to_be_removed = ue_context_p;
411
#endif
412
          ue_context_p->ue_context.ue_release_timer_s1 = 0;
413 414 415 416 417 418 419 420 421
          break;
        }
      }

      if (ue_context_p->ue_context.ue_release_timer_rrc>0) {
        ue_context_p->ue_context.ue_release_timer_rrc++;
        if (ue_context_p->ue_context.ue_release_timer_rrc >=
          ue_context_p->ue_context.ue_release_timer_thres_rrc) {
          LOG_I(RRC,"Removing UE %x instance After UE_CONTEXT_RELEASE_Complete\n", ue_context_p->ue_context.rnti);
422
          ue_context_p->ue_context.ue_release_timer_rrc = 0;
423
          ue_to_be_removed = ue_context_p;
424
          ue_context_p->ue_context.ue_release_timer_rrc = 0;
425 426
          break;
        }
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
       }
       pthread_mutex_lock(&rrc_release_freelist);
      if(rrc_release_info.num_UEs > 0){
        uint16_t release_total = 0;
        for(uint16_t release_num = 0;release_num < NUMBER_OF_UE_MAX;release_num++){
          if(rrc_release_info.RRC_release_ctrl[release_num].flag > 0){
            release_total++;
          }
          if( (rrc_release_info.RRC_release_ctrl[release_num].flag > 2) &&
            (rrc_release_info.RRC_release_ctrl[release_num].rnti == ue_context_p->ue_context.rnti)){
           ue_context_p->ue_context.ue_release_timer_rrc = 1;
           ue_context_p->ue_context.ue_release_timer_thres_rrc = 100;
#if defined(ENABLE_USE_MME)
#if defined(ENABLE_ITTI)
           int      e_rab;
           MessageDef *msg_complete_p = NULL;
           MessageDef *msg_delete_tunnels_p = NULL;
           uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
           if(rrc_release_info.RRC_release_ctrl[release_num].flag == 4){
             MSC_LOG_TX_MESSAGE(
                    MSC_RRC_ENB,
                    MSC_S1AP_ENB,
                     NULL,0,
                    "0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
                     eNB_ue_s1ap_id);
             msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
             S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
             itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_complete_p);
           }
           MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
           msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
           memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
           // do not wait response
           GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
           for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
             GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
               ue_context_p->ue_context.enb_gtp_ebi[e_rab];
             // erase data
             ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
             memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
             ue_context_p->ue_context.enb_gtp_ebi[e_rab]  = 0;
           }
           itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
           struct rrc_ue_s1ap_ids_s    *rrc_ue_s1ap_ids = NULL;
           rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(
                  RC.rrc[ctxt_pP->module_id],
                  0,
                  eNB_ue_s1ap_id);
           if (NULL != rrc_ue_s1ap_ids) {
             rrc_eNB_S1AP_remove_ue_ids(
                        RC.rrc[ctxt_pP->module_id],
                        rrc_ue_s1ap_ids);
           }
#endif
#endif
           rrc_release_info.RRC_release_ctrl[release_num].flag = 0;
           rrc_release_info.num_UEs--;
           break;
         }
         if(release_total >= rrc_release_info.num_UEs)
           break;
         }
       }
       pthread_mutex_unlock(&rrc_release_freelist);
491 492 493 494 495 496 497 498 499 500 501 502 503

      if (ue_context_p->ue_context.ue_reestablishment_timer>0) {
        ue_context_p->ue_context.ue_reestablishment_timer++;
        if (ue_context_p->ue_context.ue_reestablishment_timer >=
            ue_context_p->ue_context.ue_reestablishment_timer_thres) {
          LOG_I(RRC,"UE %d reestablishment_timer max\n",ue_context_p->ue_context.rnti);
          ue_context_p->ue_context.ul_failure_timer = 20000;
          ue_to_be_removed = ue_context_p;
          ue_context_p->ue_context.ue_reestablishment_timer = 0;
          break;
        }
      }

504 505
      if (ue_context_p->ue_context.ue_release_timer>0) {
	ue_context_p->ue_context.ue_release_timer++;
506 507
	if (ue_context_p->ue_context.ue_release_timer >= 
	    ue_context_p->ue_context.ue_release_timer_thres) {
508 509
	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
	  ue_to_be_removed = ue_context_p;
510 511 512
#ifdef UE_EXPANSION
	  ue_context_p->ue_context.ue_release_timer = 0;
#endif
513 514 515
	  break;
	}
      }
516
    }
517
    if (ue_to_be_removed) {
518
      if(ue_to_be_removed->ue_context.ul_failure_timer >= 20000) {
519
          ue_to_be_removed->ue_context.ue_release_timer_s1 = 1;
520
          ue_to_be_removed->ue_context.ue_release_timer_thres_s1 = 200;
521 522 523
          ue_to_be_removed->ue_context.ue_release_timer = 0;
          ue_to_be_removed->ue_context.ue_reestablishment_timer = 0;
      }
524
      rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed);
525
      if(ue_to_be_removed->ue_context.ul_failure_timer >= 20000){
526 527
        ue_to_be_removed->ue_context.ul_failure_timer = 0;
      }
528
    }
529
#ifdef RRC_LOCALIZATION
530

531 532 533
    /* for the localization, only primary CC_id might be relevant*/
    gettimeofday(&ts, NULL);
    current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
534 535
    ref_timestamp_ms = RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms;
    RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
536 537 538 539 540
      ctxt = *ctxt_pP;
      ctxt.rnti = ue_context_p->ue_context.rnti;
      estimated_distance = rrc_get_estimated_ue_distance(
                             &ctxt,
                             CC_id,
541
                             RC.rrc[ctxt_pP->module_id]->loc_type);
542

543
      if ((current_timestamp_ms - ref_timestamp_ms > RC.rrc[ctxt_pP->module_id]->aggregation_period_ms) &&
544
          estimated_distance != -1) {
545
        LOG_D(LOCALIZE, " RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
546 547
              ctxt.rnti,
              ctxt_pP->module_id,
548
              current_timestamp_ms,
549 550 551
              ctxt_pP->frame,
              estimated_distance);
        LOG_D(LOCALIZE, " RRC status %d\n", ue_context_p->ue_context.Status);
552
        push_front(&RC.rrc[ctxt_pP->module_id]->loc_list,
553
                   estimated_distance);
554
        RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms = current_timestamp_ms;
555
      }
556
    }
557

558
#endif
559 560 561
    (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" */
562
  }
563

564
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
565 566
  return (RRC_OK);
}
567

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

582
  if(value < elements[0]) {
583
    return first;
584
  }
585

586
  if(value > elements[last]) {
587
    return last;
588
  }
589

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

600 601
    middle = (first+last)/2;
  }
602

603
  if (first > last) {
604
    LOG_E(RRC,"Error in binary search!");
605
  }
606

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

628
  if(value <= elements[0]) {
629
    return first;
630
  }
631

632
  if(value >= elements[last]) {
633
    return last;
634
  }
635

636
  while (last - first > 1) {
637
    if (elements[middle] > value) {
638
      last = middle;
639
    } else {
640
      first = middle;
641
    }
642

643 644
    middle = (first+last)/2;
  }
645

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

650 651 652
  return first;
}