/*
 * 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
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * 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
 */

/*! \file rrc_UE.c
 * \brief rrc procedures for UE
 * \author Navid Nikaein and Raymond Knopp
 * \date 2011 - 2014
 * \version 1.0
 * \company Eurecom
 * \email: navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
 */

#define RRC_UE
#define RRC_UE_C
#define _GNU_SOURCE

#include "assertions.h"
#include "hashtable.h"
#include "asn1_conversions.h"
#include "rrc_defs.h"
#include "rrc_extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "openair1/PHY/LTE_ESTIMATION/lte_estimation.h"
#include "LAYER2/RLC/rlc.h"
#include "COMMON/mac_rrc_primitives.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#ifndef CELLULAR
#include "RRC/LTE/MESSAGES/asn1_msg.h"
#endif
#include "LTE_RRCConnectionRequest.h"
#include "LTE_RRCConnectionReconfiguration.h"
#include "LTE_UL-CCCH-Message.h"
#include "LTE_DL-CCCH-Message.h"
#include "LTE_UL-DCCH-Message.h"
#include "LTE_DL-DCCH-Message.h"
#include "LTE_BCCH-DL-SCH-Message.h"
#include "LTE_PCCH-Message.h"
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
#include "LTE_MCCH-Message.h"
#endif
#include "LTE_MeasConfig.h"
#include "LTE_MeasGapConfig.h"
#include "LTE_MeasObjectEUTRA.h"
#include "LTE_TDD-Config.h"
#include "LTE_UECapabilityEnquiry.h"
#include "LTE_UE-CapabilityRequest.h"
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#if ENABLE_RAL
#include "rrc_UE_ral.h"
#endif

#if defined(ENABLE_SECURITY)
# include "UTIL/OSA/osa_defs.h"
#endif

#include "pdcp.h"
#include "plmn_data.h"
#include "msc.h"

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

#include "SIMULATION/TOOLS/sim.h" // for taus

#include "openair2/LAYER2/MAC/mac_extern.h"

#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
#include "LTE_SL-Preconfiguration-r12.h"

//for D2D
int ctrl_sock_fd;
#define BUFSIZE 1024
struct sockaddr_in prose_app_addr;
int slrb_id;
int send_ue_information = 0;
#endif

// for malloc_clear
#include "PHY/defs_UE.h"

extern void pdcp_config_set_security(
  const protocol_ctxt_t* const  ctxt_pP,
  pdcp_t         * const pdcp_pP,
  const rb_id_t         rb_idP,
  const uint16_t        lc_idP,
  const uint8_t         security_modeP,
  uint8_t        * const kRRCenc,
  uint8_t        * const kRRCint,
  uint8_t        * const  kUPenc);

// internal prototypes

void rrc_ue_process_securityModeCommand( const protocol_ctxt_t* const ctxt_pP, LTE_SecurityModeCommand_t* const securityModeCommand, const uint8_t eNB_index );

static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index );

static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t rsrq, const uint8_t rsrp );

/** \brief Generates/Encodes RRCConnnectionSetupComplete message at UE
 *  \param ctxt_pP Running context
 *  \param eNB_index Index of corresponding eNB/CH
 *  \param Transaction_id Transaction identifier
 */
static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id );

/** \brief Generates/Encodes RRCConnectionReconfigurationComplete message at UE
 *  \param ctxt_pP Running context
 *  \param eNB_index Index of corresponding eNB/CH
 *  \param Transaction_id RRC transaction identifier
 */
static void rrc_ue_generate_RRCConnectionReconfigurationComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id );

static void rrc_ue_generate_MeasurementReport(protocol_ctxt_t* const ctxt_pP, uint8_t eNB_index );

static uint8_t check_trigger_meas_event(
  module_id_t module_idP,
  frame_t frameP,
  uint8_t eNB_index,
  uint8_t ue_cnx_index,
  uint8_t meas_index,
  LTE_Q_OffsetRange_t ofn, LTE_Q_OffsetRange_t ocn, LTE_Hysteresis_t hys,
  LTE_Q_OffsetRange_t ofs, LTE_Q_OffsetRange_t ocs, long a3_offset, LTE_TimeToTrigger_t ttt);

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
static void decode_MBSFNAreaConfiguration(module_id_t module_idP, uint8_t eNB_index, frame_t frameP,uint8_t mbsfn_sync_area);
uint8_t rrc_ue_generate_SidelinkUEInformation( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index,LTE_SL_DestinationInfoList_r12_t  *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode);
#endif








/*------------------------------------------------------------------------------*/
/* to avoid gcc warnings when compiling with certain options */
#if defined(ENABLE_USE_MME) || ENABLE_RAL
static Rrc_State_t rrc_get_state (module_id_t ue_mod_idP)
{
  return UE_rrc_inst[ue_mod_idP].RrcState;
}
#endif

static Rrc_Sub_State_t rrc_get_sub_state (module_id_t ue_mod_idP)
{
  return UE_rrc_inst[ue_mod_idP].RrcSubState;
}

static int rrc_set_state (module_id_t ue_mod_idP, Rrc_State_t state)
{
  AssertFatal ((RRC_STATE_FIRST <= state) && (state <= RRC_STATE_LAST),
               "Invalid state %d!\n", state);

  if (UE_rrc_inst[ue_mod_idP].RrcState != state) {
    UE_rrc_inst[ue_mod_idP].RrcState = state;

#if defined(ENABLE_ITTI)
    {
      MessageDef *msg_p;

      msg_p = itti_alloc_new_message(TASK_RRC_UE, RRC_STATE_IND);
      RRC_STATE_IND(msg_p).state = UE_rrc_inst[ue_mod_idP].RrcState;
      RRC_STATE_IND(msg_p).sub_state = UE_rrc_inst[ue_mod_idP].RrcSubState;

      itti_send_msg_to_task(TASK_UNKNOWN, UE_MODULE_ID_TO_INSTANCE(ue_mod_idP), msg_p);
    }
#endif
    return (1);
  }

  return (0);
}

//-----------------------------------------------------------------------------
static int rrc_set_sub_state( module_id_t ue_mod_idP, Rrc_Sub_State_t subState )
{
#if (defined(ENABLE_ITTI) && (defined(ENABLE_USE_MME) || ENABLE_RAL))

  switch (UE_rrc_inst[ue_mod_idP].RrcState) {
  case RRC_STATE_INACTIVE:
    AssertFatal ((RRC_SUB_STATE_INACTIVE_FIRST <= subState) && (subState <= RRC_SUB_STATE_INACTIVE_LAST),
                 "Invalid sub state %d for state %d!\n", subState, UE_rrc_inst[ue_mod_idP].RrcState);
    break;

  case RRC_STATE_IDLE:
    AssertFatal ((RRC_SUB_STATE_IDLE_FIRST <= subState) && (subState <= RRC_SUB_STATE_IDLE_LAST),
                 "Invalid sub state %d for state %d!\n", subState, UE_rrc_inst[ue_mod_idP].RrcState);
    break;

  case RRC_STATE_CONNECTED:
    AssertFatal ((RRC_SUB_STATE_CONNECTED_FIRST <= subState) && (subState <= RRC_SUB_STATE_CONNECTED_LAST),
                 "Invalid sub state %d for state %d!\n", subState, UE_rrc_inst[ue_mod_idP].RrcState);
    break;
  }

#endif

  if (UE_rrc_inst[ue_mod_idP].RrcSubState != subState) {
    UE_rrc_inst[ue_mod_idP].RrcSubState = subState;

#if defined(ENABLE_ITTI)
    {
      MessageDef *msg_p;

      msg_p = itti_alloc_new_message(TASK_RRC_UE, RRC_STATE_IND);
      RRC_STATE_IND(msg_p).state = UE_rrc_inst[ue_mod_idP].RrcState;
      RRC_STATE_IND(msg_p).sub_state = UE_rrc_inst[ue_mod_idP].RrcSubState;

      itti_send_msg_to_task(TASK_UNKNOWN, UE_MODULE_ID_TO_INSTANCE(ue_mod_idP), msg_p);
    }
#endif
    return (1);
  }

  return (0);
}

//-----------------------------------------------------------------------------
void
openair_rrc_on_ue(
  const protocol_ctxt_t* const ctxt_pP
)
//-----------------------------------------------------------------------------
{
  unsigned short i;


    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" UE?:OPENAIR RRC IN....\n",
          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));

    for (i = 0; i < NB_eNB_INST; i++) {
      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;
    }
}

//-----------------------------------------------------------------------------
static void init_SI_UE( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
{
  UE_rrc_inst[ctxt_pP->module_id].sizeof_SIB1[eNB_index] = 0;
  UE_rrc_inst[ctxt_pP->module_id].sizeof_SI[eNB_index] = 0;
  UE_rrc_inst[ctxt_pP->module_id].SIB1[eNB_index] = (uint8_t*)malloc16_clear( 32 );
  UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType1_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType2_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib3[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType3_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib4[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType4_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib5[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType5_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib6[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType6_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib7[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType7_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib8[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType8_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib9[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType9_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib10[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType10_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib11[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType11_t) );
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
  UE_rrc_inst[ctxt_pP->module_id].sib12[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType12_r9_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType13_r9_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType18_r12_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType19_r12_t) );
  UE_rrc_inst[ctxt_pP->module_id].sib21[eNB_index] = malloc16_clear( sizeof(LTE_SystemInformationBlockType21_r14_t) );

#endif
  UE_rrc_inst[ctxt_pP->module_id].SI[eNB_index] = (uint8_t*)malloc16_clear( 64 );

  UE_rrc_inst[ctxt_pP->module_id].si[eNB_index] = (LTE_SystemInformation_t*)malloc16_clear( sizeof(LTE_SystemInformation_t) );

  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus = 0;
  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt    = 0;
}

#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
void init_SL_preconfig(UE_RRC_INST *UE, const uint8_t eNB_index )
{
  LOG_I(RRC,"Initializing Sidelink Pre-configuration for UE\n");

  UE->SL_Preconfiguration[eNB_index] = malloc16_clear( sizeof(struct LTE_SL_Preconfiguration_r12) );
  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.rohc_Profiles_r12.profile0x0001_r12       = true;
  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.carrierFreq_r12                           = 3350;
  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.maxTxPower_r12                            = 0;
  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.additionalSpectrumEmission_r12            = 0;
  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.sl_bandwidth_r12                          = LTE_SL_PreconfigGeneral_r12__sl_bandwidth_r12_n50;
  UE->SL_Preconfiguration[eNB_index]->preconfigGeneral_r12.tdd_ConfigSL_r12.subframeAssignmentSL_r12 = LTE_TDD_ConfigSL_r12__subframeAssignmentSL_r12_none;

  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncCP_Len_r12            = LTE_SL_CP_Len_r12_normal;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncOffsetIndicator1_r12  = 0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncOffsetIndicator2_r12  = 0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncTxParameters_r12      = 0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncTxThreshOoC_r12       = 0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.filterCoefficient_r12     = LTE_FilterCoefficient_fc0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncRefMinHyst_r12        = LTE_SL_PreconfigSync_r12__syncRefMinHyst_r12_dB0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.syncRefDiffHyst_r12       = LTE_SL_PreconfigSync_r12__syncRefDiffHyst_r12_dB0;
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.ext1                      = malloc16_clear(sizeof(struct LTE_SL_PreconfigSync_r12__ext1));
  UE->SL_Preconfiguration[eNB_index]->preconfigSync_r12.ext1->syncTxPeriodic_r13  = NULL;

  struct LTE_SL_PreconfigCommPool_r12 *preconfigpool = malloc16_clear(sizeof(struct LTE_SL_PreconfigCommPool_r12));
  preconfigpool->sc_CP_Len_r12                                                    = LTE_SL_CP_Len_r12_normal;
  preconfigpool->sc_Period_r12                                                    = LTE_SL_PeriodComm_r12_sf40;
  // 20 PRBs for SL communications
  preconfigpool->sc_TF_ResourceConfig_r12.prb_Num_r12                             = 20;
  preconfigpool->sc_TF_ResourceConfig_r12.prb_Start_r12                           = 5;
  preconfigpool->sc_TF_ResourceConfig_r12.prb_End_r12                             = 44;
  // Offset set to 0 subframes
  preconfigpool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.present             = LTE_SL_OffsetIndicator_r12_PR_small_r12;
  preconfigpool->sc_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12    = 0;
  // 40 ms SL Period
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.present              = LTE_SubframeBitmapSL_r12_PR_bs40_r12;
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf         = CALLOC(1,5);
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size        = 5;
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = 0;
  // 1st 4 subframes for PSCCH
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[0]      = 0xF;
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[1]      = 0;
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[2]      = 0;
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[3]      = 0;
  preconfigpool->sc_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[4]      = 0;
  preconfigpool->sc_TxParameters_r12                                              = 0;

  preconfigpool->data_CP_Len_r12                                                  = LTE_SL_CP_Len_r12_normal;
  // 20 PRBs for SL communications
  preconfigpool->data_TF_ResourceConfig_r12.prb_Num_r12                             = 20;
  preconfigpool->data_TF_ResourceConfig_r12.prb_Start_r12                           = 5;
  preconfigpool->data_TF_ResourceConfig_r12.prb_End_r12                             = 44;
  // Offset set to 0 subframes
  preconfigpool->data_TF_ResourceConfig_r12.offsetIndicator_r12.present             = LTE_SL_OffsetIndicator_r12_PR_small_r12;
  preconfigpool->data_TF_ResourceConfig_r12.offsetIndicator_r12.choice.small_r12    = 0;
  // 40 ms SL Period
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.present              = LTE_SubframeBitmapSL_r12_PR_bs40_r12;
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf         = CALLOC(1,5);
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.size        = 5;
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.bits_unused = 0;
  // last 36 subframes for PSCCH
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[0]      = 0xF0;
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[1]      = 0xFF;
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[2]      = 0xFF;
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[3]      = 0xFF;
  preconfigpool->data_TF_ResourceConfig_r12.subframeBitmap_r12.choice.bs40_r12.buf[5]      = 0xFF;

  preconfigpool->dataHoppingConfig_r12.hoppingParameter_r12                         = 0;
  preconfigpool->dataHoppingConfig_r12.numSubbands_r12                              = LTE_SL_HoppingConfigComm_r12__numSubbands_r12_ns1;
  preconfigpool->dataHoppingConfig_r12.rb_Offset_r12                                = 0;

  preconfigpool->dataTxParameters_r12                                               = 0;

  ASN_SEQUENCE_ADD(&UE->SL_Preconfiguration[eNB_index]->preconfigComm_r12.list,preconfigpool);

  // Rel13 extensions
  UE->SL_Preconfiguration[eNB_index]->ext1 = NULL;
/*
  // Establish a SLRB (using DRB 3 for now)
  protocol_ctxt_t ctxt;
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);

  UE->DRB_config[0][0] = CALLOC(1,sizeof(struct DRB_ToAddMod));
  UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
  UE->DRB_config[0][0]->drb_Identity =  3;
  UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
  // allowed value 5..15, value : x+4
  *(UE->DRB_config[0][0]->eps_BearerIdentity) = 3;
  UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
  *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2

  // TTN - Establish a new SLRB for PC5-S (using DRB 10 for now)
  UE->DRB_config[0][1] = CALLOC(1,sizeof(struct DRB_ToAddMod));
  UE->DRB_config[0][1]->eps_BearerIdentity = CALLOC(1, sizeof(long));
  UE->DRB_config[0][1]->drb_Identity =  10;
  UE->DRB_config[0][1]->eps_BearerIdentity = CALLOC(1, sizeof(long));
  // allowed value 5..15, value : x+4
  *(UE->DRB_config[0][1]->eps_BearerIdentity) = 10;
  UE->DRB_config[0][1]->logicalChannelIdentity = CALLOC(1, sizeof(long));
  *(UE->DRB_config[0][1]->logicalChannelIdentity) = UE->DRB_config[0][1]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2

  struct RLC_Config                  *DRB_rlc_config                   = CALLOC(1,sizeof(struct RLC_Config));
  struct PDCP_Config                 *DRB_pdcp_config                  = CALLOC(1,sizeof(struct PDCP_Config));
  struct PDCP_Config__rlc_UM         *PDCP_rlc_UM                      = CALLOC(1,sizeof(struct PDCP_Config__rlc_UM));
  struct LogicalChannelConfig        *DRB_lchan_config                 = CALLOC(1,sizeof(struct LogicalChannelConfig));
  struct LogicalChannelConfig__ul_SpecificParameters
    *DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LogicalChannelConfig__ul_SpecificParameters));
  long                               *logicalchannelgroup_drb          = CALLOC(1, sizeof(long));

  DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
  DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35;
  UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;
  UE->DRB_config[0][1]->rlc_Config = DRB_rlc_config;

  DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
  UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
  UE->DRB_config[0][1]->pdcp_Config = DRB_pdcp_config;
  DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
  *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity;
  DRB_pdcp_config->rlc_AM = NULL;
  DRB_pdcp_config->rlc_UM = NULL;

  // avoid gcc warnings
  (void)PDCP_rlc_UM;

  DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
  PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
  DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;

  UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
  UE->DRB_config[0][1]->logicalChannelConfig = DRB_lchan_config;
  DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
  DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;

  DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
  DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
    //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
  DRB_ul_SpecificParameters->bucketSizeDuration =
    LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;

  // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)

  *logicalchannelgroup_drb = 1;
  DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;

  UE->DRB_configList = CALLOC(1,sizeof(DRB_ToAddModList_t));
  ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);
  ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][1]);

  rrc_pdcp_config_asn1_req(&ctxt,
			   (SRB_ToAddModList_t *) NULL,
			   UE->DRB_configList,
			   (DRB_ToReleaseList_t*) NULL,
			   0xff, NULL, NULL, NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                           , (LTE_PMCH_InfoList_r9_t *) NULL
#endif
                           ,NULL);

  rrc_rlc_config_asn1_req(&ctxt,
			  (SRB_ToAddModList_t*)NULL,
			  UE->DRB_configList,
			  (DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			  ,(LTE_PMCH_InfoList_r9_t *)NULL
#endif
			  );
*/
}

#endif

//-----------------------------------------------------------------------------
void openair_rrc_ue_init_security( const protocol_ctxt_t* const ctxt_pP )
{
#if defined(ENABLE_SECURITY)
  //    uint8_t *kRRCenc;
  //    uint8_t *kRRCint;
  char ascii_buffer[65];
  uint8_t i;

  memset(UE_rrc_inst[ctxt_pP->module_id].kenb, ctxt_pP->module_id, 32);

  for (i = 0; i < 32; i++) {
    sprintf(&ascii_buffer[2 * i], "%02X", UE_rrc_inst[ctxt_pP->module_id].kenb[i]);
  }

  LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT"[OSA] kenb    = %s\n",
        PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
        ascii_buffer);
#endif
}

//-----------------------------------------------------------------------------
char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_index )
{
  protocol_ctxt_t ctxt;
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_idP, ENB_FLAG_NO, NOT_A_RNTI, 0, 0,eNB_index);
  LOG_I(RRC,
        PROTOCOL_RRC_CTXT_FMT" Init...\n",
        PROTOCOL_RRC_CTXT_ARGS(&ctxt));
  rrc_set_state (ue_mod_idP, RRC_STATE_INACTIVE);
  rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_INACTIVE);

  LOG_I(RRC,"[UE %d] INIT State = RRC_IDLE (eNB %d)\n",ctxt.module_id,eNB_index);
  UE_rrc_inst[ctxt.module_id].Info[eNB_index].State=RRC_IDLE;
  UE_rrc_inst[ctxt.module_id].Info[eNB_index].T300_active = 0;
  UE_rrc_inst[ctxt.module_id].Info[eNB_index].T304_active = 0;
  UE_rrc_inst[ctxt.module_id].Info[eNB_index].T310_active = 0;
  UE_rrc_inst[ctxt.module_id].Info[eNB_index].UE_index=0xffff;
  UE_rrc_inst[ctxt.module_id].Srb0[eNB_index].Active=0;
  UE_rrc_inst[ctxt.module_id].Srb1[eNB_index].Active=0;
  UE_rrc_inst[ctxt.module_id].Srb2[eNB_index].Active=0;
  UE_rrc_inst[ctxt.module_id].HandoverInfoUe.measFlag=1;
  UE_rrc_inst[ctxt.module_id].ciphering_algorithm = LTE_CipheringAlgorithm_r12_eea0;
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 2, 0))
  UE_rrc_inst[ctxt.module_id].integrity_algorithm = LTE_SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920;
#else
  UE_rrc_inst[ctxt.module_id].integrity_algorithm = LTE_SecurityAlgorithmConfig__integrityProtAlgorithm_reserved;
#endif

  openair_rrc_ue_init_security(&ctxt);
  init_SI_UE(&ctxt,eNB_index);
  LOG_D(RRC,PROTOCOL_RRC_CTXT_FMT"  INIT: phy_sync_2_ch_ind\n",
        PROTOCOL_RRC_CTXT_ARGS(&ctxt));



#ifndef NO_RRM
  send_msg(&S_rrc,msg_rrc_phy_synch_to_CH_ind(ctxt.module_id,eNB_index,UE_rrc_inst[ctxt.module_id].Mac_id));
#endif

#ifndef NO_RRM
  send_msg(&S_rrc,msg_rrc_phy_synch_to_CH_ind(ctxt.module_id,eNB_index,UE_rrc_inst[ctxt.module_id].Mac_id));
#endif

#ifdef NO_RRM //init ch SRB0, SRB1 & BDTCH
  openair_rrc_on_ue(&ctxt);
#endif
#ifdef CBA
  int j;

  for(j=0; j<NUM_MAX_CBA_GROUP; j++) {
    UE_rrc_inst[ue_mod_idP].cba_rnti[j] = 0x0000;
  }

  UE_rrc_inst[ue_mod_idP].num_active_cba_groups = 0;
#endif

  return 0;
}

//-----------------------------------------------------------------------------
void rrc_ue_generate_RRCConnectionRequest( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
{

  uint8_t i=0,rv[6];

  if(UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size ==0) {

    // Get RRCConnectionRequest, fill random for now
    // Generate random byte stream for contention resolution
    for (i=0; i<6; i++) {
#ifdef SMBV
      // if SMBV is configured the contention resolution needs to be fix for the connection procedure to succeed
      rv[i]=i;
#else
      rv[i]=taus()&0xff;
#endif
      LOG_T(RRC,"%x.",rv[i]);
    }

    LOG_T(RRC,"\n");
    UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size =
      do_RRCConnectionRequest(
        ctxt_pP->module_id,
        (uint8_t*)UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.Payload,
        rv);

    LOG_I(RRC,"[UE %d] : Frame %d, Logical Channel UL-CCCH (SRB0), Generating RRCConnectionRequest (bytes %d, eNB %d)\n",
          ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size, eNB_index);

    for (i=0; i<UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size; i++) {
      LOG_T(RRC,"%x.",UE_rrc_inst[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.Payload[i]);
    }

    LOG_T(RRC,"\n");
    /*UE_rrc_inst[ue_mod_idP].Srb0[Idx].Tx_buffer.Payload[i] = taus()&0xff;
    UE_rrc_inst[ue_mod_idP].Srb0[Idx].Tx_buffer.payload_size =i; */

  }
}


mui_t rrc_mui=0;

#if !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME))
/* NAS Attach request with IMSI */
static const char const nas_attach_req_imsi[] = {
  0x07, 0x41,
  /* EPS Mobile identity = IMSI */
  0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87,
  0xF9,
  /* End of EPS Mobile Identity */
  0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03,
  0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00,
  0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2,
  0x01, 0x27, 0x11,
};
#endif /* !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)) */

//-----------------------------------------------------------------------------
void
rrc_t310_expiration(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                 eNB_index
)
//-----------------------------------------------------------------------------
{

  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State != RRC_CONNECTED) {
    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE\n");
    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) {
      LOG_D (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,
                           SRB_FLAG_YES,
                           CONFIG_ACTION_REMOVE,
                           UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
                           0);
      rrc_rlc_config_req (ctxt_pP,
                          SRB_FLAG_YES,
                          MBMS_FLAG_NO,
                          CONFIG_ACTION_REMOVE,
                          UE_rrc_inst[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
                          Rlc_info_um);
      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;
    }
  } else { // Restablishment procedure
    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
  }
}

//-----------------------------------------------------------------------------
static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id )
{

  uint8_t    buffer[100];
  uint8_t    size;
  const char * nas_msg;
  int   nas_msg_length;

#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
  nas_msg         = (char*) UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data;
  nas_msg_length  = UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.length;
#else
  nas_msg         = nas_attach_req_imsi;
  nas_msg_length  = sizeof(nas_attach_req_imsi);
#endif

  size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, nas_msg_length, nas_msg);

  LOG_I(RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionSetupComplete (bytes%d, eNB %d)\n",
        ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index);
  LOG_D(RLC,
        "[FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCConnectionSetupComplete to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
        ctxt_pP->frame, ctxt_pP->module_id+NB_eNB_INST, size, eNB_index, rrc_mui, ctxt_pP->module_id+NB_eNB_INST, DCCH);
  rrc_data_req_ue (
		ctxt_pP,
		DCCH,
		rrc_mui++,
		SDU_CONFIRM_NO,
		size,
		buffer,
		PDCP_TRANSMISSION_MODE_CONTROL);
}

//-----------------------------------------------------------------------------
void rrc_ue_generate_RRCConnectionReconfigurationComplete( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id )
{

  uint8_t buffer[32], size;
  size = do_RRCConnectionReconfigurationComplete(ctxt_pP, buffer, Transaction_id);
  LOG_I(RRC,PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel UL-DCCH (SRB1), Generating RRCConnectionReconfigurationComplete (bytes %d, eNB_index %d)\n",
        PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), size, eNB_index);
  LOG_D(RLC,
        "[FRAME %05d][RRC_UE][INST %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCConnectionReconfigurationComplete to eNB %d MUI %d) --->][PDCP][INST %02d][RB %02d]\n",
        ctxt_pP->frame,
        UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id),
        size,
        eNB_index,
        rrc_mui,
        UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id),
        DCCH);
  rrc_data_req_ue (
		ctxt_pP,
		DCCH,
		rrc_mui++,
		SDU_CONFIRM_NO,
		size,
		buffer,
		PDCP_TRANSMISSION_MODE_CONTROL);
}


//-----------------------------------------------------------------------------
// Called by L2 interface (MAC)
int rrc_ue_decode_ccch( const protocol_ctxt_t* const ctxt_pP, const SRB_INFO* const Srb_info, const uint8_t eNB_index )
{
  LTE_DL_CCCH_Message_t* dl_ccch_msg=NULL;
  asn_dec_rval_t dec_rval;
  int rval=0;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN);
  //  LOG_D(RRC,"[UE %d] Decoding DL-CCCH message (%d bytes), State %d\n",ue_mod_idP,Srb_info->Rx_buffer.payload_size,
  //  UE_rrc_inst[ue_mod_idP].Info[eNB_index].State);

  dec_rval = uper_decode(NULL,
                         &asn_DEF_LTE_DL_CCCH_Message,
                         (void**)&dl_ccch_msg,
                         (uint8_t*)Srb_info->Rx_buffer.Payload,
                         100,0,0);

  if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
     xer_fprint(stdout,&asn_DEF_LTE_DL_CCCH_Message,(void*)dl_ccch_msg);
  }

#if defined(ENABLE_ITTI)
# if defined(DISABLE_ITTI_XER_PRINT)
  {
    MessageDef *msg_p;

    msg_p = itti_alloc_new_message (TASK_RRC_UE, RRC_DL_CCCH_MESSAGE);
    memcpy (&msg_p->ittiMsg, (void *) dl_ccch_msg, sizeof(RrcDlCcchMessage));

    itti_send_msg_to_task (TASK_UNKNOWN, ctxt_pP->instance, msg_p);
  }
# else
  {
    char        message_string[10000];
    size_t      message_string_size;

    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_LTE_DL_CCCH_Message, (void *)dl_ccch_msg)) > 0) {
      MessageDef *msg_p;

      msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);

      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
    }
  }
# endif
#endif

  if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) {
    LOG_E(RRC,"[UE %d] Frame %d : Failed to decode DL-CCCH-Message (%zu bytes)\n",ctxt_pP->module_id,ctxt_pP->frame,dec_rval.consumed);
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT);
    return -1;
  }

  if (dl_ccch_msg->message.present == LTE_DL_CCCH_MessageType_PR_c1) {

    if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_SI_RECEIVED) {

      switch (dl_ccch_msg->message.choice.c1.present) {

      case LTE_DL_CCCH_MessageType__c1_PR_NOTHING:
        LOG_I(RRC, "[UE%d] Frame %d : Received PR_NOTHING on DL-CCCH-Message\n",
              ctxt_pP->module_id,
              ctxt_pP->frame);
        rval = 0;
        break;

      case LTE_DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment:
        LOG_I(RRC,
              "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishment\n",
              ctxt_pP->module_id,
              ctxt_pP->frame);
        rval = 0;
        break;

      case LTE_DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentReject:
        LOG_I(RRC,
              "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishmentReject\n",
              ctxt_pP->module_id,
              ctxt_pP->frame);
        rval = 0;
        break;

      case LTE_DL_CCCH_MessageType__c1_PR_rrcConnectionReject:
        LOG_I(RRC,
              "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n",
              ctxt_pP->module_id,
              ctxt_pP->frame);
        rval = 0;
        break;

      case LTE_DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
        LOG_I(RRC,
              "[UE%d][RAPROC] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup RNTI %x\n",
              ctxt_pP->module_id,
              ctxt_pP->frame,
              ctxt_pP->rnti);
        // Get configuration

        // Release T300 timer
        UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].T300_active = 0;
        rrc_ue_process_radioResourceConfigDedicated(
          ctxt_pP,
          eNB_index,
          &dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.criticalExtensions.choice.c1.choice.rrcConnectionSetup_r8.radioResourceConfigDedicated);

        rrc_set_state (ctxt_pP->module_id, RRC_STATE_CONNECTED);
        rrc_set_sub_state (ctxt_pP->module_id, RRC_SUB_STATE_CONNECTED);
        UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].rnti = ctxt_pP->rnti;
        rrc_ue_generate_RRCConnectionSetupComplete(
          ctxt_pP,
          eNB_index,
          dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier);

        rval = 0;
        break;

      default:
        LOG_E(RRC, "[UE%d] Frame %d : Unknown message\n",
              ctxt_pP->module_id,
              ctxt_pP->frame);
        rval = -1;
        break;
      }
    }
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT);
  return rval;
}

//-----------------------------------------------------------------------------
int32_t
rrc_ue_establish_srb1(
  module_id_t ue_mod_idP,
  frame_t frameP,
  uint8_t eNB_index,
  struct LTE_SRB_ToAddMod* SRB_config
)
//-----------------------------------------------------------------------------
{
  // add descriptor from RRC PDU


  UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Active = 1;
  UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Status = RADIO_CONFIG_OK;//RADIO CFG
  UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Srb_id = 1;

  // copy default configuration for now
  //  memcpy(&UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Lchan_desc[0],&DCCH_LCHAN_DESC,LCHAN_DESC_SIZE);
  //  memcpy(&UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Lchan_desc[1],&DCCH_LCHAN_DESC,LCHAN_DESC_SIZE);


  LOG_I(RRC,"[UE %d], CONFIG_SRB1 %d corresponding to eNB_index %d\n", ue_mod_idP,DCCH,eNB_index);

  //rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, lchan_id,UNDEF_SECURITY_MODE);
  //  rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,lchan_id,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);

  //  UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Tx_buffer.payload_size=DEFAULT_MEAS_IND_SIZE+1;


  return(0);
}

//-----------------------------------------------------------------------------
int32_t
rrc_ue_establish_srb2(
  module_id_t ue_mod_idP,
  frame_t frameP,
  uint8_t eNB_index,
  struct LTE_SRB_ToAddMod* SRB_config
)
//-----------------------------------------------------------------------------
{
  // add descriptor from RRC PDU


  UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Active = 1;
  UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Status = RADIO_CONFIG_OK;//RADIO CFG
  UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Srb_info.Srb_id = 2;

  // copy default configuration for now
  //  memcpy(&UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Srb_info.Lchan_desc[0],&DCCH_LCHAN_DESC,LCHAN_DESC_SIZE);
  //  memcpy(&UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Srb_info.Lchan_desc[1],&DCCH_LCHAN_DESC,LCHAN_DESC_SIZE);


  LOG_I(RRC,"[UE %d], CONFIG_SRB2 %d corresponding to eNB_index %d\n",ue_mod_idP,DCCH1,eNB_index);

  //rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, lchan_id, UNDEF_SECURITY_MODE);
  //  rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,lchan_id,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);

  //  UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Srb_info.Tx_buffer.payload_size=DEFAULT_MEAS_IND_SIZE+1;


  return(0);
}

//-----------------------------------------------------------------------------
int32_t
rrc_ue_establish_drb(
  module_id_t ue_mod_idP,
  frame_t frameP,
  uint8_t eNB_index,
  struct LTE_DRB_ToAddMod* DRB_config
)
//-----------------------------------------------------------------------------
{
  // add descriptor from RRC PDU
#ifdef PDCP_USE_NETLINK
  int oip_ifup=0,ip_addr_offset3=0,ip_addr_offset4=0;
  /* avoid gcc warnings */
  (void)oip_ifup;
  (void)ip_addr_offset3;
  (void)ip_addr_offset4;
#endif

  LOG_I(RRC,"[UE %d] Frame %d: processing RRCConnectionReconfiguration: reconfiguring DRB %ld/LCID %d\n",
        ue_mod_idP, frameP, DRB_config->drb_Identity, (int)*DRB_config->logicalChannelIdentity);
  /*
  rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD,
                             (eNB_index * NB_RB_MAX) + *DRB_config->logicalChannelIdentity, UNDEF_SECURITY_MODE);

  rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,
                    (eNB_index * NB_RB_MAX) + *DRB_config->logicalChannelIdentity,
                    RADIO_ACCESS_BEARER,Rlc_info_um);
   */
#ifdef PDCP_USE_NETLINK
#   if !defined(OAI_NW_DRIVER_TYPE_ETHERNET) && !defined(EXMIMO) && !defined(OAI_USRP) && !defined(OAI_BLADERF) && !defined(ETHERNET) && !defined(LINK_ENB_PDCP_TO_GTPV1U)
  ip_addr_offset3 = 0;
  ip_addr_offset4 = 1;
  LOG_I(OIP,"[UE %d] trying to bring up the OAI interface oai%d, IP 10.0.%d.%d\n", ue_mod_idP, ip_addr_offset3+ue_mod_idP,
        ip_addr_offset3+ue_mod_idP+1,ip_addr_offset4+ue_mod_idP+1);
  oip_ifup=nas_config(ip_addr_offset3+ue_mod_idP,   // interface_id
                      ip_addr_offset3+ue_mod_idP+1, // third_octet
                      ip_addr_offset4+ue_mod_idP+1); // fourth_octet

  if (oip_ifup == 0 ) { // interface is up --> send a config the DRB
    LOG_I(OIP,"[UE %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n",
          ue_mod_idP,
          ip_addr_offset3+ue_mod_idP,
          (long int)((eNB_index * maxDRB) + DRB_config->drb_Identity));

    rb_conf_ipv4(0,//add
                 ue_mod_idP,//cx align with the UE index
                 ip_addr_offset3+ue_mod_idP,//inst num_enb+ue_index
                 (eNB_index * maxDRB) + DRB_config->drb_Identity,//rb
                 0,//dscp
                 ipv4_address(ip_addr_offset3+ue_mod_idP+1,ip_addr_offset4+ue_mod_idP+1),//saddr
                 ipv4_address(ip_addr_offset3+ue_mod_idP+1,eNB_index+1));//daddr
    LOG_D(RRC,"[UE %d] State = Attached (eNB %d)\n",ue_mod_idP,eNB_index);
  }

#    endif
#endif

  return(0);
}


//-----------------------------------------------------------------------------
void
rrc_ue_process_measConfig(
  const protocol_ctxt_t* const       ctxt_pP,
  const uint8_t                      eNB_index,
  LTE_MeasConfig_t* const               measConfig
)
//-----------------------------------------------------------------------------
{

  // This is the procedure described in 36.331 Section 5.5.2.1
  int i;
  long ind;
  LTE_MeasObjectToAddMod_t *measObj;

  if (measConfig->measObjectToRemoveList != NULL) {
    for (i=0; i<measConfig->measObjectToRemoveList->list.count; i++) {
      ind   = *measConfig->measObjectToRemoveList->list.array[i];
      free(UE_rrc_inst[ctxt_pP->module_id].MeasObj[eNB_index][ind-1]);
    }
  }

  if (measConfig->measObjectToAddModList != NULL) {
    LOG_D(RRC,"Measurement Object List is present\n");

    for (i=0; i<measConfig->measObjectToAddModList->list.count; i++) {
      measObj = measConfig->measObjectToAddModList->list.array[i];
      ind   = measConfig->measObjectToAddModList->list.array[i]->measObjectId;

      if (UE_rrc_inst[ctxt_pP->module_id].MeasObj[eNB_index][ind-1]) {
        LOG_D(RRC,"Modifying measurement object %ld\n",ind);
        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].MeasObj[eNB_index][ind-1],
               (char*)measObj,
               sizeof(LTE_MeasObjectToAddMod_t));
      } else {
        LOG_I(RRC,"Adding measurement object %ld\n",ind);

        if (measObj->measObject.present == LTE_MeasObjectToAddMod__measObject_PR_measObjectEUTRA) {
          LOG_I(RRC,"EUTRA Measurement : carrierFreq %ld, allowedMeasBandwidth %ld,presenceAntennaPort1 %d, neighCellConfig %d\n",
                measObj->measObject.choice.measObjectEUTRA.carrierFreq,
                measObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth,
                measObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1,
                measObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0]);
          UE_rrc_inst[ctxt_pP->module_id].MeasObj[eNB_index][ind-1]=measObj;
        }
      }
    }

    LOG_I(RRC,"call rrc_mac_config_req \n");

    rrc_mac_config_req_ue(ctxt_pP->module_id,0,eNB_index,
			  (LTE_RadioResourceConfigCommonSIB_t *)NULL,
			  (struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			  (LTE_SCellToAddMod_r10_t *)NULL,
			  //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
			  UE_rrc_inst[ctxt_pP->module_id].MeasObj[eNB_index],
			  (LTE_MAC_MainConfig_t *)NULL,
			  0,
			  (struct LTE_LogicalChannelConfig *)NULL,
			  (LTE_MeasGapConfig_t *)NULL,
			  (LTE_TDD_Config_t *)NULL,
			  (LTE_MobilityControlInfo_t *)NULL,
			  NULL,
			  NULL,
			  NULL,
			  NULL,
			  NULL,
			  NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
			  ,0,
			  (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
			  (LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
			  ,
			  0,
			  0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			  );
  }

  if (measConfig->reportConfigToRemoveList != NULL) {
    for (i=0; i<measConfig->reportConfigToRemoveList->list.count; i++) {
      ind   = *measConfig->reportConfigToRemoveList->list.array[i];
      free(UE_rrc_inst[ctxt_pP->module_id].ReportConfig[eNB_index][ind-1]);
    }
  }

  if (measConfig->reportConfigToAddModList != NULL) {
    LOG_I(RRC,"Report Configuration List is present\n");

    for (i=0; i<measConfig->reportConfigToAddModList->list.count; i++) {
      ind   = measConfig->reportConfigToAddModList->list.array[i]->reportConfigId;

      if (UE_rrc_inst[ctxt_pP->module_id].ReportConfig[eNB_index][ind-1]) {
        LOG_I(RRC,"Modifying Report Configuration %ld\n",ind-1);
        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].ReportConfig[eNB_index][ind-1],
               (char*)measConfig->reportConfigToAddModList->list.array[i],
               sizeof(LTE_ReportConfigToAddMod_t));
      } else {
        LOG_D(RRC,"Adding Report Configuration %ld %p \n",ind-1,measConfig->reportConfigToAddModList->list.array[i]);
        UE_rrc_inst[ctxt_pP->module_id].ReportConfig[eNB_index][ind-1] = measConfig->reportConfigToAddModList->list.array[i];
      }
    }
  }

  if (measConfig->quantityConfig != NULL) {
    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index]) {
      LOG_D(RRC,"Modifying Quantity Configuration \n");
      memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index],
             (char*)measConfig->quantityConfig,
             sizeof(LTE_QuantityConfig_t));
    } else {
      LOG_D(RRC,"Adding Quantity configuration\n");
      UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index] = measConfig->quantityConfig;
    }
  }

  if (measConfig->measIdToRemoveList != NULL) {
    for (i=0; i<measConfig->measIdToRemoveList->list.count; i++) {
      ind   = *measConfig->measIdToRemoveList->list.array[i];
      free(UE_rrc_inst[ctxt_pP->module_id].MeasId[eNB_index][ind-1]);
    }
  }

  if (measConfig->measIdToAddModList != NULL) {
    for (i=0; i<measConfig->measIdToAddModList->list.count; i++) {
      ind   = measConfig->measIdToAddModList->list.array[i]->measId;

      if (UE_rrc_inst[ctxt_pP->module_id].MeasId[eNB_index][ind-1]) {
        LOG_D(RRC,"Modifying Measurement ID %ld\n",ind-1);
        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].MeasId[eNB_index][ind-1],
               (char*)measConfig->measIdToAddModList->list.array[i],
               sizeof(LTE_MeasIdToAddMod_t));
      } else {
        LOG_D(RRC,"Adding Measurement ID %ld %p\n",ind-1,measConfig->measIdToAddModList->list.array[i]);
        UE_rrc_inst[ctxt_pP->module_id].MeasId[eNB_index][ind-1] = measConfig->measIdToAddModList->list.array[i];
      }
    }
  }

  if (measConfig->measGapConfig !=NULL) {
    if (UE_rrc_inst[ctxt_pP->module_id].measGapConfig[eNB_index]) {
      memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].measGapConfig[eNB_index],
             (char*)measConfig->measGapConfig,
             sizeof(LTE_MeasGapConfig_t));
    } else {
      UE_rrc_inst[ctxt_pP->module_id].measGapConfig[eNB_index] = measConfig->measGapConfig;
    }
  }

  if (measConfig->quantityConfig != NULL) {
    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index]) {
      LOG_I(RRC,"Modifying Quantity Configuration \n");
      memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index],
             (char*)measConfig->quantityConfig,
             sizeof(LTE_QuantityConfig_t));
    } else {
      LOG_I(RRC,"Adding Quantity configuration\n");
      UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index] = measConfig->quantityConfig;
    }

    UE_rrc_inst[ctxt_pP->module_id].filter_coeff_rsrp = 1./pow(2,
        (*UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index]->quantityConfigEUTRA->filterCoefficientRSRP)/4);
    UE_rrc_inst[ctxt_pP->module_id].filter_coeff_rsrq = 1./pow(2,
        (*UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index]->quantityConfigEUTRA->filterCoefficientRSRQ)/4);

    LOG_I(RRC,"[UE %d] set rsrp-coeff for eNB %d: %ld rsrq-coeff: %ld rsrp_factor: %f rsrq_factor: %f \n",
          ctxt_pP->module_id, eNB_index, // UE_rrc_inst[ue_mod_idP].Info[eNB_index].UE_index,
          *UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index]->quantityConfigEUTRA->filterCoefficientRSRP,
          *UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[eNB_index]->quantityConfigEUTRA->filterCoefficientRSRQ,
          UE_rrc_inst[ctxt_pP->module_id].filter_coeff_rsrp,
          UE_rrc_inst[ctxt_pP->module_id].filter_coeff_rsrq);
  }

  if (measConfig->s_Measure != NULL) {
    UE_rrc_inst[ctxt_pP->module_id].s_measure = *measConfig->s_Measure;
  }

  if (measConfig->speedStatePars != NULL) {
    if (UE_rrc_inst[ctxt_pP->module_id].speedStatePars) {
      memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].speedStatePars,(char*)measConfig->speedStatePars,sizeof(struct LTE_MeasConfig__speedStatePars));
    } else {
      UE_rrc_inst[ctxt_pP->module_id].speedStatePars = measConfig->speedStatePars;
    }

    LOG_I(RRC,"[UE %d] Configuring mobility optimization params for UE %d \n",
          ctxt_pP->module_id,UE_rrc_inst[ctxt_pP->module_id].Info[0].UE_index);
  }
}


void
rrc_ue_update_radioResourceConfigDedicated(LTE_RadioResourceConfigDedicated_t* radioResourceConfigDedicated,
        const protocol_ctxt_t* const ctxt_pP,
        uint8_t eNB_index)
{
    LTE_PhysicalConfigDedicated_t* physicalConfigDedicated2 = NULL;

    physicalConfigDedicated2 = CALLOC(1,sizeof(*physicalConfigDedicated2));
    physicalConfigDedicated2->pdsch_ConfigDedicated         = CALLOC(1,sizeof(*physicalConfigDedicated2->pdsch_ConfigDedicated));
    physicalConfigDedicated2->pusch_ConfigDedicated         = CALLOC(1,sizeof(*physicalConfigDedicated2->pusch_ConfigDedicated));
    physicalConfigDedicated2->pucch_ConfigDedicated         = CALLOC(1,sizeof(*physicalConfigDedicated2->pucch_ConfigDedicated));
    physicalConfigDedicated2->cqi_ReportConfig              = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
    physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic
                                                            = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic));
    physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
    physicalConfigDedicated2->schedulingRequestConfig       = CALLOC(1,sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
    physicalConfigDedicated2->antennaInfo                   = CALLOC(1,sizeof(*physicalConfigDedicated2->antennaInfo));

    physicalConfigDedicated2->uplinkPowerControlDedicated   = CALLOC(1,sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated));
    physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH         = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
    physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH         = CALLOC(1,sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));

    // Update pdsch_ConfigDedicated
    if(radioResourceConfigDedicated->physicalConfigDedicated->pdsch_ConfigDedicated != NULL)
    {
        LOG_I(RRC,"Update pdsch_ConfigDedicated config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated = CALLOC(1,sizeof(LTE_PDSCH_ConfigDedicated_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pdsch_ConfigDedicated,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->pdsch_ConfigDedicated,
                sizeof(physicalConfigDedicated2->pdsch_ConfigDedicated));
    }
    else
    {
        LOG_I(RRC,"Keep old config for pdsch_ConfigDedicated\n");
    }

    // Update pusch_ConfigDedicated
    if(radioResourceConfigDedicated->physicalConfigDedicated->pusch_ConfigDedicated != NULL)
    {
        LOG_I(RRC,"Update pusch_ConfigDedicated config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated = CALLOC(1,sizeof(LTE_PUSCH_ConfigDedicated_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pusch_ConfigDedicated,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->pusch_ConfigDedicated,
                sizeof(physicalConfigDedicated2->pusch_ConfigDedicated));
    }
    else
    {
        LOG_I(RRC,"Keep old config for pusch_ConfigDedicated\n");
    }

    // Update pucch_ConfigDedicated
    if(radioResourceConfigDedicated->physicalConfigDedicated->pucch_ConfigDedicated != NULL)
    {
        LOG_I(RRC,"Update pucch_ConfigDedicated config \n");
        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated = CALLOC(1,sizeof(LTE_PUCCH_ConfigDedicated_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->pucch_ConfigDedicated,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->pucch_ConfigDedicated,
                sizeof(physicalConfigDedicated2->pucch_ConfigDedicated));
    }
    else
    {
        LOG_I(RRC,"Keep old config for pucch_ConfigDedicated\n");
    }

    // Update cqi_ReportConfig
    if(radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig != NULL)
    {
        LOG_I(RRC,"Update cqi_ReportConfig config (size=%zu,%zu)\n", sizeof(*physicalConfigDedicated2->cqi_ReportConfig), sizeof(LTE_CQI_ReportConfig_t));

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig = CALLOC(1,sizeof(LTE_CQI_ReportConfig_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig,
                sizeof(*physicalConfigDedicated2->cqi_ReportConfig));

        if (radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic != NULL) {
          LOG_I(RRC,"Update cqi_ReportPeriodic config (size=%zu,%zu)\n", sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic), sizeof(LTE_CQI_ReportPeriodic_t));

          if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig->cqi_ReportPeriodic == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig->cqi_ReportPeriodic = CALLOC(1,sizeof(LTE_CQI_ReportPeriodic_t));

          memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->cqi_ReportConfig->cqi_ReportPeriodic,
                  (char*)radioResourceConfigDedicated->physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic,
                  sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic));
        }
    }
    else
    {
        LOG_I(RRC,"Keep old config for cqi_ReportConfig\n");
    }

    // Update schedulingRequestConfig
    if(radioResourceConfigDedicated->physicalConfigDedicated->schedulingRequestConfig != NULL)
    {
        LOG_I(RRC,"Update schedulingRequestConfig config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig = CALLOC(1,sizeof(LTE_SchedulingRequestConfig_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->schedulingRequestConfig,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->schedulingRequestConfig,
                sizeof(physicalConfigDedicated2->schedulingRequestConfig));
    }
    else
    {
        LOG_I(RRC,"Keep old config for schedulingRequestConfig\n");
    }

    // Update soundingRS_UL_ConfigDedicated
    if(radioResourceConfigDedicated->physicalConfigDedicated->soundingRS_UL_ConfigDedicated != NULL)
    {
        LOG_I(RRC,"Update soundingRS_UL_ConfigDedicated config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated = CALLOC(1,sizeof(LTE_SoundingRS_UL_ConfigDedicated_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->soundingRS_UL_ConfigDedicated,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->soundingRS_UL_ConfigDedicated,
                sizeof(physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
    }
    else
    {
        LOG_I(RRC,"Keep old config for soundingRS_UL_ConfigDedicated\n");
    }

    // Update antennaInfo
    if(radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo != NULL)
    {
        LOG_I(RRC,"Update antennaInfo config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo = CALLOC(1,sizeof(struct LTE_PhysicalConfigDedicated__antennaInfo));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo,
                sizeof(physicalConfigDedicated2->antennaInfo));

        UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.transmissionMode =
        		radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode;
        UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.codebookSubsetRestriction =
        		radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.codebookSubsetRestriction;
        UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection =
        		radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection;

        LOG_I(PHY,"New Transmission Mode %ld \n",radioResourceConfigDedicated->physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
        LOG_I(PHY,"Configured Transmission Mode %ld \n",UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->antennaInfo->choice.explicitValue.transmissionMode);

    }
    else
    {
        LOG_I(RRC,"Keep old config for antennaInfo\n");
    }


    // Update uplinkPowerControlDedicated
    if(radioResourceConfigDedicated->physicalConfigDedicated->uplinkPowerControlDedicated != NULL)
    {
        LOG_I(RRC,"Update uplinkPowerControlDedicated config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated = CALLOC(1,sizeof(LTE_UplinkPowerControlDedicated_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->uplinkPowerControlDedicated,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->uplinkPowerControlDedicated,
                sizeof(physicalConfigDedicated2->uplinkPowerControlDedicated));
    }
    else
    {
        LOG_I(RRC,"Keep old config for uplinkPowerControlDedicated\n");
    }

    // Update tpc_PDCCH_ConfigPUCCH
    if(radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUCCH != NULL)
    {
        LOG_I(RRC,"Update tpc_PDCCH_ConfigPUCCH config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH = CALLOC(1,sizeof(LTE_TPC_PDCCH_Config_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUCCH,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUCCH,
                sizeof(physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
    }
    else
    {
        LOG_I(RRC,"Keep old config for tpc_PDCCH_ConfigPUCCH\n");
    }

    // Update tpc_PDCCH_ConfigPUSCH
    if(radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUSCH != NULL)
    {
        LOG_I(RRC,"Update tpc_PDCCH_ConfigPUSCH config \n");

        if(UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH == NULL)
            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH = CALLOC(1,sizeof(LTE_TPC_PDCCH_Config_t));

        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]->tpc_PDCCH_ConfigPUSCH,
                (char*)radioResourceConfigDedicated->physicalConfigDedicated->tpc_PDCCH_ConfigPUSCH,
                sizeof(physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));

    }
    else
    {
        LOG_I(RRC,"Keep old config for tpc_PDCCH_ConfigPUSCH\n");
    }

}
//-----------------------------------------------------------------------------
void
rrc_ue_process_radioResourceConfigDedicated(
  const protocol_ctxt_t* const ctxt_pP,
  uint8_t eNB_index,
  LTE_RadioResourceConfigDedicated_t* radioResourceConfigDedicated
)
//-----------------------------------------------------------------------------
{

  long SRB_id,DRB_id;
  int i,cnt;
  LTE_LogicalChannelConfig_t *SRB1_logicalChannelConfig,*SRB2_logicalChannelConfig;
#ifdef CBA
  uint8_t cba_found = 0;
  uint16_t cba_RNTI;
#endif

  // Save physicalConfigDedicated if present
  if (radioResourceConfigDedicated->physicalConfigDedicated) {
    LOG_I(RRC,"Save physicalConfigDedicated if present \n");

    if (UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index]) {
#if 1
        rrc_ue_update_radioResourceConfigDedicated(radioResourceConfigDedicated, ctxt_pP, eNB_index);
#else
      memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],(char*)radioResourceConfigDedicated->physicalConfigDedicated,
             sizeof(struct PhysicalConfigDedicated));
#endif
    } else {
      LOG_I(RRC,"Init physicalConfigDedicated UE_rrc_inst to radioResourceConfigDedicated->physicalConfigDedicated\n");
      UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index] = radioResourceConfigDedicated->physicalConfigDedicated;
    }
  }

  // Apply macMainConfig if present
  if (radioResourceConfigDedicated->mac_MainConfig) {
    if (radioResourceConfigDedicated->mac_MainConfig->present == LTE_RadioResourceConfigDedicated__mac_MainConfig_PR_explicitValue) {
      if (UE_rrc_inst[ctxt_pP->module_id].mac_MainConfig[eNB_index]) {
        memcpy((char*)UE_rrc_inst[ctxt_pP->module_id].mac_MainConfig[eNB_index],(char*)&radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue,
               sizeof(LTE_MAC_MainConfig_t));
      } else {
        UE_rrc_inst[ctxt_pP->module_id].mac_MainConfig[eNB_index] = &radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue;
      }
    }
  }

  // Apply spsConfig if present
  if (radioResourceConfigDedicated->sps_Config) {
    if (UE_rrc_inst[ctxt_pP->module_id].sps_Config[eNB_index]) {
      memcpy(UE_rrc_inst[ctxt_pP->module_id].sps_Config[eNB_index],radioResourceConfigDedicated->sps_Config,
             sizeof(struct LTE_SPS_Config));
    } else {
      UE_rrc_inst[ctxt_pP->module_id].sps_Config[eNB_index] = radioResourceConfigDedicated->sps_Config;
    }
  }

#ifdef CBA

  if (radioResourceConfigDedicated->cba_RNTI_vlola) {
    cba_RNTI = (uint16_t) (((radioResourceConfigDedicated->cba_RNTI_vlola->buf[1]&0xff) << 8) |
                           (radioResourceConfigDedicated->cba_RNTI_vlola->buf[0]&0xff));

    for (i=0 ; i< NUM_MAX_CBA_GROUP; i++) {
      if (UE_rrc_inst[ctxt_pP->module_id].cba_rnti[i] == cba_RNTI ) {
        cba_found=1;
        break;
      } else if (UE_rrc_inst[ctxt_pP->module_id].cba_rnti[i] == 0 ) {
        break;
      }
    }

    if (cba_found==0) {
      UE_rrc_inst[ctxt_pP->module_id].num_active_cba_groups++;
      UE_rrc_inst[ctxt_pP->module_id].cba_rnti[i]=cba_RNTI;
      LOG_D(RRC, "[UE %d] Frame %d: radioResourceConfigDedicated reveived CBA_RNTI = %x for group %d from eNB %d \n",
            ctxt_pP->module_id,frameP, UE_rrc_inst[ctxt_pP->module_id].cba_rnti[i], i, eNB_index);
    }
  }

#endif

  // Establish SRBs if present
  // loop through SRBToAddModList
  if (radioResourceConfigDedicated->srb_ToAddModList) {
    uint8_t *kRRCenc = NULL;
    uint8_t *kRRCint = NULL;

#if defined(ENABLE_SECURITY)
    derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
                       UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
    derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
                       UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
#endif
    // Refresh SRBs
    rrc_pdcp_config_asn1_req(ctxt_pP,
                             radioResourceConfigDedicated->srb_ToAddModList,
                             (LTE_DRB_ToAddModList_t*)NULL,
                             (LTE_DRB_ToReleaseList_t*)NULL,
                             UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm |
                             (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4),
                             kRRCenc,
                             kRRCint,
                             NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
                             ,(LTE_PMCH_InfoList_r9_t *)NULL
#endif
                             ,NULL);

    // Refresh SRBs
    rrc_rlc_config_asn1_req(ctxt_pP,
                            radioResourceConfigDedicated->srb_ToAddModList,
                            (LTE_DRB_ToAddModList_t*)NULL,
                            (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
                            ,(LTE_PMCH_InfoList_r9_t *)NULL
                            , 0, 0
#endif
                           );

#if ENABLE_RAL
    // first msg that includes srb config
    UE_rrc_inst[ctxt_pP->module_id].num_srb=radioResourceConfigDedicated->srb_ToAddModList->list.count;
#endif

    for (cnt=0; cnt<radioResourceConfigDedicated->srb_ToAddModList->list.count; cnt++) {
      //  connection_reestablishment_ind.num_srb+=1;
      SRB_id = radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt]->srb_Identity;
      LOG_D(RRC,"[UE %d]: Frame %d SRB config cnt %d (SRB%ld)\n",ctxt_pP->module_id,ctxt_pP->frame,cnt,SRB_id);

      if (SRB_id == 1) {
        if (UE_rrc_inst[ctxt_pP->module_id].SRB1_config[eNB_index]) {
          memcpy(UE_rrc_inst[ctxt_pP->module_id].SRB1_config[eNB_index],radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt],
                 sizeof(struct LTE_SRB_ToAddMod));
        } else {
          UE_rrc_inst[ctxt_pP->module_id].SRB1_config[eNB_index] = radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt];
          rrc_ue_establish_srb1(ctxt_pP->module_id,ctxt_pP->frame,eNB_index,radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt]);

          if (UE_rrc_inst[ctxt_pP->module_id].SRB1_config[eNB_index]->logicalChannelConfig) {
            if (UE_rrc_inst[ctxt_pP->module_id].SRB1_config[eNB_index]->logicalChannelConfig->present == LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
              SRB1_logicalChannelConfig = &UE_rrc_inst[ctxt_pP->module_id].SRB1_config[eNB_index]->logicalChannelConfig->choice.explicitValue;

            } else {
              SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
            }
          } else {
            SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
          }

          LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);

          rrc_mac_config_req_ue(ctxt_pP->module_id,0,eNB_index,
				(LTE_RadioResourceConfigCommonSIB_t *)NULL,
				UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
				(LTE_SCellToAddMod_r10_t *)NULL,
				//struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
				(LTE_MeasObjectToAddMod_t **)NULL,
				UE_rrc_inst[ctxt_pP->module_id].mac_MainConfig[eNB_index],
				1,
				SRB1_logicalChannelConfig,
				(LTE_MeasGapConfig_t *)NULL,
				NULL,
				NULL,
				NULL,
				NULL,
				NULL,
				NULL,
				NULL,
				NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
				,
				0,
				(LTE_MBSFN_AreaInfoList_r9_t *)NULL,
				(LTE_PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
				,
				0,
				0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
				);
        }
      } else {
        if (UE_rrc_inst[ctxt_pP->module_id].SRB2_config[eNB_index]) {
          memcpy(UE_rrc_inst[ctxt_pP->module_id].SRB2_config[eNB_index],radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt],
                 sizeof(struct LTE_SRB_ToAddMod));
        } else {
          UE_rrc_inst[ctxt_pP->module_id].SRB2_config[eNB_index] = radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt];
          rrc_ue_establish_srb2(ctxt_pP->module_id,ctxt_pP->frame,eNB_index,radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt]);

          if (UE_rrc_inst[ctxt_pP->module_id].SRB2_config[eNB_index]->logicalChannelConfig) {
            if (UE_rrc_inst[ctxt_pP->module_id].SRB2_config[eNB_index]->logicalChannelConfig->present == LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
              LOG_I(RRC,"Applying Explicit SRB2 logicalChannelConfig\n");
              SRB2_logicalChannelConfig = &UE_rrc_inst[ctxt_pP->module_id].SRB2_config[eNB_index]->logicalChannelConfig->choice.explicitValue;
            } else {
              LOG_I(RRC,"Applying default SRB2 logicalChannelConfig\n");
              SRB2_logicalChannelConfig = &SRB2_logicalChannelConfig_defaultValue;
            }
          } else {
            SRB2_logicalChannelConfig = &SRB2_logicalChannelConfig_defaultValue;
          }

          LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                ctxt_pP->frame,
                ctxt_pP->module_id,
                eNB_index,
                ctxt_pP->module_id);
          rrc_mac_config_req_ue(ctxt_pP->module_id,0,eNB_index,
				(LTE_RadioResourceConfigCommonSIB_t *)NULL,
				UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
				(LTE_SCellToAddMod_r10_t *)NULL,
				//struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
				(LTE_MeasObjectToAddMod_t **)NULL,
				UE_rrc_inst[ctxt_pP->module_id].mac_MainConfig[eNB_index],
				2,
				SRB2_logicalChannelConfig,
				UE_rrc_inst[ctxt_pP->module_id].measGapConfig[eNB_index],
				(LTE_TDD_Config_t *)NULL,
				(LTE_MobilityControlInfo_t *)NULL,
				NULL,
				NULL,
				NULL,
				NULL,
				NULL,
				NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
				,
				0,
				(LTE_MBSFN_AreaInfoList_r9_t *)NULL,
				(LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
				,
				0,
				0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
				);
        }
      }
    }
  }

  // Establish DRBs if present
  if (radioResourceConfigDedicated->drb_ToAddModList) {

    if ( (UE_rrc_inst[ctxt_pP->module_id].defaultDRB == NULL) &&
         (radioResourceConfigDedicated->drb_ToAddModList->list.count >= 1) ) {
        // configure the first DRB ID as the default DRB ID
        UE_rrc_inst[ctxt_pP->module_id].defaultDRB = malloc(sizeof(rb_id_t));
        *UE_rrc_inst[ctxt_pP->module_id].defaultDRB = radioResourceConfigDedicated->drb_ToAddModList->list.array[0]->drb_Identity;
        LOG_I(RRC,"[UE %d] default DRB = %d\n",ctxt_pP->module_id, *UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
      }

    uint8_t *kUPenc = NULL;

#if defined(ENABLE_SECURITY)
    derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
                      UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
#endif

    MSC_LOG_TX_MESSAGE(
      MSC_RRC_UE,
      MSC_PDCP_UE,
      NULL,
      0,
      MSC_AS_TIME_FMT" CONFIG_REQ UE %x DRB (security %X)",
      MSC_AS_TIME_ARGS(ctxt_pP),
      ctxt_pP->rnti,
      UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm |
      (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4));

    // Refresh DRBs
    rrc_pdcp_config_asn1_req(ctxt_pP,
                             (LTE_SRB_ToAddModList_t*)NULL,
                             radioResourceConfigDedicated->drb_ToAddModList,
                             (LTE_DRB_ToReleaseList_t*)NULL,
                             UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm |
                             (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4),
                             NULL,
                             NULL,
                             kUPenc
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
                             ,(LTE_PMCH_InfoList_r9_t *)NULL
#endif
                             , UE_rrc_inst[ctxt_pP->module_id].defaultDRB);

    // Refresh DRBs
    rrc_rlc_config_asn1_req(ctxt_pP,
                            (LTE_SRB_ToAddModList_t*)NULL,
                            radioResourceConfigDedicated->drb_ToAddModList,
                            (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
                            ,(LTE_PMCH_InfoList_r9_t *)NULL
                            , 0, 0
#endif
                           );

    for (i=0; i<radioResourceConfigDedicated->drb_ToAddModList->list.count; i++) {
      DRB_id   = radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity-1;

      if (UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id]) {
        memcpy(UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id],
               radioResourceConfigDedicated->drb_ToAddModList->list.array[i],
               sizeof(struct LTE_DRB_ToAddMod));
      } else {
        UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id] = radioResourceConfigDedicated->drb_ToAddModList->list.array[i];
        rrc_ue_establish_drb(ctxt_pP->module_id,ctxt_pP->frame,eNB_index,radioResourceConfigDedicated->drb_ToAddModList->list.array[i]);
        // MAC/PHY Configuration
        LOG_I(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB %ld eNB %d) --->][MAC_UE][MOD %02d][]\n",
              ctxt_pP->frame, ctxt_pP->module_id,
              radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity,
              eNB_index,
              ctxt_pP->module_id);
        rrc_mac_config_req_ue(ctxt_pP->module_id,0,eNB_index,
			      (LTE_RadioResourceConfigCommonSIB_t *)NULL,
			      UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			      (LTE_SCellToAddMod_r10_t *)NULL,
			      //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
			      (LTE_MeasObjectToAddMod_t **)NULL,
			      UE_rrc_inst[ctxt_pP->module_id].mac_MainConfig[eNB_index],
			      *UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id]->logicalChannelIdentity,
			      UE_rrc_inst[ctxt_pP->module_id].DRB_config[eNB_index][DRB_id]->logicalChannelConfig,
			      UE_rrc_inst[ctxt_pP->module_id].measGapConfig[eNB_index],
			      (LTE_TDD_Config_t*)NULL,
			      (LTE_MobilityControlInfo_t *)NULL,
			      NULL,
			      NULL,
			      NULL,
			      NULL,
			      NULL,
			      NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
			      ,
			      0,
			      (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
			      (LTE_PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
			      ,
			      UE_rrc_inst[ue_mod_idP].num_active_cba_groups, //
			      UE_rrc_inst[ue_mod_idP].cba_rnti[0]
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			      );

      }
    }
  }

  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_CONNECTED;
  LOG_I(RRC,"[UE %d] State = RRC_CONNECTED (eNB %d)\n",ctxt_pP->module_id,eNB_index);
}


//-----------------------------------------------------------------------------
void
rrc_ue_process_securityModeCommand(
  const protocol_ctxt_t* const ctxt_pP,
  LTE_SecurityModeCommand_t* const securityModeCommand,
  const uint8_t                eNB_index
)
//-----------------------------------------------------------------------------
{

  asn_enc_rval_t enc_rval;

  LTE_UL_DCCH_Message_t ul_dcch_msg;
  // SecurityModeCommand_t SecurityModeCommand;
  uint8_t buffer[200];
  int i, securityMode;

  LOG_I(RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), Processing securityModeCommand (eNB %d)\n",
        ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, eNB_index);

  switch (securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm) {
  case LTE_CipheringAlgorithm_r12_eea0:
    LOG_I(RRC,"[UE %d] Security algorithm is set to eea0\n",
          ctxt_pP->module_id);
    securityMode= LTE_CipheringAlgorithm_r12_eea0;
    break;

  case LTE_CipheringAlgorithm_r12_eea1:
    LOG_I(RRC,"[UE %d] Security algorithm is set to eea1\n",ctxt_pP->module_id);
    securityMode= LTE_CipheringAlgorithm_r12_eea1;
    break;

  case LTE_CipheringAlgorithm_r12_eea2:
    LOG_I(RRC,"[UE %d] Security algorithm is set to eea2\n",
          ctxt_pP->module_id);
    securityMode = LTE_CipheringAlgorithm_r12_eea2;
    break;

  default:
    LOG_I(RRC,"[UE %d] Security algorithm is set to none\n",ctxt_pP->module_id);
    securityMode = LTE_CipheringAlgorithm_r12_spare1;
    break;
  }

  switch (securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm) {
  case LTE_SecurityAlgorithmConfig__integrityProtAlgorithm_eia1:
    LOG_I(RRC,"[UE %d] Integrity protection algorithm is set to eia1\n",ctxt_pP->module_id);
    securityMode |= 1 << 5;
    break;

  case LTE_SecurityAlgorithmConfig__integrityProtAlgorithm_eia2:
    LOG_I(RRC,"[UE %d] Integrity protection algorithm is set to eia2\n",ctxt_pP->module_id);
    securityMode |= 1 << 6;
    break;

  default:
    LOG_I(RRC,"[UE %d] Integrity protection algorithm is set to none\n",ctxt_pP->module_id);
    securityMode |= 0x70 ;
    break;
  }

  LOG_D(RRC,"[UE %d] security mode is %x \n",ctxt_pP->module_id, securityMode);

  /* Store the parameters received */
  UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm =
    securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm;
  UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm =
    securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm;

  memset((void *)&ul_dcch_msg,0,sizeof(LTE_UL_DCCH_Message_t));
  //memset((void *)&SecurityModeCommand,0,sizeof(SecurityModeCommand_t));

  ul_dcch_msg.message.present           = LTE_UL_DCCH_MessageType_PR_c1;

  if (securityMode >= NO_SECURITY_MODE) {
	  LOG_I(RRC, "rrc_ue_process_securityModeCommand, security mode complete case \n");
    ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_securityModeComplete;
  } else {
	  LOG_I(RRC, "rrc_ue_process_securityModeCommand, security mode failure case \n");
    ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_securityModeFailure;
  }


#if defined(ENABLE_SECURITY)
  uint8_t *kRRCenc = NULL;
  uint8_t *kUPenc = NULL;
  uint8_t *kRRCint = NULL;
  pdcp_t *pdcp_p = NULL;
  hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t h_rc;

  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti,
      ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
  h_rc = hashtable_get(pdcp_coll_p, key, (void**) &pdcp_p);

  if (h_rc == HASH_TABLE_OK) {
    LOG_D(RRC, "PDCP_COLL_KEY_VALUE() returns valid key = %ld\n", key);

    LOG_D(RRC, "driving kRRCenc, kRRCint and kUPenc from KeNB="
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x"
        "%02x%02x%02x%02x\n",
        UE_rrc_inst[ctxt_pP->module_id].kenb[0],  UE_rrc_inst[ctxt_pP->module_id].kenb[1],  UE_rrc_inst[ctxt_pP->module_id].kenb[2],  UE_rrc_inst[ctxt_pP->module_id].kenb[3],
        UE_rrc_inst[ctxt_pP->module_id].kenb[4],  UE_rrc_inst[ctxt_pP->module_id].kenb[5],  UE_rrc_inst[ctxt_pP->module_id].kenb[6],  UE_rrc_inst[ctxt_pP->module_id].kenb[7],
        UE_rrc_inst[ctxt_pP->module_id].kenb[8],  UE_rrc_inst[ctxt_pP->module_id].kenb[9],  UE_rrc_inst[ctxt_pP->module_id].kenb[10], UE_rrc_inst[ctxt_pP->module_id].kenb[11],
        UE_rrc_inst[ctxt_pP->module_id].kenb[12], UE_rrc_inst[ctxt_pP->module_id].kenb[13], UE_rrc_inst[ctxt_pP->module_id].kenb[14], UE_rrc_inst[ctxt_pP->module_id].kenb[15],
        UE_rrc_inst[ctxt_pP->module_id].kenb[16], UE_rrc_inst[ctxt_pP->module_id].kenb[17], UE_rrc_inst[ctxt_pP->module_id].kenb[18], UE_rrc_inst[ctxt_pP->module_id].kenb[19],
        UE_rrc_inst[ctxt_pP->module_id].kenb[20], UE_rrc_inst[ctxt_pP->module_id].kenb[21], UE_rrc_inst[ctxt_pP->module_id].kenb[22], UE_rrc_inst[ctxt_pP->module_id].kenb[23],
        UE_rrc_inst[ctxt_pP->module_id].kenb[24], UE_rrc_inst[ctxt_pP->module_id].kenb[25], UE_rrc_inst[ctxt_pP->module_id].kenb[26], UE_rrc_inst[ctxt_pP->module_id].kenb[27],
        UE_rrc_inst[ctxt_pP->module_id].kenb[28], UE_rrc_inst[ctxt_pP->module_id].kenb[29], UE_rrc_inst[ctxt_pP->module_id].kenb[30], UE_rrc_inst[ctxt_pP->module_id].kenb[31]);

    derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
        UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
    derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
        UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
    derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
        UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);

    if (securityMode != 0xff) {
      pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0,
          UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm
              | (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4),
          kRRCenc, kRRCint, kUPenc);
    } else {
      LOG_I(RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x",
          securityMode);
    }
  } else {
    LOG_I(RRC, "Could not get PDCP instance where key=0x%ld\n", key);
  }

#endif //#if defined(ENABLE_SECURITY)

  if (securityModeCommand->criticalExtensions.present == LTE_SecurityModeCommand__criticalExtensions_PR_c1) {
    if (securityModeCommand->criticalExtensions.choice.c1.present != LTE_SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8)
      LOG_W(RRC,"securityModeCommand->criticalExtensions.choice.c1.present (%d) != SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8\n",
	    securityModeCommand->criticalExtensions.choice.c1.present);
    
    
    ul_dcch_msg.message.choice.c1.choice.securityModeComplete.rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier;
    ul_dcch_msg.message.choice.c1.choice.securityModeComplete.criticalExtensions.present = LTE_SecurityModeCommand__criticalExtensions_PR_c1;
    ul_dcch_msg.message.choice.c1.choice.securityModeComplete.criticalExtensions.choice.securityModeComplete_r8.nonCriticalExtension =NULL;
    
    LOG_I(RRC,"[UE %d] SFN/SF %d/%d: Receiving from SRB1 (DL-DCCH), encoding securityModeComplete (eNB %d), rrc_TransactionIdentifier: %ld\n",
	  ctxt_pP->module_id,ctxt_pP->frame, ctxt_pP->subframe, eNB_index, securityModeCommand->rrc_TransactionIdentifier);
    
    enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_UL_DCCH_Message,
                                     NULL,
				     (void*)&ul_dcch_msg,
				     buffer,
				     100);
    AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
		 enc_rval.failed_type->name, enc_rval.encoded);
    
    if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
       xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void*)&ul_dcch_msg);
    }
    
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
    {
      char        message_string[20000];
      size_t      message_string_size;
      
      if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_LTE_UL_DCCH_Message, (void *) &ul_dcch_msg)) > 0) {
	MessageDef *msg_p;
	
	msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_UL_DCCH, message_string_size + sizeof (IttiMsgText));
	msg_p->ittiMsg.rrc_ul_dcch.size = message_string_size;
	memcpy(&msg_p->ittiMsg.rrc_ul_dcch.text, message_string, message_string_size);
	
	itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
      }
    }
# endif
#endif

      LOG_D(RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8);

      for (i = 0; i < (enc_rval.encoded + 7) / 8; i++) {
        LOG_T(RRC, "%02x.", buffer[i]);
      }

      LOG_T(RRC, "\n");
      rrc_data_req (
		    ctxt_pP,
		    DCCH,
		    rrc_mui++,
		    SDU_CONFIRM_NO,
		    (enc_rval.encoded + 7) / 8,
		    buffer,
		    PDCP_TRANSMISSION_MODE_CONTROL);
    }
    
  else LOG_W(RRC,"securityModeCommand->criticalExtensions.present (%d) != SecurityModeCommand__criticalExtensions_PR_c1\n",
	     securityModeCommand->criticalExtensions.present);
}

//-----------------------------------------------------------------------------
void
rrc_ue_process_ueCapabilityEnquiry(
  const protocol_ctxt_t* const ctxt_pP,
  LTE_UECapabilityEnquiry_t* UECapabilityEnquiry,
  uint8_t eNB_index
)
//-----------------------------------------------------------------------------
{

  asn_enc_rval_t enc_rval;

  LTE_UL_DCCH_Message_t ul_dcch_msg;


  LTE_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container;

  uint8_t buffer[200];
  int i;

  LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing UECapabilityEnquiry (eNB %d)\n",
        ctxt_pP->module_id,
        ctxt_pP->frame,
        eNB_index);


  memset((void *)&ul_dcch_msg,0,sizeof(LTE_UL_DCCH_Message_t));
  memset((void *)&ue_CapabilityRAT_Container,0,sizeof(LTE_UE_CapabilityRAT_Container_t));

  ul_dcch_msg.message.present           = LTE_UL_DCCH_MessageType_PR_c1;
  ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation;
  ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier;

  ue_CapabilityRAT_Container.rat_Type = LTE_RAT_Type_eutra;
  OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ueCapabilityRAT_Container,
                       (const char*)UE_rrc_inst[ctxt_pP->module_id].UECapability,
                       UE_rrc_inst[ctxt_pP->module_id].UECapability_size);
  //  ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf  = UE_rrc_inst[ue_mod_idP].UECapability;
  // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size;


  AssertFatal(UECapabilityEnquiry->criticalExtensions.present == LTE_UECapabilityEnquiry__criticalExtensions_PR_c1,
	      "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n",
	      UECapabilityEnquiry->criticalExtensions.present,LTE_UECapabilityEnquiry__criticalExtensions_PR_c1);

  if (UECapabilityEnquiry->criticalExtensions.choice.c1.present != LTE_UECapabilityEnquiry__criticalExtensions__c1_PR_ueCapabilityEnquiry_r8)
    LOG_I(RRC,"UECapabilityEnquiry->criticalExtensions.choice.c1.present (%d) != UECapabilityEnquiry__criticalExtensions__c1_PR_ueCapabilityEnquiry_r8)\n",
	  UECapabilityEnquiry->criticalExtensions.choice.c1.present);
  
  ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.present           = LTE_UECapabilityInformation__criticalExtensions_PR_c1;
  ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.choice.c1.present =
    LTE_UECapabilityInformation__criticalExtensions__c1_PR_ueCapabilityInformation_r8;
  ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.count
    =0;
  
  for (i=0; i<UECapabilityEnquiry->criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list.count; i++) {
    
    if (*UECapabilityEnquiry->criticalExtensions.choice.c1.choice.ueCapabilityEnquiry_r8.ue_CapabilityRequest.list.array[i]
	== LTE_RAT_Type_eutra) {
      ASN_SEQUENCE_ADD(
		       &ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list,
		       &ue_CapabilityRAT_Container);
      
      enc_rval = uper_encode_to_buffer(&asn_DEF_LTE_UL_DCCH_Message, NULL, (void*) &ul_dcch_msg, buffer, 100);
      AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
		   enc_rval.failed_type->name, enc_rval.encoded);
      
      if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
         xer_fprint(stdout, &asn_DEF_LTE_UL_DCCH_Message, (void*)&ul_dcch_msg);
      }
      
#if defined(ENABLE_ITTI)
# if !defined(DISABLE_XER_SPRINT)
      {
	char        message_string[20000];
	size_t      message_string_size;
	
	if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_LTE_UL_DCCH_Message, (void *) &ul_dcch_msg)) > 0) {
	  MessageDef *msg_p;
	  
	  msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_UL_DCCH, message_string_size + sizeof (IttiMsgText));
	  msg_p->ittiMsg.rrc_ul_dcch.size = message_string_size;
	  memcpy(&msg_p->ittiMsg.rrc_ul_dcch.text, message_string, message_string_size);
	  
	  itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
	}
      }
# endif
#endif
	

          LOG_I(RRC,"UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);

          for (i = 0; i < (enc_rval.encoded + 7) / 8; i++) {
            LOG_T(RRC, "%02x.", buffer[i]);
          }
      
      LOG_T(RRC, "\n");
      rrc_data_req_ue (
		    ctxt_pP,
		    DCCH,
		    rrc_mui++,
		    SDU_CONFIRM_NO,
		    (enc_rval.encoded + 7) / 8,
		    buffer,
		    PDCP_TRANSMISSION_MODE_CONTROL);
    }
  }
}


//-----------------------------------------------------------------------------
void
rrc_ue_process_rrcConnectionReconfiguration(
  const protocol_ctxt_t* const       ctxt_pP,
  LTE_RRCConnectionReconfiguration_t *rrcConnectionReconfiguration,
  uint8_t eNB_index
)
//-----------------------------------------------------------------------------
{

  LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing RRCConnectionReconfiguration (eNB %d)\n",
        ctxt_pP->module_id,ctxt_pP->frame,eNB_index);

  if (rrcConnectionReconfiguration->criticalExtensions.present == LTE_RRCConnectionReconfiguration__criticalExtensions_PR_c1) {
    if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.present ==
        LTE_RRCConnectionReconfiguration__criticalExtensions__c1_PR_rrcConnectionReconfiguration_r8) {
      LTE_RRCConnectionReconfiguration_r8_IEs_t* rrcConnectionReconfiguration_r8 =
        &rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8;

      if (rrcConnectionReconfiguration_r8->mobilityControlInfo) {
        LOG_I(RRC,"Mobility Control Information is present\n");
        rrc_ue_process_mobilityControlInfo(
          ctxt_pP,
          eNB_index,
          rrcConnectionReconfiguration_r8->mobilityControlInfo);
      }

      if (rrcConnectionReconfiguration_r8->measConfig != NULL) {
        LOG_I(RRC,"Measurement Configuration is present\n");
        rrc_ue_process_measConfig(ctxt_pP,
                                  eNB_index,
                                  rrcConnectionReconfiguration_r8->measConfig);
      }

      if (rrcConnectionReconfiguration_r8->radioResourceConfigDedicated) {
        LOG_I(RRC,"Radio Resource Configuration is present\n");
        rrc_ue_process_radioResourceConfigDedicated(ctxt_pP,eNB_index, rrcConnectionReconfiguration_r8->radioResourceConfigDedicated);
      }

      //TTN for D2D
      //if RRCConnectionReconfiguration message includes the sl-CommConfig
      if ((rrcConnectionReconfiguration_r8->nonCriticalExtension != NULL)
            && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension
                  != NULL)
                  && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
                        != NULL)
                        && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
                              != NULL)
                              && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension
                                    != NULL)
                                    && (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12
                                          != NULL)) {
         if (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12->commTxResources_r12->present != LTE_SL_CommConfig_r12__commTxResources_r12_PR_NOTHING){
            LOG_I(RRC,"sl-CommConfig is present\n");
            //process sl-CommConfig
            rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
                  (LTE_SystemInformationBlockType18_r12_t *)NULL,
                  (LTE_SystemInformationBlockType19_r12_t *)NULL,
                  rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_CommConfig_r12,
                  (LTE_SL_DiscConfig_r12_t *)NULL
            );
         }
      }

/*
      //if RRCConnectionReconfiguration message includes the sl-DiscConfig
      if (rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12->discTxResources_r12->present != SL_DiscConfig_r12__discTxResources_r12_PR_NOTHING ){
         LOG_I(RRC,"sl-DiscConfig is present\n");
         //process sl-DiscConfig
         rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
               (SystemInformationBlockType18_r12_t *)NULL,
               (SystemInformationBlockType19_r12_t *)NULL,
               (SL_CommConfig_r12_t* )NULL,
               rrcConnectionReconfiguration_r8->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->nonCriticalExtension->sl_DiscConfig_r12
               );
      }
*/

#if defined(ENABLE_ITTI)

      /* Check if there is dedicated NAS information to forward to NAS */
      if (rrcConnectionReconfiguration_r8->dedicatedInfoNASList != NULL) {
        int list_count;
        uint32_t pdu_length;
        uint8_t *pdu_buffer;
        MessageDef *msg_p;

        for (list_count = 0; list_count < rrcConnectionReconfiguration_r8->dedicatedInfoNASList->list.count; list_count++) {
          pdu_length = rrcConnectionReconfiguration_r8->dedicatedInfoNASList->list.array[list_count]->size;
          pdu_buffer = rrcConnectionReconfiguration_r8->dedicatedInfoNASList->list.array[list_count]->buf;

          msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CONN_ESTABLI_CNF);
          NAS_CONN_ESTABLI_CNF(msg_p).errCode = AS_SUCCESS;
          NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length = pdu_length;
          NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data = pdu_buffer;

          itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
        }

        free (rrcConnectionReconfiguration_r8->dedicatedInfoNASList);
      }

#if ENABLE_RAL
      {
        MessageDef                                 *message_ral_p = NULL;
        rrc_ral_connection_reestablishment_ind_t    connection_reestablishment_ind;
        int                                         i;

        message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_CONNECTION_REESTABLISHMENT_IND);
        memset(&connection_reestablishment_ind, 0, sizeof(rrc_ral_connection_reestablishment_ind_t));
        // TO DO ral_si_ind.plmn_id        = 0;
        connection_reestablishment_ind.ue_id            = ctxt_pP->rnti;

        if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList != NULL) {
          connection_reestablishment_ind.num_drb      =
            rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.count;

          for (i=0; (
                 i<rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.count)
               && (i < maxDRB); i++) {
            // why minus 1 in RRC code for drb_identity ?
            connection_reestablishment_ind.drb_id[i]   =
              rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity;
          }
        } else {
          connection_reestablishment_ind.num_drb      = 0;
        }

        if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->srb_ToAddModList != NULL) {
          connection_reestablishment_ind.num_srb      =
            rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->srb_ToAddModList->list.count +
            UE_rrc_inst[ctxt_pP->module_id].num_srb;

        } else {
          connection_reestablishment_ind.num_srb      += UE_rrc_inst[ctxt_pP->module_id].num_srb;
        }

        if (connection_reestablishment_ind.num_srb > 2) { // fixme: only 2 srbs can exist, adjust the value
          connection_reestablishment_ind.num_srb =2;
        }

        memcpy (&message_ral_p->ittiMsg, (void *) &connection_reestablishment_ind, sizeof(rrc_ral_connection_reestablishment_ind_t));
        //#warning "ue_mod_idP ? for instance ? => YES"
        LOG_I(RRC, "Sending RRC_RAL_CONNECTION_REESTABLISHMENT_IND to mRAL\n");
        itti_send_msg_to_task (TASK_RAL_UE, ctxt_pP->instance, message_ral_p);
      }
#endif
#endif
    } // c1 present
  } // critical extensions present
}

/* 36.331, 5.3.5.4      Reception of an RRCConnectionReconfiguration including the mobilityControlInfo by the UE (handover) */
//-----------------------------------------------------------------------------
void
rrc_ue_process_mobilityControlInfo(
  const protocol_ctxt_t* const       ctxt_pP,
  const uint8_t                      eNB_index,
  struct LTE_MobilityControlInfo* const mobilityControlInfo
)
//-----------------------------------------------------------------------------
{
  /*
  DRB_ToReleaseList_t*  drb2release_list;
  DRB_Identity_t *lcid;
   */
  LOG_I(RRC,"Note: This function needs some updates\n");

  if(UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].T310_active == 1) {
    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].T310_active = 0;
  }

  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].T304_active = 1;
  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].T304_cnt = T304[mobilityControlInfo->t304];

  /*
  drb2release_list = CALLOC (1, sizeof (*drb2release_list));
  lcid= CALLOC (1, sizeof (DRB_Identity_t)); // long
  for (*lcid=0;*lcid<NB_RB_MAX;*lcid++)
  {
    ASN_SEQUENCE_ADD (&(drb2release_list)->list,lcid);
  }
   */
  //Removing SRB1 and SRB2 and DRB0
  LOG_I(RRC,"[UE %d] : Update needed for rrc_pdcp_config_req (deprecated) and rrc_rlc_config_req commands(deprecated)\n", ctxt_pP->module_id);
  rrc_pdcp_config_req (ctxt_pP, SRB_FLAG_YES, CONFIG_ACTION_REMOVE, DCCH,UNDEF_SECURITY_MODE);
  rrc_rlc_config_req(ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, CONFIG_ACTION_REMOVE,ctxt_pP->module_id+DCCH,Rlc_info_am_config);
  rrc_pdcp_config_req (ctxt_pP, SRB_FLAG_YES, CONFIG_ACTION_REMOVE, DCCH1,UNDEF_SECURITY_MODE);
  rrc_rlc_config_req(ctxt_pP, SRB_FLAG_YES,CONFIG_ACTION_REMOVE, MBMS_FLAG_NO,ctxt_pP->module_id+DCCH1,Rlc_info_am_config);
  rrc_pdcp_config_req (ctxt_pP, SRB_FLAG_NO, CONFIG_ACTION_REMOVE, DTCH,UNDEF_SECURITY_MODE);
  rrc_rlc_config_req(ctxt_pP, SRB_FLAG_NO,CONFIG_ACTION_REMOVE, MBMS_FLAG_NO,ctxt_pP->module_id+DTCH,Rlc_info_um);
  /*
  rrc_pdcp_config_asn1_req(NB_eNB_INST+ue_mod_idP,frameP, 0,eNB_index,
         NULL, // SRB_ToAddModList
         NULL, // DRB_ToAddModList
         drb2release_list,
         0, // security mode
         NULL, // key rrc encryption
         NULL, // key rrc integrity
         NULL // key encryption
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
         ,NULL
#endif
         ,NULL);

  rrc_rlc_config_asn1_req(NB_eNB_INST+ue_mod_idP, frameP,0,eNB_index,
        NULL,// SRB_ToAddModList
        NULL,// DRB_ToAddModList
        drb2release_list // DRB_ToReleaseList
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
        ,NULL
#endif
        ,NULL);
   */


  //A little cleanup at RRC...
  //Copying current queue config to free RRC index
  /*
    memcpy((void *)UE_rrc_inst[ue_mod_idP].SRB1_config[~(7<<eNB_index)],(void *)UE_rrc_inst[ue_mod_idP].SRB1_config[7<<eNB_index],sizeof(SRB_ToAddMod_t));
    memcpy((void *)UE_rrc_inst[ue_mod_idP].SRB2_config[~(7<<eNB_index)],(void *)UE_rrc_inst[ue_mod_idP].SRB2_config[7<<eNB_index],sizeof(SRB_ToAddMod_t));
    memcpy((void *)UE_rrc_inst[ue_mod_idP].DRB_config[~(7<<eNB_index)][0],(void *)UE_rrc_inst[ue_mod_idP].DRB_config[7<<eNB_index][0],sizeof(DRB_ToAddMod_t));
   */
  /*
  LOG_I(RRC,"Not sure if Freeing the current queue config works properly: Fix me\n");
  free((void *)&UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index]);
  free((void *)&UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index]);
  free((void *)&UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][0]);

  UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index] = NULL;
  UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index] = NULL;
  UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][0] = NULL;
   */
  //Synchronisation to DL of target cell
  LOG_I(RRC,
        "HO: Reset PDCP and RLC for configured RBs.. \n[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
        ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);

  // Reset MAC and configure PHY
  rrc_mac_config_req_ue(ctxt_pP->module_id,
			0,
			eNB_index,
			(LTE_RadioResourceConfigCommonSIB_t *)NULL,
			(struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			(LTE_SCellToAddMod_r10_t *)NULL,
			//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
			(LTE_MeasObjectToAddMod_t **)NULL,
			(LTE_MAC_MainConfig_t *)NULL,
			0,
			(struct LTE_LogicalChannelConfig *)NULL,
			(LTE_MeasGapConfig_t *)NULL,
			(LTE_TDD_Config_t *)NULL,
			mobilityControlInfo,
			(uint8_t *)NULL,
			(uint16_t *)NULL,
			NULL,
			NULL,
			NULL,
			NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
			,0,
			(LTE_MBSFN_AreaInfoList_r9_t *)NULL,
			(LTE_PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
			,0,
			0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			);

  // Re-establish PDCP for all RBs that are established
  // rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, ue_mod_idP+DCCH);
  // rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, ue_mod_idP+DCCH1);
  // rrc_pdcp_config_req (ue_mod_idP+NB_eNB_INST, frameP, 0, CONFIG_ACTION_ADD, ue_mod_idP+DTCH);


  // Re-establish RLC for all RBs that are established
  // rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,ue_mod_idP+DCCH,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);
  // rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,ue_mod_idP+DCCH1,SIGNALLING_RADIO_BEARER,Rlc_info_am_config);
  // rrc_rlc_config_req(ue_mod_idP+NB_eNB_INST,frameP,0,CONFIG_ACTION_ADD,ue_mod_idP+DTCH,RADIO_ACCESS_BEARER,Rlc_info_um);
  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_SI_RECEIVED;
}

//-----------------------------------------------------------------------------
void
rrc_detach_from_eNB(
  module_id_t ue_mod_idP,
  uint8_t eNB_index
)
//-----------------------------------------------------------------------------
{
  //UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index]
}

//-----------------------------------------------------------------------------
void
rrc_ue_decode_dcch(
  const protocol_ctxt_t* const ctxt_pP,
  const rb_id_t                Srb_id,
  const uint8_t*         const Buffer,
  const uint8_t                eNB_indexP
)
//-----------------------------------------------------------------------------
{

  //DL_DCCH_Message_t dldcchmsg;
  LTE_DL_DCCH_Message_t *dl_dcch_msg=NULL;//&dldcchmsg;
  //  asn_dec_rval_t dec_rval;
  // int i;
  uint8_t target_eNB_index=0xFF;
#if defined(ENABLE_ITTI)
  MessageDef *msg_p;
#endif

  if (Srb_id != 1) {
    LOG_E(RRC,"[UE %d] Frame %d: Received message on DL-DCCH (SRB%d), should not have ...\n",
          ctxt_pP->module_id, ctxt_pP->frame, Srb_id);
    return;
  }

  //memset(dl_dcch_msg,0,sizeof(DL_DCCH_Message_t));

  // decode messages
  //  LOG_D(RRC,"[UE %d] Decoding DL-DCCH message\n",ue_mod_idP);
  /*
  for (i=0;i<30;i++)
    LOG_T(RRC,"%x.",Buffer[i]);
  LOG_T(RRC, "\n");
   */
  uper_decode(NULL,
              &asn_DEF_LTE_DL_DCCH_Message,
              (void**)&dl_dcch_msg,
              (uint8_t*)Buffer,
              RRC_BUF_SIZE,0,0);

  if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
     xer_fprint(stdout,&asn_DEF_LTE_DL_DCCH_Message,(void*)dl_dcch_msg);
  }

#if defined(ENABLE_ITTI)
# if defined(DISABLE_ITTI_XER_PRINT)
  {
    msg_p = itti_alloc_new_message (TASK_RRC_UE, RRC_DL_DCCH_MESSAGE);
    memcpy (&msg_p->ittiMsg, (void *) dl_dcch_msg, sizeof(RrcDlDcchMessage));

    itti_send_msg_to_task (TASK_UNKNOWN, ctxt_pP->instance, msg_p);
  }
# else
  {
    char        message_string[30000];
    size_t      message_string_size;

    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_LTE_DL_DCCH_Message, (void *)dl_dcch_msg)) > 0) {
      msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_DL_DCCH, message_string_size + sizeof (IttiMsgText));
      msg_p->ittiMsg.rrc_dl_dcch.size = message_string_size;
      memcpy(&msg_p->ittiMsg.rrc_dl_dcch.text, message_string, message_string_size);

      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
    }
  }
# endif
#endif

  if (dl_dcch_msg->message.present == LTE_DL_DCCH_MessageType_PR_c1) {

    if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_indexP].State >= RRC_CONNECTED) {

      switch (dl_dcch_msg->message.choice.c1.present) {

      case LTE_DL_DCCH_MessageType__c1_PR_NOTHING:
        LOG_I(RRC, "[UE %d] Frame %d : Received PR_NOTHING on DL-DCCH-Message\n",
              ctxt_pP->module_id, ctxt_pP->frame);
        return;

      case LTE_DL_DCCH_MessageType__c1_PR_csfbParametersResponseCDMA2000:
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: {
#if defined(ENABLE_ITTI)
        LTE_DLInformationTransfer_t *dlInformationTransfer = &dl_dcch_msg->message.choice.c1.choice.dlInformationTransfer;

        if ((dlInformationTransfer->criticalExtensions.present == LTE_DLInformationTransfer__criticalExtensions_PR_c1)
            && (dlInformationTransfer->criticalExtensions.choice.c1.present
                == LTE_DLInformationTransfer__criticalExtensions__c1_PR_dlInformationTransfer_r8)
            && (dlInformationTransfer->criticalExtensions.choice.c1.choice.dlInformationTransfer_r8.dedicatedInfoType.present
                == LTE_DLInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)) {
          /* This message hold a dedicated info NAS payload, forward it to NAS */
          struct LTE_DLInformationTransfer_r8_IEs__dedicatedInfoType *dedicatedInfoType =
                &dlInformationTransfer->criticalExtensions.choice.c1.choice.dlInformationTransfer_r8.dedicatedInfoType;
          uint32_t pdu_length;
          uint8_t *pdu_buffer;
          MessageDef *msg_p;

          pdu_length = dedicatedInfoType->choice.dedicatedInfoNAS.size;
          pdu_buffer = dedicatedInfoType->choice.dedicatedInfoNAS.buf;

          msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_DOWNLINK_DATA_IND);
          NAS_DOWNLINK_DATA_IND(msg_p).UEid = ctxt_pP->module_id; // TODO set the UEid to something else ?
          NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length = pdu_length;
          NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data = pdu_buffer;

          itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
        }

#endif
        break;
      }

      case LTE_DL_DCCH_MessageType__c1_PR_handoverFromEUTRAPreparationRequest:
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_mobilityFromEUTRACommand:
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionReconfiguration:

        // first check if mobilityControlInfo  is present
        if (dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo
            != NULL) {
          /* 36.331, 5.3.5.4 Reception of an RRCConnectionReconfiguration including the mobilityControlInfo by the UE (handover)*/
          if (UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId
              != dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo->targetPhysCellId) {
            LOG_W(RRC,
                  "[UE %d] Frame %d: Handover target (%ld) is different from RSRP measured target (%ld)..\n",
                  ctxt_pP->module_id,
                  ctxt_pP->frame,
                  dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo->targetPhysCellId,
                  UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId);
            return;
          } else if ((target_eNB_index = get_adjacent_cell_mod_id(UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId))
                     == 0xFF) {
            LOG_W(RRC,
                  "[UE %d] Frame %d: ue_mod_idP of the target eNB not found, check the network topology\n",
                  ctxt_pP->module_id,
                  ctxt_pP->frame);
            return;
          } else {
            LOG_I(RRC,
                  "[UE% d] Frame %d: Received rrcConnectionReconfiguration with mobilityControlInfo \n",
                  ctxt_pP->module_id,
                  ctxt_pP->frame);
            UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1; // Ready to send more MeasReports if required
          }
        }

        rrc_ue_process_rrcConnectionReconfiguration(
          ctxt_pP,
          &dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration,
          eNB_indexP);

        if (target_eNB_index != 0xFF) {
          rrc_ue_generate_RRCConnectionReconfigurationComplete(
            ctxt_pP,
            target_eNB_index,
            dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.rrc_TransactionIdentifier);
          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_indexP].State = RRC_HO_EXECUTION;
          UE_rrc_inst[ctxt_pP->module_id].Info[target_eNB_index].State = RRC_RECONFIGURED;
          LOG_I(RRC, "[UE %d] State = RRC_RECONFIGURED during HO (eNB %d)\n",
                ctxt_pP->module_id, target_eNB_index);
#if defined(ENABLE_ITTI)
#if ENABLE_RAL
          {
            MessageDef                                 *message_ral_p = NULL;
            rrc_ral_connection_reconfiguration_ho_ind_t connection_reconfiguration_ho_ind;
            int                                         i;

            message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_CONNECTION_RECONFIGURATION_HO_IND);
            memset(&connection_reconfiguration_ho_ind, 0, sizeof(rrc_ral_connection_reconfiguration_ho_ind_t));
            connection_reconfiguration_ho_ind.ue_id = ctxt_pP->module_id;

            if (dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList
                != NULL) {
              connection_reconfiguration_ho_ind.num_drb      =
                dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.count;

              for (i=0; (
                     i<dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.count)
                   && (i < maxDRB); i++) {
                // why minus 1 in RRC code for drb_identity ?
                connection_reconfiguration_ho_ind.drb_id[i]   =
                  dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity;
              }
            } else {
              connection_reconfiguration_ho_ind.num_drb      = 0;
            }

            if (dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->srb_ToAddModList
                != NULL) {
              connection_reconfiguration_ho_ind.num_srb      =
                dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->srb_ToAddModList->list.count
                +
                UE_rrc_inst[ctxt_pP->module_id].num_srb;
            } else {
              connection_reconfiguration_ho_ind.num_srb      += UE_rrc_inst[ctxt_pP->module_id].num_srb;
            }

            if (connection_reconfiguration_ho_ind.num_srb > 2 ) {
              connection_reconfiguration_ho_ind.num_srb =2;
            }

            memcpy (&message_ral_p->ittiMsg, (void *) &connection_reconfiguration_ho_ind, sizeof(rrc_ral_connection_reconfiguration_ho_ind_t));
            //#warning "ue_mod_idP ? for instance ? => YES"
            LOG_I(RRC, "Sending RRC_RAL_CONNECTION_RECONFIGURATION_HO_IND to mRAL\n");
            itti_send_msg_to_task (TASK_RAL_UE, ctxt_pP->instance, message_ral_p);
          }
#endif
#endif
        } else {
          rrc_ue_generate_RRCConnectionReconfigurationComplete(
            ctxt_pP,
            eNB_indexP,
            dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.rrc_TransactionIdentifier);
          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_indexP].State = RRC_RECONFIGURED;
          LOG_I(RRC, "[UE %d] State = RRC_RECONFIGURED (eNB %d)\n",
                ctxt_pP->module_id,
                eNB_indexP);
#if defined(ENABLE_ITTI)
#if ENABLE_RAL
          {
            MessageDef                                 *message_ral_p = NULL;
            rrc_ral_connection_reconfiguration_ind_t    connection_reconfiguration_ind;
            int                                         i;

            message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_CONNECTION_RECONFIGURATION_IND);
            memset(&connection_reconfiguration_ind, 0, sizeof(rrc_ral_connection_reconfiguration_ind_t));
            connection_reconfiguration_ind.ue_id = ctxt_pP->module_id;

            if (dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList
                != NULL) {
              connection_reconfiguration_ind.num_drb      =
                dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.count;

              for (i=0; (
                     i<dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.count)
                   && (i < maxDRB); i++) {
                // why minus 1 in RRC code for drb_identity ?
                connection_reconfiguration_ind.drb_id[i]   =
                  dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity;
              }
            } else {
              connection_reconfiguration_ind.num_drb      = 0;
            }

            if (dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->srb_ToAddModList
                != NULL) {
              connection_reconfiguration_ind.num_srb      =
                dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated->srb_ToAddModList->list.count
                +
                UE_rrc_inst[ctxt_pP->module_id].num_srb;
            } else {
              connection_reconfiguration_ind.num_srb      +=UE_rrc_inst[ctxt_pP->module_id].num_srb;
            }

            if (connection_reconfiguration_ind.num_srb > 2 ) {
              connection_reconfiguration_ind.num_srb =2;
            }

            memcpy (&message_ral_p->ittiMsg, (void *) &connection_reconfiguration_ind, sizeof(rrc_ral_connection_reconfiguration_ind_t));
            //#warning "ue_mod_idP ? for instance ? => YES"
            LOG_I(RRC, "Sending RRC_RAL_CONNECTION_RECONFIGURATION_IND to mRAL\n");
            itti_send_msg_to_task (TASK_RAL_UE, ctxt_pP->instance, message_ral_p);
          }
#endif
#endif

        }

        //TTN test D2D (should not be here - in reality, this message will be triggered from ProSeApp)
        if (send_ue_information == 0) {
           LOG_I(RRC, "TEST SidelinkUEInformation [UE %d] Received  (eNB %d)\n",
                 ctxt_pP->module_id, eNB_indexP);
           LTE_SL_DestinationInfoList_r12_t *destinationInfoList = CALLOC(1, sizeof(LTE_SL_DestinationInfoList_r12_t));
           LTE_SL_DestinationIdentity_r12_t *sl_destination_identity = CALLOC(1, sizeof(LTE_SL_DestinationIdentity_r12_t));
           sl_destination_identity->size = 3;
           sl_destination_identity->buf = CALLOC(1,3);
           sl_destination_identity->buf[0] = 0x00;
           sl_destination_identity->buf[1] = 0x00;
           sl_destination_identity->buf[2] = 0x01;
           sl_destination_identity->bits_unused = 0;
           ASN_SEQUENCE_ADD(&destinationInfoList->list,sl_destination_identity);
           rrc_ue_generate_SidelinkUEInformation(ctxt_pP, eNB_indexP, destinationInfoList, NULL, SL_TRANSMIT_NON_RELAY_ONE_TO_ONE);
           send_ue_information ++;
        }
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_rrcConnectionRelease:
#if defined(ENABLE_ITTI)
        msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CONN_RELEASE_IND);

        if ((dl_dcch_msg->message.choice.c1.choice.rrcConnectionRelease.criticalExtensions.present
             == LTE_RRCConnectionRelease__criticalExtensions_PR_c1)
            && (dl_dcch_msg->message.choice.c1.choice.rrcConnectionRelease.criticalExtensions.choice.c1.present
                == LTE_RRCConnectionRelease__criticalExtensions__c1_PR_rrcConnectionRelease_r8)) {
          NAS_CONN_RELEASE_IND(msg_p).cause =
            dl_dcch_msg->message.choice.c1.choice.rrcConnectionRelease.criticalExtensions.choice.c1.choice.rrcConnectionRelease_r8.releaseCause;
        }

        itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
#if ENABLE_RAL
        msg_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_CONNECTION_RELEASE_IND);
        RRC_RAL_CONNECTION_RELEASE_IND(msg_p).ue_id = ctxt_pP->module_id;
        itti_send_msg_to_task(TASK_RAL_UE, ctxt_pP->instance, msg_p);
#endif
#endif
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_securityModeCommand:
        LOG_I(RRC, "[UE %d] Received securityModeCommand (eNB %d)\n",
              ctxt_pP->module_id, eNB_indexP);
        rrc_ue_process_securityModeCommand(
          ctxt_pP,
          &dl_dcch_msg->message.choice.c1.choice.securityModeCommand,
          eNB_indexP);
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry:
        LOG_I(RRC, "[UE %d] Received Capability Enquiry (eNB %d)\n",
              ctxt_pP->module_id,
              eNB_indexP);
        rrc_ue_process_ueCapabilityEnquiry(
          ctxt_pP,
          &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry,
          eNB_indexP);
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_counterCheck:
        break;

#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
      case LTE_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r9:
        break;
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
      case LTE_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r10:
        break;

      case LTE_DL_DCCH_MessageType__c1_PR_rnReconfiguration_r10:
        break;
#endif

      case LTE_DL_DCCH_MessageType__c1_PR_spare1:
      case LTE_DL_DCCH_MessageType__c1_PR_spare2:
      case LTE_DL_DCCH_MessageType__c1_PR_spare3:
#if (LTE_RRC_VERSION < MAKE_VERSION(14, 0, 0))
      case LTE_DL_DCCH_MessageType__c1_PR_spare4:
#endif
        break;

      default:
        break;
      }
    }
  }

#ifndef NO_RRM
  send_msg(&S_rrc,msg_rrc_end_scan_req(ctxt_pP->module_id,eNB_indexP));
#endif
}

const char siWindowLength[8][5] = {"1ms","2ms","5ms","10ms","15ms","20ms","40ms","ERR"};
const char siWindowLength_int[7] = {1,2,5,10,15,20,40};

const char SIBType[12][6] = {"SIB3","SIB4","SIB5","SIB6","SIB7","SIB8","SIB9","SIB10","SIB11","SIB12","SIB13","Spare"};
const char SIBPeriod[8][6]= {"rf8","rf16","rf32","rf64","rf128","rf256","rf512","ERR"};
int siPeriod_int[7] = {80,160,320,640,1280,2560,5120};

const char* SIBreserved( long value )
{
  if (value < 0 || value > 1)
    return "ERR";

  if (value)
    return "notReserved";

  return "reserved";
}
const char* SIBbarred( long value )
{
  if (value < 0 || value > 1)
    return "ERR";

  if (value)
    return "notBarred";

  return "barred";
}
const char* SIBallowed( long value )
{
  if (value < 0 || value > 1)
    return "ERR";

  if (value)
    return "notAllowed";

  return "allowed";
}
const char* SIB2SoundingPresent( int value )
{
  switch (value) {
  case LTE_SoundingRS_UL_ConfigCommon_PR_NOTHING:
    return "NOTHING";

  case LTE_SoundingRS_UL_ConfigCommon_PR_release:
    return "release";

  case LTE_SoundingRS_UL_ConfigCommon_PR_setup:
    return "setup";
  }

  return "ERR";
}
const char* SIB2numberOfRA_Preambles( long value )
{
  static char temp[4] = {0};

  if (value < 0 || value > 15)
    return "ERR";

  snprintf( temp, sizeof(temp), "n%ld", value*4 + 4 );
  temp[3] = 0; // terminate string
  return temp;
}
const char* SIB2powerRampingStep( long value )
{
  if (value < 0 || value > 3)
    return "ERR";

  static const char str[4][4] = {"dB0","dB2","dB4","dB6"};
  return str[value];
}
const char* SIB2preambleInitialReceivedTargetPower( long value )
{
  static char temp[8] = {0};

  if (value < 0 || value > 15)
    return "ERR";

  snprintf( temp, sizeof(temp), "dBm-%ld", 120 - value*2 );
  temp[7] = 0; // terminate string
  return temp;
}
const char* SIB2preambleTransMax( long value )
{
  static char temp[5] = {0};

  if (value < 0 || value > 10)
    return "ERR";

  if (value <= 5) {
    snprintf( temp, sizeof(temp), "n%ld", value+3 );
    return temp;
  }

  switch (value) {
  case 6:
    return "n10";

  case 7:
    return "n20";

  case 8:
    return "n50";

  case 9:
    return "n100";

  case 10:
    return "n200";
  }

  /* unreachable but gcc warns... */
  return "ERR";
}
const char* SIB2ra_ResponseWindowSize( long value )
{
  static char temp[4] = {0};

  if (value < 0 || value > 7)
    return "ERR";

  if (value == 7)
    return "sf10";

  snprintf( temp, sizeof(temp), "sf%ld", value+2 );
  return temp;
}
const char* SIB2mac_ContentionResolutionTimer( long value )
{
  static char temp[5] = {0};

  if (value < 0 || value > 7)
    return "ERR";

  snprintf( temp, sizeof(temp), "sf%ld", 8 + value*8 );
  return temp;
}
const char* SIB2modificationPeriodCoeff( long value )
{
  static char temp[32] = {0};

  if (value < 0 || value > 3)
    return "ERR";

  snprintf( temp, sizeof(temp), "n%d", (int)pow(2,value+1) );
  return temp;
}
const char* SIB2defaultPagingCycle( long value )
{
  static char temp[32] = {0};

  if (value < 0 || value > 3)
    return "ERR";

  snprintf( temp, sizeof(temp), "rf%d", (int)pow(2,value+4) );
  return temp;
}
const char* SIB2nB( long value )
{
  if (value < 0 || value > 7)
    return "ERR";

  static const char str[8][17] = {"fourT","twoT","oneT","halfT","quarterT","oneEigthT","oneSixteenthT","oneThirtySecondT"};
  return str[value];
}




//-----------------------------------------------------------------------------
int decode_BCCH_DLSCH_Message(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                eNB_index,
  uint8_t*               const Sdu,
  const uint8_t                Sdu_len,
  const uint8_t                rsrq,
  const uint8_t                rsrp )
{
  LTE_BCCH_DL_SCH_Message_t *bcch_message = NULL;
  LTE_SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];
  int i;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN );

  if (((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 1) &&  // SIB1 received
      (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)) {
    // Avoid decoding  SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];
    // to prevent memory bloating
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );
    return 0;
  }

  rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_RECEIVING_SIB );

  asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
                            &asn_DEF_LTE_BCCH_DL_SCH_Message,
                            (void **)&bcch_message,
                            (const void *)Sdu,
                            Sdu_len );

  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    LOG_E( RRC, "[UE %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n",
           ctxt_pP->module_id,
           dec_rval.consumed );
    for (i=0;i<Sdu_len;i++)
      printf("%02x ",Sdu[i]);
    printf("\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_LTE_BCCH_DL_SCH_Message, (void*)bcch_message, 1 );
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );
    return -1;
  }

#if defined(ENABLE_ITTI)
# if defined(DISABLE_ITTI_XER_PRINT)
  {
    MessageDef *msg_p;

    msg_p = itti_alloc_new_message (TASK_RRC_UE, RRC_DL_BCCH_MESSAGE);
    memcpy (&msg_p->ittiMsg, (void *) bcch_message, sizeof(RrcDlBcchMessage));

    itti_send_msg_to_task (TASK_UNKNOWN, ctxt_pP->instance, msg_p);
  }
# else
  {
    char        message_string[15000];
    size_t      message_string_size;

    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_LTE_BCCH_DL_SCH_Message, (void *)bcch_message)) > 0) {
      MessageDef *msg_p;

      msg_p = itti_alloc_new_message_sized (TASK_RRC_UE, RRC_DL_BCCH, message_string_size + sizeof (IttiMsgText));
      msg_p->ittiMsg.rrc_dl_bcch.size = message_string_size;
      memcpy(&msg_p->ittiMsg.rrc_dl_bcch.text, message_string, message_string_size);

      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
    }
  }
# endif
#endif

  if (bcch_message->message.present == LTE_BCCH_DL_SCH_MessageType_PR_c1) {
    switch (bcch_message->message.choice.c1.present) {
    case LTE_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
      if ((ctxt_pP->frame % 2) == 0) {
        // even frame
        if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 0) {
          LTE_SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];
          memcpy( (void*)sib1,
                  (void*)&bcch_message->message.choice.c1.choice.systemInformationBlockType1,
                  sizeof(LTE_SystemInformationBlockType1_t) );
          LOG_D( RRC, "[UE %"PRIu8"] Decoding First SIB1\n", ctxt_pP->module_id );

          decode_SIB1( ctxt_pP, eNB_index, rsrq, rsrp );
        }
      }

      break;

    case LTE_BCCH_DL_SCH_MessageType__c1_PR_systemInformation:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1) == 1) {
        // SIB1 with schedulingInfoList is available

        LTE_SystemInformation_t* si = UE_rrc_inst[ctxt_pP->module_id].si[eNB_index];
        memcpy( si,
                &bcch_message->message.choice.c1.choice.systemInformation,
                sizeof(LTE_SystemInformation_t) );

        LOG_I( RRC, "[UE %"PRIu8"] Decoding SI for frameP %"PRIu32"\n",
               ctxt_pP->module_id,
               ctxt_pP->frame );
        decode_SI( ctxt_pP, eNB_index );
        //if (nfapi_mode == 3)
        	UE_mac_inst[ctxt_pP->module_id].SI_Decoded = 1;
      }

      break;

    case LTE_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
    default:
      break;
    }
  }

  if ((rrc_get_sub_state(ctxt_pP->module_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE)
#if defined(ENABLE_USE_MME)
      && (UE_rrc_inst[ctxt_pP->module_id].initialNasMsg.data != NULL)
#endif
     ) {
    rrc_ue_generate_RRCConnectionRequest(ctxt_pP, 0);
    rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_CONNECTING );
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );

  return 0;
}

//-----------------------------------------------------------------------------
int decode_PCCH_DLSCH_Message(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                eNB_index,
  uint8_t*               const Sdu,
  const uint8_t                Sdu_len)
{
  LTE_PCCH_Message_t *pcch_message = NULL;
  int i;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN );

  asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
                            &asn_DEF_LTE_PCCH_Message,
                            (void **)&pcch_message,
                            (const void *)Sdu,
                            Sdu_len );

  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    LOG_E( RRC, "[UE %"PRIu8"] Failed to decode PCCH_MESSAGE (%zu bits)\n",
           ctxt_pP->module_id,
           dec_rval.consumed );
    for (i=0;i<Sdu_len;i++)
      printf("%02x ",Sdu[i]);
    printf("\n");
    // free the memory
    SEQUENCE_free( &asn_DEF_LTE_PCCH_Message, (void*)pcch_message, 1 );
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_OUT );
    return -1;
  }

  return(0);
}

//-----------------------------------------------------------------------------
int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t rsrq, const uint8_t rsrp )
{
  LTE_SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN );

  LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id );

  LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_Identity;

  int mccdigits = PLMN_identity->mcc->list.count;
  int mncdigits = PLMN_identity->mnc.list.count;

  int mcc;

  if (mccdigits == 2) {
    mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1];
  } else {
    mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2];
  }

  int mnc;

  if (mncdigits == 2) {
    mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1];
  } else {
    mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2];
  }

  LOG_I( RRC, "PLMN MCC %0*d, MNC %0*d, TAC 0x%04x\n", mccdigits, mcc, mncdigits, mnc, 
       ((sib1->cellAccessRelatedInfo.trackingAreaCode.size == 2)?((sib1->cellAccessRelatedInfo.trackingAreaCode.buf[0]<<8) + sib1->cellAccessRelatedInfo.trackingAreaCode.buf[1]):0));
  LOG_I( RRC, "cellReservedForOperatorUse                 : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) );

  // search internal table for provider name
  int plmn_ind = 0;

  while (plmn_data[plmn_ind].mcc > 0) {
    if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) {
      LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short );
      break;
    }

    plmn_ind++;
  }

  if (plmn_data[plmn_ind].mcc < 0) {
    LOG_I( RRC, "Found Unknown operator (no entry in internal table)\n" );
  }

  LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity         : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n",
         BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.cellIdentity ),
         sib1->cellAccessRelatedInfo.cellIdentity.buf[0],
         sib1->cellAccessRelatedInfo.cellIdentity.buf[1],
         sib1->cellAccessRelatedInfo.cellIdentity.buf[2],
         sib1->cellAccessRelatedInfo.cellIdentity.buf[3] >> sib1->cellAccessRelatedInfo.cellIdentity.bits_unused);

  LOG_I( RRC, "cellAccessRelatedInfo.cellBarred           : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.cellBarred, SIBbarred(sib1->cellAccessRelatedInfo.cellBarred) );
  LOG_I( RRC, "cellAccessRelatedInfo.intraFreqReselection : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.intraFreqReselection, SIBallowed(sib1->cellAccessRelatedInfo.intraFreqReselection) );
  LOG_I( RRC, "cellAccessRelatedInfo.csg_Indication       : %d\n", sib1->cellAccessRelatedInfo.csg_Indication );

  if (sib1->cellAccessRelatedInfo.csg_Identity)
    LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity         : %"PRIu32"\n", BIT_STRING_to_uint32(sib1->cellAccessRelatedInfo.csg_Identity) );
  else
    LOG_I( RRC, "cellAccessRelatedInfo.csg_Identity         : not defined\n" );

  LOG_I( RRC, "cellSelectionInfo.q_RxLevMin               : %ld\n", sib1->cellSelectionInfo.q_RxLevMin );

  if (sib1->cellSelectionInfo.q_RxLevMinOffset)
    LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset         : %ld\n", *sib1->cellSelectionInfo.q_RxLevMinOffset );
  else
    LOG_I( RRC, "cellSelectionInfo.q_RxLevMinOffset         : not defined\n" );

  if (sib1->p_Max)
    LOG_I( RRC, "p_Max                                      : %ld\n", *sib1->p_Max );
  else
    LOG_I( RRC, "p_Max                                      : not defined\n" );

  LOG_I( RRC, "freqBandIndicator                          : %ld\n", sib1->freqBandIndicator );

  if (sib1->schedulingInfoList.list.count > 0) {
    for (int i=0; i<sib1->schedulingInfoList.list.count; i++) {
      LOG_I( RRC, "si_Periodicity[%d]                          : %s\n", i, SIBPeriod[min(sib1->schedulingInfoList.list.array[i]->si_Periodicity,7)]);

      if (sib1->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count > 0) {
        char temp[32 * sizeof(SIBType[0])] = {0}; // maxSIB==32

        for (int j=0; j<sib1->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count; j++) {
          sprintf( temp + j*sizeof(SIBType[0]), "%*s ", (int)sizeof(SIBType[0])-1, SIBType[min(*sib1->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[0],11)] );
        }

        LOG_I( RRC, "siSchedulingInfoSIBType[%d]                 : %s\n", i, temp );
      } else {
        LOG_I( RRC, "mapping list %d is null\n", i );
      }
    }
  } else {
    LOG_E( RRC, "siSchedulingInfoPeriod[0]                  : PROBLEM!!!\n" );
    return -1;
  }

  if (sib1->tdd_Config) {
    LOG_I( RRC, "TDD subframeAssignment                     : %ld\n", sib1->tdd_Config->subframeAssignment );
    LOG_I( RRC, "TDD specialSubframePatterns                : %ld\n", sib1->tdd_Config->specialSubframePatterns );
  }

  LOG_I( RRC, "siWindowLength                             : %s\n", siWindowLength[min(sib1->si_WindowLength,7)] );
  LOG_I( RRC, "systemInfoValueTag                         : %ld\n", sib1->systemInfoValueTag );

  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod     = siPeriod_int[sib1->schedulingInfoList.list.array[0]->si_Periodicity];
  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize = siWindowLength_int[sib1->si_WindowLength];
  LOG_I( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
         ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );

  rrc_mac_config_req_ue(ctxt_pP->module_id, 0, eNB_index,
			(LTE_RadioResourceConfigCommonSIB_t *)NULL,
			(struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			(LTE_SCellToAddMod_r10_t *)NULL,
			//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
			(LTE_MeasObjectToAddMod_t **)NULL,
			(LTE_MAC_MainConfig_t *)NULL,
			0,
			(struct LTE_LogicalChannelConfig *)NULL,
			(LTE_MeasGapConfig_t *)NULL,
			UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]->tdd_Config,
			(LTE_MobilityControlInfo_t *) NULL,
			&UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIwindowsize,
			&UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIperiod,
			NULL,
			NULL,
			NULL,
			(LTE_MBSFN_SubframeConfigList_t *)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
			,0,
			(LTE_MBSFN_AreaInfoList_r9_t *)NULL,
			(LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
			,
			0,
			0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			);

  LOG_I(RRC,"Setting SIStatus bit 0 to 1\n");
  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus = 1;
  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIB1systemInfoValueTag = sib1->systemInfoValueTag;

#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
  {
    int cell_valid = 0;

    if (sib1->cellAccessRelatedInfo.cellBarred == LTE_SystemInformationBlockType1__cellAccessRelatedInfo__cellBarred_notBarred) {
      /* Cell is not barred */
      int plmn;
      int plmn_number;

      plmn_number = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count;

      /* Compare requested PLMN and PLMNs from SIB1*/
      for (plmn = 0; plmn < plmn_number; plmn++) {
        LTE_PLMN_Identity_t *plmn_Identity;

        plmn_Identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_Identity;

        if (
          (
            (plmn_Identity->mcc == NULL)
            ||
            (
              (UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) &&
              (UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) &&
              (UE_rrc_inst[ctxt_pP->module_id].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2]))
            )
          )
          &&
          (UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0]))
          &&
          (UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1]))
          &&
          (
            ((UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2))
            ||
            (UE_rrc_inst[ctxt_pP->module_id].plmnID.MNCdigit3 == *(plmn_Identity->mnc.list.array[2]))
          )
        ) {
          /* PLMN match, send a confirmation to NAS */
          MessageDef  *msg_p;

          msg_p = itti_alloc_new_message(TASK_RRC_UE, NAS_CELL_SELECTION_CNF);
          NAS_CELL_SELECTION_CNF (msg_p).errCode = AS_SUCCESS;
          NAS_CELL_SELECTION_CNF (msg_p).cellID = BIT_STRING_to_uint32(&sib1->cellAccessRelatedInfo.cellIdentity);
          NAS_CELL_SELECTION_CNF (msg_p).tac = BIT_STRING_to_uint16(&sib1->cellAccessRelatedInfo.trackingAreaCode);
          NAS_CELL_SELECTION_CNF (msg_p).rat = 0xFF;
          NAS_CELL_SELECTION_CNF (msg_p).rsrq = rsrq;
          NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp;

          itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p);
          cell_valid = 1;
          break;
        }
      }
    }

    if (cell_valid == 0) {
      /* Cell can not be used, ask PHY to try the next one */
      MessageDef  *msg_p;

      msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ);

      itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p);
    }
  }
#endif

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_OUT );

  return 0;
}


//-----------------------------------------------------------------------------
 void dump_sib2( LTE_SystemInformationBlockType2_t *sib2 )
{
  // ac_BarringInfo
  if (sib2->ac_BarringInfo) {
    LOG_I( RRC, "ac_BarringInfo->ac_BarringForEmergency : %d\n",
           sib2->ac_BarringInfo->ac_BarringForEmergency );

    if (sib2->ac_BarringInfo->ac_BarringForMO_Signalling) {
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Signalling->ac_BarringFactor       : %ld\n",
             sib2->ac_BarringInfo->ac_BarringForMO_Signalling->ac_BarringFactor );
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Signalling->ac_BarringTime         : %ld\n",
             sib2->ac_BarringInfo->ac_BarringForMO_Signalling->ac_BarringTime );
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Signalling->ac_BarringForSpecialAC : %"PRIu32"\n",
             BIT_STRING_to_uint32(&sib2->ac_BarringInfo->ac_BarringForMO_Signalling->ac_BarringForSpecialAC) );
    } else
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Signalling : not defined\n" );

    if (sib2->ac_BarringInfo->ac_BarringForMO_Data) {
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Data->ac_BarringFactor       : %ld\n",
             sib2->ac_BarringInfo->ac_BarringForMO_Data->ac_BarringFactor );
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Data->ac_BarringTime         : %ld\n",
             sib2->ac_BarringInfo->ac_BarringForMO_Data->ac_BarringTime );
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Data->ac_BarringForSpecialAC : %"PRIu32"\n",
             BIT_STRING_to_uint32(&sib2->ac_BarringInfo->ac_BarringForMO_Data->ac_BarringForSpecialAC) );
    } else
      LOG_I( RRC, "ac_BarringInfo->ac_BarringForMO_Data : not defined\n" );
  } else
    LOG_I( RRC, "ac_BarringInfo : not defined\n" );

  // RACH
  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.numberOfRA_Preambles  : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.numberOfRA_Preambles,
         SIB2numberOfRA_Preambles(sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.numberOfRA_Preambles) );

  if (sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig) {
    LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA : %ld\n",
           sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA );
    LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig->messageSizeGroupA        : %ld\n",
           sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig->messageSizeGroupA );
    LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig->messagePowerOffsetGroupB : %ld\n",
           sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig->messagePowerOffsetGroupB );
  } else {
    LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig : not defined\n" );
  }

  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.powerRampingStep                   : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.powerRampingStep,
         SIB2powerRampingStep(sib2->radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.powerRampingStep) );
  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.preambleInitialReceivedTargetPower : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.preambleInitialReceivedTargetPower,
         SIB2preambleInitialReceivedTargetPower(sib2->radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.preambleInitialReceivedTargetPower) );

  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.preambleTransMax              : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.preambleTransMax,
         SIB2preambleTransMax(sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.preambleTransMax) );
  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.ra_ResponseWindowSize         : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.ra_ResponseWindowSize,
         SIB2ra_ResponseWindowSize(sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.ra_ResponseWindowSize) );
  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.mac_ContentionResolutionTimer : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.mac_ContentionResolutionTimer,
         SIB2mac_ContentionResolutionTimer(sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.mac_ContentionResolutionTimer) );

  LOG_I( RRC, "radioResourceConfigCommon.rach_ConfigCommon.maxHARQ_Msg3Tx : %ld\n",
         sib2->radioResourceConfigCommon.rach_ConfigCommon.maxHARQ_Msg3Tx );

  // BCCH
  LOG_I( RRC, "radioResourceConfigCommon.bcch_Config.modificationPeriodCoeff : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.bcch_Config.modificationPeriodCoeff,
         SIB2modificationPeriodCoeff(sib2->radioResourceConfigCommon.bcch_Config.modificationPeriodCoeff) );

  // PCCH
  LOG_I( RRC, "radioResourceConfigCommon.pcch_Config.defaultPagingCycle : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.pcch_Config.defaultPagingCycle,
         SIB2defaultPagingCycle(sib2->radioResourceConfigCommon.pcch_Config.defaultPagingCycle) );
  LOG_I( RRC, "radioResourceConfigCommon.pcch_Config.nB                 : raw:%ld decoded:%s\n",
         sib2->radioResourceConfigCommon.pcch_Config.nB,
         SIB2nB(sib2->radioResourceConfigCommon.pcch_Config.nB) );

  // PRACH
  LOG_I( RRC, "radioResourceConfigCommon.prach_Config.rootSequenceIndex                          : %ld\n",
         sib2->radioResourceConfigCommon.prach_Config.rootSequenceIndex );
  LOG_I( RRC, "radioResourceConfigCommon.prach_Config.prach_ConfigInfo.prach_ConfigIndex         : %ld\n",
         sib2->radioResourceConfigCommon.prach_Config.prach_ConfigInfo.prach_ConfigIndex );
  LOG_I( RRC, "radioResourceConfigCommon.prach_Config.prach_ConfigInfo.highSpeedFlag             : %d\n",
         sib2->radioResourceConfigCommon.prach_Config.prach_ConfigInfo.highSpeedFlag );
  LOG_I( RRC, "radioResourceConfigCommon.prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig : %ld\n",
         sib2->radioResourceConfigCommon.prach_Config.prach_ConfigInfo.zeroCorrelationZoneConfig );
  LOG_I( RRC, "radioResourceConfigCommon.prach_Config.prach_ConfigInfo.prach_FreqOffset          : %ld\n",
         sib2->radioResourceConfigCommon.prach_Config.prach_ConfigInfo.prach_FreqOffset );

  // PDSCH-Config
  LOG_I( RRC, "radioResourceConfigCommon.pdsch_ConfigCommon.referenceSignalPower : %ld\n",
         sib2->radioResourceConfigCommon.pdsch_ConfigCommon.referenceSignalPower );
  LOG_I( RRC, "radioResourceConfigCommon.pdsch_ConfigCommon.p_b                  : %ld\n",
         sib2->radioResourceConfigCommon.pdsch_ConfigCommon.p_b );

  // PUSCH-Config
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.n_SB                : %ld\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.n_SB );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode         : %ld\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.hoppingMode );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset : %ld\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.pusch_HoppingOffset );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM         : %d\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.pusch_ConfigBasic.enable64QAM );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled    : %d\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupHoppingEnabled );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH   : %ld\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled : %d\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled );
  LOG_I( RRC, "radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift            : %ld\n",
         sib2->radioResourceConfigCommon.pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift );

  // PUCCH-Config
  LOG_I( RRC, "radioResourceConfigCommon.pucch_ConfigCommon.deltaPUCCH_Shift : %ld\n",
         sib2->radioResourceConfigCommon.pucch_ConfigCommon.deltaPUCCH_Shift );
  LOG_I( RRC, "radioResourceConfigCommon.pucch_ConfigCommon.nRB_CQI          : %ld\n",
         sib2->radioResourceConfigCommon.pucch_ConfigCommon.nRB_CQI );
  LOG_I( RRC, "radioResourceConfigCommon.pucch_ConfigCommon.nCS_AN           : %ld\n",
         sib2->radioResourceConfigCommon.pucch_ConfigCommon.nCS_AN );
  LOG_I( RRC, "radioResourceConfigCommon.pucch_ConfigCommon.n1PUCCH_AN       : %ld\n",
         sib2->radioResourceConfigCommon.pucch_ConfigCommon.n1PUCCH_AN );

  // SoundingRS_UL_Config
  LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.present : raw:%d decoded:%s\n",
         sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.present,
         SIB2SoundingPresent(sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.present) );

  if (sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.present == LTE_SoundingRS_UL_ConfigCommon_PR_setup) {
    LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig                 : %ld\n",
           sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_BandwidthConfig );
    LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig                  : %ld\n",
           sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_SubframeConfig );
    LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission : %d\n",
           sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.ackNackSRS_SimultaneousTransmission );

    if(sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts)
    {
    LOG_I( RRC, "radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts                        : %ld\n",
           /* TODO: check that it's okay to access [0] */
           sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon.choice.setup.srs_MaxUpPts[0] );
    }
  }

  // uplinkPowerControlCommon
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.p0_NominalPUSCH   : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.p0_NominalPUSCH );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.alpha             : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.alpha );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.p0_NominalPUCCH   : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.p0_NominalPUCCH );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1  : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1 );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format1b );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2  : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2 );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2a );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaFList_PUCCH.deltaF_PUCCH_Format2b );
  LOG_I( RRC, "radioResourceConfigCommon.uplinkPowerControlCommon.deltaPreambleMsg3 : %ld\n",
         sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaPreambleMsg3 );

  LOG_I( RRC, "radioResourceConfigCommon.ul_CyclicPrefixLength : %ld\n",
         sib2->radioResourceConfigCommon.ul_CyclicPrefixLength );

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 2, 0))
  // UplinkPowerControlCommon_v1020
  // ...
#endif

  LOG_I( RRC, "ue_TimersAndConstants.t300 : %ld\n", sib2->ue_TimersAndConstants.t300 );
  LOG_I( RRC, "ue_TimersAndConstants.t301 : %ld\n", sib2->ue_TimersAndConstants.t301 );
  LOG_I( RRC, "ue_TimersAndConstants.t310 : %ld\n", sib2->ue_TimersAndConstants.t310 );
  LOG_I( RRC, "ue_TimersAndConstants.n310 : %ld\n", sib2->ue_TimersAndConstants.n310 );
  LOG_I( RRC, "ue_TimersAndConstants.t311 : %ld\n", sib2->ue_TimersAndConstants.t311 );
  LOG_I( RRC, "ue_TimersAndConstants.n311 : %ld\n", sib2->ue_TimersAndConstants.n311 );

  if (sib2->freqInfo.ul_CarrierFreq)
    LOG_I( RRC, "freqInfo.ul_CarrierFreq             : %ld\n", *sib2->freqInfo.ul_CarrierFreq );
  else
    LOG_I( RRC, "freqInfo.ul_CarrierFreq             : not defined\n" );

  if (sib2->freqInfo.ul_Bandwidth)
    LOG_I( RRC, "freqInfo.ul_Bandwidth               : %ld\n", *sib2->freqInfo.ul_Bandwidth );
  else
    LOG_I( RRC, "freqInfo.ul_Bandwidth               : not defined\n" );

  LOG_I( RRC, "freqInfo.additionalSpectrumEmission : %ld\n", sib2->freqInfo.additionalSpectrumEmission );

  if (sib2->mbsfn_SubframeConfigList) {
    LOG_I( RRC, "mbsfn_SubframeConfigList : %p\n", sib2->mbsfn_SubframeConfigList );
    // FIXME
  } else
    LOG_I( RRC, "mbsfn_SubframeConfigList : not defined\n" );

  LOG_I( RRC, "timeAlignmentTimerCommon : %ld\n", sib2->timeAlignmentTimerCommon );

#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
  if (sib2->lateNonCriticalExtension) {
    LOG_I( RRC, "lateNonCriticalExtension : %p\n", sib2->lateNonCriticalExtension );
  } else
    LOG_I( RRC, "lateNonCriticalExtension : not defined\n" );
#endif

#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
  if (sib2->ext1 && sib2->ext1->ssac_BarringForMMTEL_Voice_r9) {
    LOG_I( RRC, "ssac_BarringForMMTEL_Voice_r9->ac_BarringFactor       : %ld\n",
           sib2->ext1->ssac_BarringForMMTEL_Voice_r9->ac_BarringFactor );
    LOG_I( RRC, "ssac_BarringForMMTEL_Voice_r9->ac_BarringTime         : %ld\n",
           sib2->ext1->ssac_BarringForMMTEL_Voice_r9->ac_BarringTime );
    LOG_I( RRC, "ssac_BarringForMMTEL_Voice_r9->ac_BarringForSpecialAC : %"PRIu32"\n",
           BIT_STRING_to_uint32(&sib2->ext1->ssac_BarringForMMTEL_Voice_r9->ac_BarringForSpecialAC) );
  } else
    LOG_I( RRC, "ssac_BarringForMMTEL_Voice_r9 : not defined\n" );

  if (sib2->ext1 && sib2->ext1->ssac_BarringForMMTEL_Video_r9) {
    LOG_I( RRC, "ssac_BarringForMMTEL_Video_r9->ac_BarringFactor       : %ld\n",
           sib2->ext1->ssac_BarringForMMTEL_Video_r9->ac_BarringFactor );
    LOG_I( RRC, "ssac_BarringForMMTEL_Video_r9->ac_BarringTime         : %ld\n",
           sib2->ext1->ssac_BarringForMMTEL_Video_r9->ac_BarringTime );
    LOG_I( RRC, "ssac_BarringForMMTEL_Video_r9->ac_BarringForSpecialAC : %"PRIu32"\n",
           BIT_STRING_to_uint32(&sib2->ext1->ssac_BarringForMMTEL_Video_r9->ac_BarringForSpecialAC) );
  } else
    LOG_I( RRC, "ssac_BarringForMMTEL_Video_r9 : not defined\n" );
#endif

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
  if (sib2->ext2 && sib2->ext2->ac_BarringForCSFB_r10) {
    LOG_I( RRC, "ac_BarringForCSFB_r10->ac_BarringFactor       : %ld\n",
           sib2->ext2->ac_BarringForCSFB_r10->ac_BarringFactor );
    LOG_I( RRC, "ac_BarringForCSFB_r10->ac_BarringTime         : %ld\n",
           sib2->ext2->ac_BarringForCSFB_r10->ac_BarringTime );
    LOG_I( RRC, "ac_BarringForCSFB_r10->ac_BarringForSpecialAC : %"PRIu32"\n",
           BIT_STRING_to_uint32(&sib2->ext2->ac_BarringForCSFB_r10->ac_BarringForSpecialAC) );
  } else
    LOG_I( RRC, "ac_BarringForCSFB_r10 : not defined\n" );

#endif
}

//-----------------------------------------------------------------------------
 void dump_sib3( LTE_SystemInformationBlockType3_t *sib3 )
{
  LOG_I( RRC, "Dumping SIB3 (see TS36.331 V8.21.0)\n" );

  int q_Hyst_dB = sib3->cellReselectionInfoCommon.q_Hyst; // sib3->cellReselectionInfoCommon.q_Hyst is a enumerated value

  if (q_Hyst_dB > 6)
    q_Hyst_dB = (q_Hyst_dB-6) * 2 + 6;

  LOG_I( RRC, "cellReselectionInfoCommon.q_Hyst : raw:%ld  decoded:%d dB\n", sib3->cellReselectionInfoCommon.q_Hyst, q_Hyst_dB );

  if (sib3->cellReselectionInfoCommon.speedStateReselectionPars) {
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_Evaluation : %ld\n",
           sib3->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_Evaluation );
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_HystNormal : %ld\n",
           sib3->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.t_HystNormal );
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeMedium : %ld\n",
           sib3->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeMedium );
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeHigh : %ld\n",
           sib3->cellReselectionInfoCommon.speedStateReselectionPars->mobilityStateParameters.n_CellChangeHigh );
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_Medium : raw:%ld decoded:%ld dB\n", sib3->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_Medium,
           6 - 2 * sib3->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_Medium );
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_High : raw:%ld decoded:%ld dB\n", sib3->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_High,
           6 - 2 * sib3->cellReselectionInfoCommon.speedStateReselectionPars->q_HystSF.sf_High );
  } else {
    LOG_I( RRC, "cellReselectionInfoCommon.speedStateReselectionPars : not defined\n" );
  }

  if (sib3->cellReselectionServingFreqInfo.s_NonIntraSearch) {
    LOG_I( RRC, "cellReselectionServingFreqInfo.s_NonIntraSearch : %ld\n", *(sib3->cellReselectionServingFreqInfo.s_NonIntraSearch) );
  } else {
    LOG_I( RRC, "cellReselectionServingFreqInfo.s_NonIntraSearch : not defined\n" );
  }

  LOG_I( RRC, "cellReselectionServingFreqInfo.threshServingLow : %ld\n", sib3->cellReselectionServingFreqInfo.threshServingLow );
  LOG_I( RRC, "cellReselectionServingFreqInfo.cellReselectionPriority : %ld\n", sib3->cellReselectionServingFreqInfo.cellReselectionPriority );

  LOG_I( RRC, "intraFreqCellReselectionInfo.q_RxLevMin : %ld\n", sib3->intraFreqCellReselectionInfo.q_RxLevMin );

  if (sib3->intraFreqCellReselectionInfo.p_Max) {
    LOG_I( RRC, "intraFreqCellReselectionInfo.p_Max : %ld\n", *(sib3->intraFreqCellReselectionInfo.p_Max) );
  } else {
    LOG_I( RRC, "intraFreqCellReselectionInfo.p_Max : not defined\n" );
  }

  if (sib3->intraFreqCellReselectionInfo.s_IntraSearch) {
    LOG_I( RRC, "intraFreqCellReselectionInfo.s_IntraSearch : %ld\n", *(sib3->intraFreqCellReselectionInfo.s_IntraSearch) );
  } else {
    LOG_I( RRC, "intraFreqCellReselectionInfo.s_IntraSearch : not defined\n" );
  }

  if (sib3->intraFreqCellReselectionInfo.allowedMeasBandwidth) {
    LOG_I( RRC, "intraFreqCellReselectionInfo.allowedMeasBandwidth : %ld\n", *(sib3->intraFreqCellReselectionInfo.allowedMeasBandwidth) );
  } else {
    LOG_I( RRC, "intraFreqCellReselectionInfo.allowedMeasBandwidth : not defined\n" );
  }

  LOG_I( RRC, "intraFreqCellReselectionInfo.presenceAntennaPort1 : %d\n", sib3->intraFreqCellReselectionInfo.presenceAntennaPort1 );
  LOG_I( RRC, "intraFreqCellReselectionInfo.neighCellConfig : %"PRIu8"\n", BIT_STRING_to_uint8( &(sib3->intraFreqCellReselectionInfo.neighCellConfig) ) );
  LOG_I( RRC, "intraFreqCellReselectionInfo.t_ReselectionEUTRA : %ld\n", sib3->intraFreqCellReselectionInfo.t_ReselectionEUTRA );

  if (sib3->intraFreqCellReselectionInfo.t_ReselectionEUTRA_SF) {
    LOG_I( RRC, "intraFreqCellReselectionInfo.t_ReselectionEUTRA_SF->sf_Medium : %ld\n", sib3->intraFreqCellReselectionInfo.t_ReselectionEUTRA_SF->sf_Medium );
    LOG_I( RRC, "intraFreqCellReselectionInfo.t_ReselectionEUTRA_SF->sf_High : %ld\n", sib3->intraFreqCellReselectionInfo.t_ReselectionEUTRA_SF->sf_High );
  } else {
    LOG_I( RRC, "intraFreqCellReselectionInfo.t_ReselectionEUTRA_SF : not defined\n" );
  }
}

int Qoffsettab[31] = {-24,-22,-20,-18,-16,-14,-12,-10,-8,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,8,10,12,14,16,18,20,22,24};
int PhysCellIdRange[16] = {4,8,12,16,24,32,48,64,84,96,128,168,252,504,0,0};

uint64_t arfcn_to_freq(long arfcn) {

  if (arfcn < 600)  // Band 1
    return((uint64_t)2110000000 + (arfcn*100000));
  else if (arfcn <1200) // Band 2
    return((uint64_t)1930000000 + ((arfcn-600)*100000));
  else if (arfcn <1950) // Band 3
    return((uint64_t)1805000000 + ((arfcn-1200)*100000));
  else if (arfcn <2400) // Band 4
    return((uint64_t)2110000000 + ((arfcn-1950)*100000));
  else if (arfcn <2650) // Band 5
    return((uint64_t)869000000 + ((arfcn-2400)*100000));
  else if (arfcn <2750) // Band 6
    return((uint64_t)875000000 + ((arfcn-2650)*100000));
  else if (arfcn <3450) // Band 7
    return((uint64_t)2620000000 + ((arfcn-2750)*100000));
  else if (arfcn <3800) // Band 8
    return((uint64_t)925000000 + ((arfcn-3450)*100000));
  else if (arfcn <4150) // Band 9
    return((uint64_t)1844900000 + ((arfcn-3800)*100000));
  else if (arfcn <4650) // Band 10
    return((uint64_t)2110000000 + ((arfcn-4150)*100000));
  else if (arfcn <5010) // Band 11
    return((uint64_t)1475900000 + ((arfcn-4750)*100000));
  else if (arfcn <5180) // Band 12
    return((uint64_t)729000000 + ((arfcn-5010)*100000));
  else if (arfcn <5280) // Band 13
    return((uint64_t)746000000 + ((arfcn-5180)*100000));
  else if (arfcn <5730) // Band 14
    return((uint64_t)758000000 + ((arfcn-5280)*100000));
  else if (arfcn <5850) // Band 17
    return((uint64_t)734000000 + ((arfcn-5730)*100000));
  else if (arfcn <6000) // Band 18
    return((uint64_t)860000000 + ((arfcn-5850)*100000));
  else if (arfcn <6150) // Band 19
    return((uint64_t)875000000 + ((arfcn-6000)*100000));
  else if (arfcn <6450) // Band 20
    return((uint64_t)791000000 + ((arfcn-6150)*100000));
  else if (arfcn <6600) // Band 21
    return((uint64_t)1495900000 + ((arfcn-6450)*100000));
  else if (arfcn <7500) // Band 22
    return((uint64_t)351000000 + ((arfcn-6600)*100000));
  else if (arfcn <7700) // Band 23
    return((uint64_t)2180000000 + ((arfcn-7500)*100000));
  else if (arfcn <8040) // Band 24
    return((uint64_t)1525000000 + ((arfcn-7700)*100000));
  else if (arfcn <8690) // Band 25
    return((uint64_t)1930000000 + ((arfcn-8040)*100000));
  else if (arfcn <36200) // Band 33
    return((uint64_t)1900000000 + ((arfcn-36000)*100000));
  else if (arfcn <36350) // Band 34
    return((uint64_t)2010000000 + ((arfcn-36200)*100000));
  else if (arfcn <36950) // Band 35
    return((uint64_t)1850000000 + ((arfcn-36350)*100000));
  else if (arfcn <37550) // Band 36
    return((uint64_t)1930000000 + ((arfcn-36950)*100000));
  else if (arfcn <37750) // Band 37
    return((uint64_t)1910000000 + ((arfcn-37550)*100000));
  else if (arfcn <38250) // Band 38
    return((uint64_t)2570000000 + ((arfcn-37750)*100000));
  else if (arfcn <38650) // Band 39
    return((uint64_t)1880000000 + ((arfcn-38250)*100000));
  else if (arfcn <39650) // Band 40
    return((uint64_t)2300000000 + ((arfcn-38650)*100000));
  else if (arfcn <41590) // Band 41
    return((uint64_t)2496000000 + ((arfcn-39650)*100000));
  else if (arfcn <43590) // Band 42
    return((uint64_t)3400000000 + ((arfcn-41590)*100000));
  else if (arfcn <45590) // Band 43
    return((uint64_t)3600000000 + ((arfcn-43950)*100000));
  else {
    LOG_E(RRC,"Unknown EARFCN %ld\n",arfcn);
    exit(1);
  }
}
 void dump_sib5( LTE_SystemInformationBlockType5_t *sib5 )
{
  LTE_InterFreqCarrierFreqList_t interFreqCarrierFreqList = sib5->interFreqCarrierFreqList;
  int i,j;
  LTE_InterFreqCarrierFreqInfo_t *ifcfInfo;

  LOG_I( RRC, "Dumping SIB5 (see TS36.331 V8.21.0)\n" );

  for (i=0;i<interFreqCarrierFreqList.list.count;i++) {
    LOG_I(RRC, "SIB5 InterFreqCarrierFreq element %d/%d\n",i,interFreqCarrierFreqList.list.count);
    ifcfInfo = interFreqCarrierFreqList.list.array[i];
    LOG_I(RRC, "   DL Carrier Frequency/ARFCN : %ld/%ld\n",
	  arfcn_to_freq(ifcfInfo->dl_CarrierFreq),
	  ifcfInfo->dl_CarrierFreq);
    LOG_I(RRC,"   Q_RXLevMin : %ld\n", ifcfInfo->q_RxLevMin);
    if (ifcfInfo->p_Max != NULL)
      LOG_I(RRC,"   P_max : %ld\n", *ifcfInfo->p_Max);
    LOG_I(RRC,"   T_ReselectionEUTRA : %ld\n",ifcfInfo->t_ReselectionEUTRA);
    if (ifcfInfo->t_ReselectionEUTRA_SF) {
      LOG_I(RRC,"   t_ReselectionEUTRA_SF.sf_Medium %ld, t_ReselectionEUTRA_SF.sf_High %ld",
	    ifcfInfo->t_ReselectionEUTRA_SF->sf_Medium,
	    ifcfInfo->t_ReselectionEUTRA_SF->sf_High);
    }
    LOG_I(RRC,"   threshX_High : %ld\n",ifcfInfo->threshX_High);
    LOG_I(RRC,"   threshX_Low : %ld\n",ifcfInfo->threshX_Low);
    switch(ifcfInfo->allowedMeasBandwidth) {
    case LTE_AllowedMeasBandwidth_mbw6:
      LOG_I(RRC,"   AllowedMeasBandwidth : 6\n");
      break;
    case LTE_AllowedMeasBandwidth_mbw15:
      LOG_I(RRC,"   AllowedMeasBandwidth : 15\n");
      break;
    case LTE_AllowedMeasBandwidth_mbw25:
      LOG_I(RRC,"   AllowedMeasBandwidth : 25\n");
      break;
    case LTE_AllowedMeasBandwidth_mbw50:
      LOG_I(RRC,"   AllowedMeasBandwidth : 50\n");
      break;
    case LTE_AllowedMeasBandwidth_mbw75:
      LOG_I(RRC,"   AllowedMeasBandwidth : 75\n");
      break;
    case LTE_AllowedMeasBandwidth_mbw100:
      LOG_I(RRC,"   AllowedMeasBandwidth : 100\n");
      break;
    }
    if (ifcfInfo->presenceAntennaPort1)
      LOG_I(RRC,"   PresenceAntennaPort1 : True\n");
    else
      LOG_I(RRC,"   PresenceAntennaPort1 : False\n");
    if (ifcfInfo->cellReselectionPriority) {
      LOG_I(RRC,"   CellReselectionPriority : %ld\n",
	    *ifcfInfo->cellReselectionPriority);
    }
    LOG_I(RRC,"   NeighCellConfig  : ");
    for (j=0;j<ifcfInfo->neighCellConfig.size;j++) {
      printf("%2x ",ifcfInfo->neighCellConfig.buf[j]);
    }
    printf("\n");
    if (ifcfInfo->q_OffsetFreq)
      LOG_I(RRC,"   Q_OffsetFreq : %d\n",Qoffsettab[*ifcfInfo->q_OffsetFreq]);
    if (ifcfInfo->interFreqNeighCellList) {

      for (j=0;j<ifcfInfo->interFreqNeighCellList->list.count;j++) {
	LOG_I(RRC,"   Cell %d\n", j);
	LOG_I(RRC,"      PhysCellId : %ld\n",ifcfInfo->interFreqNeighCellList->list.array[j]->physCellId);
	LOG_I(RRC,"      Q_OffsetRange : %ld\n",ifcfInfo->interFreqNeighCellList->list.array[j]->q_OffsetCell);

      }
    }
    if (ifcfInfo->interFreqBlackCellList) {

      for (j=0;j<ifcfInfo->interFreqBlackCellList->list.count;j++) {
	LOG_I(RRC,"   Cell %d\n", j);
	LOG_I(RRC,"      PhysCellId start: %ld\n",ifcfInfo->interFreqBlackCellList->list.array[j]->start);
	if (ifcfInfo->interFreqBlackCellList->list.array[i]->range) {
	  LOG_I(RRC,"      PhysCellId Range : %ld\n",*ifcfInfo->interFreqBlackCellList->list.array[j]->range);
	}
      }
    }
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
    if (ifcfInfo->ext1 && ifcfInfo->ext1->q_QualMin_r9)
      LOG_I(RRC,"   Q_QualMin_r9 : %ld\n",*ifcfInfo->ext1->q_QualMin_r9);

    if (ifcfInfo->ext1 && ifcfInfo->ext1->threshX_Q_r9) {
      LOG_I(RRC,"   threshX_HighQ_r9 : %ld\n",ifcfInfo->ext1->threshX_Q_r9->threshX_HighQ_r9);
      LOG_I(RRC,"   threshX_LowQ_r9: %ld\n",ifcfInfo->ext1->threshX_Q_r9->threshX_LowQ_r9);
    }
#endif
  }

}

#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
 void dump_sib13( LTE_SystemInformationBlockType13_r9_t *sib13 )
{
  LOG_I( RRC, "[UE] Dumping SIB13\n" );
  LOG_I( RRC, "[UE] dumping sib13 second time\n" );
  LOG_I( RRC, "[UE] NotificationRepetitionCoeff-r9 : %ld\n", sib13->notificationConfig_r9.notificationRepetitionCoeff_r9 );
  LOG_I( RRC, "[UE] NotificationOffset-r9 : %d\n", (int)sib13->notificationConfig_r9.notificationOffset_r9 );
  LOG_I( RRC, "[UE] NotificationSF-Index-r9 : %d\n", (int)sib13->notificationConfig_r9.notificationSF_Index_r9 );
}


//TTN - SIB18
//-----------------------------------------------------------------------------
 void dump_sib18(LTE_SystemInformationBlockType18_r12_t *sib18){
   LOG_I( RRC, "[UE] Dumping SIB18\n" );
   for (int i = 0; i < sib18->commConfig_r12->commRxPool_r12.list.count; i++) {
       LOG_I(RRC, " Contents of SIB18 %d/%d \n", i+1, sib18->commConfig_r12->commRxPool_r12.list.count);
       LOG_I(RRC, " SIB18 rxPool_sc_CP_Len: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_CP_Len_r12);
       LOG_I(RRC, " SIB18 sc_Period_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_Period_r12);
       LOG_I(RRC, " SIB18 data_CP_Len_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->data_CP_Len_r12);
       LOG_I(RRC, " SIB18 prb_Num_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_TF_ResourceConfig_r12.prb_Num_r12);
       LOG_I(RRC, " SIB18 prb_Start_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_TF_ResourceConfig_r12.prb_Start_r12);
       LOG_I(RRC, " SIB18 prb_End_r12: %ld \n", sib18->commConfig_r12->commRxPool_r12.list.array[i]->sc_TF_ResourceConfig_r12.prb_End_r12);
       //to add more log
     }
}

//TTN -  SIB19
//-----------------------------------------------------------------------------
 void dump_sib19(LTE_SystemInformationBlockType19_r12_t *sib19){
   LOG_I( RRC, "[UE] Dumping SIB19\n" );
   for (int i = 0; i < sib19->discConfig_r12->discRxPool_r12.list.count; i++) {
       LOG_I(RRC, " Contents of SIB19 %d/%d \n", i+1, sib19->discConfig_r12->discRxPool_r12.list.count);
       LOG_I(RRC, " SIB19 cp_Len_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->cp_Len_r12);
       LOG_I(RRC, " SIB19 discPeriod_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->discPeriod_r12);
       LOG_I(RRC, " SIB19 numRetx_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->numRetx_r12);
       LOG_I(RRC, " SIB19 numRepetition_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->numRepetition_r12);
       LOG_I(RRC, " SIB19 prb_Num_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->tf_ResourceConfig_r12.prb_Num_r12);
       LOG_I(RRC, " SIB19 prb_Start_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->tf_ResourceConfig_r12.prb_Start_r12);
       LOG_I(RRC, " SIB19 prb_End_r12: %ld \n", sib19->discConfig_r12->discRxPool_r12.list.array[i]->tf_ResourceConfig_r12.prb_End_r12);
       //to add more log
     }
}

 void dump_sib21(LTE_SystemInformationBlockType21_r14_t *sib21){
    if ((sib21->sl_V2X_ConfigCommon_r14 != NULL) && (sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14 !=NULL) ){
       for (int i = 0; i < sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.count; i++) {
          LOG_I(RRC, " Contents of SIB21 %d/%d \n", i+1, sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.count);
          LOG_I(RRC, " SIB21 sl_Subframe_r14: %d \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->sl_Subframe_r14.present);
          LOG_I(RRC, " SIB21 adjacencyPSCCH_PSSCH_r14: %d \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->adjacencyPSCCH_PSSCH_r14);
          LOG_I(RRC, " SIB21 sizeSubchannel_r14: %ld \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->sizeSubchannel_r14);
          LOG_I(RRC, " SIB21 numSubchannel_r14: %ld \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->numSubchannel_r14);
          LOG_I(RRC, " SIB21 startRB_Subchannel_r14: %ld \n", sib21->sl_V2X_ConfigCommon_r14->v2x_CommRxPool_r14->list.array[i]->startRB_Subchannel_r14);
          //to add more log
       }
    }
 }


#endif
//-----------------------------------------------------------------------------
 int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
{
  LTE_SystemInformation_t** si = &UE_rrc_inst[ctxt_pP->module_id].si[eNB_index];
  int new_sib = 0;
  LTE_SystemInformationBlockType1_t* sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index];

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN );

  // Dump contents
  if ((*si)->criticalExtensions.present == LTE_SystemInformation__criticalExtensions_PR_systemInformation_r8 ||
#if (LTE_RRC_VERSION >= MAKE_VERSION(15, 3, 0))
		  (*si)->criticalExtensions.present == LTE_SystemInformation__criticalExtensions_PR_criticalExtensionsFuture_r15) {
#else
		  (*si)->criticalExtensions.present == LTE_SystemInformation__criticalExtensions_PR_criticalExtensionsFuture) {
#endif
    LOG_D( RRC, "[UE] (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count %d\n",
           (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count );
  } else {
    LOG_D( RRC, "[UE] Unknown criticalExtension version (not Rel8)\n" );
    return -1;
  }

  for (int i=0; i<(*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count; i++) {
    struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;
    typeandinfo = (*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];

    switch(typeandinfo->present) {
    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&2) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=2;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index], &typeandinfo->choice.sib2, sizeof(LTE_SystemInformationBlockType2_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB2 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
	dump_sib2( UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index] );
	LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB2 params  eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
	       ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );

	rrc_mac_config_req_ue(ctxt_pP->module_id, 0, eNB_index,
			      &UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->radioResourceConfigCommon,
			      (struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			      (LTE_SCellToAddMod_r10_t *)NULL,
#endif
			      (LTE_MeasObjectToAddMod_t **)NULL,
			      (LTE_MAC_MainConfig_t *)NULL,
			      0,
			      (struct LTE_LogicalChannelConfig *)NULL,
			      (LTE_MeasGapConfig_t *)NULL,
			      (LTE_TDD_Config_t *)NULL,
			      (LTE_MobilityControlInfo_t *)NULL,
			      NULL,
			      NULL,
			      UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.ul_CarrierFreq,
			      UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.ul_Bandwidth,
			      &UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.additionalSpectrumEmission,
			      UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->mbsfn_SubframeConfigList
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
			      ,0,
			      (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
			      (LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
			      ,0,
			      0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			      );
	// After SI is received, prepare RRCConnectionRequest
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))

	if (UE_rrc_inst[ctxt_pP->module_id].MBMS_flag < 3) // see -Q option
#endif
#if !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME))
	  rrc_ue_generate_RRCConnectionRequest( ctxt_pP, eNB_index );

#endif

	if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_IDLE) {
	  LOG_I( RRC, "[UE %d] Received SIB1/SIB2/SIB3 Switching to RRC_SI_RECEIVED\n", ctxt_pP->module_id );
	  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State = RRC_SI_RECEIVED;
#if ENABLE_RAL
	  {
	    MessageDef                            *message_ral_p = NULL;
	    rrc_ral_system_information_ind_t       ral_si_ind;

	    message_ral_p = itti_alloc_new_message (TASK_RRC_UE, RRC_RAL_SYSTEM_INFORMATION_IND);
	    memset(&ral_si_ind, 0, sizeof(rrc_ral_system_information_ind_t));
	    ral_si_ind.plmn_id.MCCdigit2 = '0';
	    ral_si_ind.plmn_id.MCCdigit1 = '2';
	    ral_si_ind.plmn_id.MNCdigit3 = '0';
	    ral_si_ind.plmn_id.MCCdigit3 = '8';
	    ral_si_ind.plmn_id.MNCdigit2 = '9';
	    ral_si_ind.plmn_id.MNCdigit1 = '9';
	    ral_si_ind.cell_id        = 1;
	    ral_si_ind.dbm            = 0;
	    //ral_si_ind.dbm            = fifo_dump_emos_UE.PHY_measurements->rx_rssi_dBm[eNB_index];
	    // TO DO
	    ral_si_ind.sinr           = 0;
	    //ral_si_ind.sinr           = fifo_dump_emos_UE.PHY_measurements->subband_cqi_dB[eNB_index][phy_vars_ue->lte_frame_parms.nb_antennas_rx][0];
	    // TO DO
	    ral_si_ind.link_data_rate = 0;
	    memcpy (&message_ral_p->ittiMsg, (void *) &ral_si_ind, sizeof(rrc_ral_system_information_ind_t));
#warning "ue_mod_idP ? for instance ?"
	    itti_send_msg_to_task (TASK_RAL_UE, UE_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), message_ral_p);
	  }
#endif
	}
      }
      break; // case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&4) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=4;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib3[eNB_index], &typeandinfo->choice.sib3, sizeof(LTE_SystemInformationBlockType3_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB3 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
	dump_sib3( UE_rrc_inst[ctxt_pP->module_id].sib3[eNB_index] );

      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&8) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=8;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib4[eNB_index], &typeandinfo->choice.sib4, sizeof(LTE_SystemInformationBlockType4_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB4 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }

      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&16) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=16;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib5[eNB_index], &typeandinfo->choice.sib5, sizeof(LTE_SystemInformationBlockType5_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB5 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
	dump_sib5(UE_rrc_inst[ctxt_pP->module_id].sib5[eNB_index]);
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&32) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=32;
	new_sib=1;

	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib6[eNB_index], &typeandinfo->choice.sib6, sizeof(LTE_SystemInformationBlockType6_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB6 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&64) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=64;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib7[eNB_index], &typeandinfo->choice.sib7, sizeof(LTE_SystemInformationBlockType7_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB7 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&128) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=128;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib8[eNB_index], &typeandinfo->choice.sib8, sizeof(LTE_SystemInformationBlockType8_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB8 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&256) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=256;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib9[eNB_index], &typeandinfo->choice.sib9, sizeof(LTE_SystemInformationBlockType9_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB9 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&512) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=512;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib10[eNB_index], &typeandinfo->choice.sib10, sizeof(LTE_SystemInformationBlockType10_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB10 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&1024) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=1024;
	new_sib=1;

	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib11[eNB_index], &typeandinfo->choice.sib11, sizeof(LTE_SystemInformationBlockType11_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB11 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 2, 0))

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&2048) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=2048;
	new_sib=1;
	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib12[eNB_index], &typeandinfo->choice.sib12_v920, sizeof(LTE_SystemInformationBlockType12_r9_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB12 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
      }
      break;

    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920:
      if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&4096) == 0) {
	UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=4096;
	new_sib=1;

	memcpy( UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index], &typeandinfo->choice.sib13_v920, sizeof(LTE_SystemInformationBlockType13_r9_t) );
	LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB13 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
	dump_sib13( UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index] );
	// adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer
	LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
	       ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
	rrc_mac_config_req_ue(ctxt_pP->module_id,0,eNB_index,
			      (LTE_RadioResourceConfigCommonSIB_t *)NULL,
			      (struct LTE_PhysicalConfigDedicated *)NULL,
			      (LTE_SCellToAddMod_r10_t *)NULL,
			      (LTE_MeasObjectToAddMod_t **)NULL,
			      (LTE_MAC_MainConfig_t *)NULL,
			      0,
			      (struct LTE_LogicalChannelConfig *)NULL,
			      (LTE_MeasGapConfig_t *)NULL,
			      (LTE_TDD_Config_t *)NULL,
			      (LTE_MobilityControlInfo_t *)NULL,
			      NULL,
			      NULL,
			      NULL,
			      NULL,
			      NULL,
			      (LTE_MBSFN_SubframeConfigList_t *)NULL,
			      0,
			      &UE_rrc_inst[ctxt_pP->module_id].sib13[eNB_index]->mbsfn_AreaInfoList_r9,
			      (LTE_PMCH_InfoList_r9_t *)NULL
#ifdef CBA
			      ,0,
			      0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			      );
	break;
      }
#endif

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
      //SIB18
    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib18_v1250:
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&8192) == 0) {
          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=8192;
          new_sib=1;

          memcpy( UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index], &typeandinfo->choice.sib18_v1250, sizeof(LTE_SystemInformationBlockType18_r12_t) );
          LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB18 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
          dump_sib18( UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index] );
          // adding here function to store necessary parameters to transfer to PHY layer
          LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB18 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);

          //process SIB18 to transfer SL-related parameters to PHY
          rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
                UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index],
                (LTE_SystemInformationBlockType19_r12_t *)NULL,
                (LTE_SL_CommConfig_r12_t *)NULL,
                (LTE_SL_DiscConfig_r12_t *)NULL
          );

       }
       break;

       //SIB19
    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib19_v1250:
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&16384) == 0) {
          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=16384;
          new_sib=1;

          memcpy( UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index], &typeandinfo->choice.sib19_v1250, sizeof(LTE_SystemInformationBlockType19_r12_t) );
          LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB19 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
          dump_sib19( UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index] );
          // adding here function to store necessary parameters to transfer to PHY layer
          LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB19 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
          //process SIB19 to transfer SL-related parameters to PHY
          rrc_ue_process_sidelink_radioResourceConfig(ctxt_pP->module_id,eNB_index,
                (LTE_SystemInformationBlockType18_r12_t *)NULL,
                UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index],
                (LTE_SL_CommConfig_r12_t *)NULL,
                (LTE_SL_DiscConfig_r12_t *)NULL
          );

       }
       break;

       //SIB21
    case LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib21_v1430:
       if ((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&32768) == 0) {
          UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus|=32768;
          new_sib=1;

          memcpy( UE_rrc_inst[ctxt_pP->module_id].sib21[eNB_index], &typeandinfo->choice.sib21_v1430, sizeof(LTE_SystemInformationBlockType21_r14_t) );
          LOG_I( RRC, "[UE %"PRIu8"] Frame %"PRIu32" Found SIB21 from eNB %"PRIu8"\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index );
          dump_sib21( UE_rrc_inst[ctxt_pP->module_id].sib21[eNB_index] );
          // adding here function to store necessary parameters to transfer to PHY layer
          LOG_I( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB21 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
                ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
          //process SIB21
          //TODO
       }
       break;


#endif
    default:
      break;
    }

  }
  if (new_sib == 1) {
    UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt++;

    if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt == sib1->schedulingInfoList.list.count)
      rrc_set_sub_state( ctxt_pP->module_id, RRC_SUB_STATE_IDLE_SIB_COMPLETE );

    LOG_I(RRC,"SIStatus %x, SIcnt %d/%d\n",
	  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus,
	  UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIcnt,
	  sib1->schedulingInfoList.list.count);
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI  , VCD_FUNCTION_OUT);
  return 0;
}

// layer 3 filtering of RSRP (EUTRA) measurements: 36.331, Sec. 5.5.3.2
//-----------------------------------------------------------------------------
void ue_meas_filtering( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
{
  float a  = UE_rrc_inst[ctxt_pP->module_id].filter_coeff_rsrp; // 'a' in 36.331 Sec. 5.5.3.2
  float a1 = UE_rrc_inst[ctxt_pP->module_id].filter_coeff_rsrq;
  //float rsrp_db, rsrq_db;
  uint8_t    eNB_offset;

  if(UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0] != NULL) { // Only consider 1 serving cell (index: 0)
    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0]->quantityConfigEUTRA != NULL) {
      if(UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRP != NULL) {
        for (eNB_offset = 0; eNB_offset<1+get_n_adj_cells(ctxt_pP->module_id,0); eNB_offset++) {
          UE_rrc_inst[ctxt_pP->module_id].rsrp_db[eNB_offset] = get_RSRP(ctxt_pP->module_id,0,eNB_offset);
	  /*
	  (dB_fixed_times10(get_RSRP(ctxt_pP->module_id,0,eNB_offset))/10.0) -
	  get_rx_total_gain_dB(ctxt_pP->module_id,0) -
	  get_bw_gain_dB(ctxt_pP->module_id);
	  */
          UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_offset] =
            (1.0-a)*UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_offset] +
            a*UE_rrc_inst[ctxt_pP->module_id].rsrp_db[eNB_offset];

          LOG_D(RRC,"RSRP_dBm: %3.2f \n",get_RSRP(ctxt_pP->module_id,0,eNB_offset));;
	  /*          LOG_D(RRC,"gain_loss_dB: %d \n",get_rx_total_gain_dB(ctxt_pP->module_id,0));
		      LOG_D(RRC,"gain_fixed_dB: %d \n",dB_fixed(frame_parms->N_RB_DL*12));*/
          LOG_D(PHY,"[UE %d] Frame %d, RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB)\n",
                ctxt_pP->module_id,
                ctxt_pP->frame,
                10*log10(get_RSSI(ctxt_pP->module_id,0))-get_rx_total_gain_dB(ctxt_pP->module_id,0),
                10*log10(get_RSSI(ctxt_pP->module_id,0)));
          LOG_D(RRC,"[UE %d] Frame %d: Meas RSRP: eNB_offset: %d rsrp_coef: %3.1f filter_coef: %ld before L3 filtering: rsrp: %3.1f after L3 filtering: rsrp: %3.1f \n ",
                ctxt_pP->module_id,
                ctxt_pP->frame, eNB_offset,a,
                *UE_rrc_inst->QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRP,
                UE_rrc_inst[ctxt_pP->module_id].rsrp_db[eNB_offset],
                UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_offset]);
        }
      }
    } else {
      for (eNB_offset = 0; eNB_offset<1+get_n_adj_cells(ctxt_pP->module_id,0); eNB_offset++) {
        UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_offset]= get_RSRP(ctxt_pP->module_id,0,eNB_offset);
      }
    }

    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0]->quantityConfigEUTRA != NULL) {
      if(UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRQ != NULL) {
        for (eNB_offset = 0; eNB_offset<1+get_n_adj_cells(ctxt_pP->module_id,0); eNB_offset++) {
          UE_rrc_inst[ctxt_pP->module_id].rsrq_db[eNB_offset] = (10*log10(get_RSRQ(ctxt_pP->module_id,0,eNB_offset)))-20;
          UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[eNB_offset]=(1-a1)*UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[eNB_offset] +
              a1 *UE_rrc_inst[ctxt_pP->module_id].rsrq_db[eNB_offset];
        }
      }
    } else {
      for (eNB_offset = 0; eNB_offset<1+get_n_adj_cells(ctxt_pP->module_id,0); eNB_offset++) {
        UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[eNB_offset]= get_RSRQ(ctxt_pP->module_id,0,eNB_offset);
      }
    }
  }
}

//Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5
//-----------------------------------------------------------------------------
 void rrc_ue_generate_MeasurementReport(protocol_ctxt_t* const ctxt_pP, uint8_t eNB_index )
{

  uint8_t             buffer[32], size;
  uint8_t             i;
  uint8_t             target_eNB_offset;
  LTE_MeasId_t        measId;
  LTE_PhysCellId_t    targetCellId;
  long             rsrp_t,rsrq_t;
  long             rsrp_s,rsrq_s;
  long             nElem, nElem1;
  float            rsrp_filtered, rsrq_filtered;
  static frame_t   pframe=0;
  int              result;

  nElem = 98;
  nElem1 = 35;
  target_eNB_offset = UE_rrc_inst[ctxt_pP->module_id].Info[0].handoverTarget; // eNB_offset of target eNB: used to obtain the mod_id of target eNB

  for (i=0; i<MAX_MEAS_ID; i++) {
    if (UE_rrc_inst[ctxt_pP->module_id].measReportList[0][i] != NULL) {
      measId = UE_rrc_inst[ctxt_pP->module_id].measReportList[0][i]->measId;

      // Note: Values in the meas report have to be the mapped values...to implement binary search for LUT
      rsrp_filtered = UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[eNB_index];//nid_cell];
      rsrp_s = binary_search_float(RSRP_meas_mapping,nElem, rsrp_filtered);

      rsrq_filtered = UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[eNB_index];//nid_cell]; //RSRQ of serving cell
      rsrq_s = binary_search_float(RSRQ_meas_mapping,nElem1,rsrq_filtered);//mapped RSRQ of serving cell

      LOG_D(RRC,"[UE %d] Frame %d: source eNB %d :rsrp_s: %ld rsrq_s: %ld rsrp_filtered: %f rsrq_filtered: %f \n",
            ctxt_pP->module_id,
            ctxt_pP->frame,
            eNB_index,
            rsrp_s,
            rsrq_s,
            rsrp_filtered,
            rsrq_filtered);
      rsrp_t = binary_search_float(RSRP_meas_mapping,nElem,UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[target_eNB_offset]); //RSRP of target cell
      rsrq_t = binary_search_float(RSRQ_meas_mapping,nElem1,UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[target_eNB_offset]); //RSRQ of target cell

      LOG_D(RRC,"[UE %d] Frame %d: target eNB %d :rsrp_t: %ld rsrq_t: %ld rsrp_filtered: %f rsrq_filtered: %f \n",
            ctxt_pP->module_id,
            ctxt_pP->frame,
            target_eNB_offset,
            rsrp_t,
            rsrq_t,
            UE_rrc_inst[ctxt_pP->module_id].rsrp_db_filtered[target_eNB_offset],
            UE_rrc_inst[ctxt_pP->module_id].rsrq_db_filtered[target_eNB_offset]);

      //  if (measFlag == 1) {
      targetCellId = UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId ;//get_adjacent_cell_id(ue_mod_idP,target_eNB_offset); //PhycellId of target cell

      if (pframe!=ctxt_pP->frame) {
        pframe=ctxt_pP->frame;
        LOG_D(RRC, "[UE %d] Frame %ld: doing MeasReport: servingCell(%ld) targetCell(%ld) rsrp_s(%ld) rsrq_s(%ld) rsrp_t(%ld) rsrq_t(%ld) \n",
              ctxt_pP->module_id,
              (long int)ctxt_pP->frame,
              (long int)get_adjacent_cell_id(ctxt_pP->module_id, eNB_index),
              (long int)targetCellId,
              (long int)rsrp_s,
              (long int)rsrq_s,
              (long int)rsrp_t,
              (long int)rsrq_t);
        size = do_MeasurementReport(ctxt_pP->module_id, buffer,measId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
        LOG_I(RRC, "[UE %d] Frame %d : Generating Measurement Report for eNB %d\n",
              ctxt_pP->module_id, ctxt_pP->frame, eNB_index);
        result = pdcp_data_req(ctxt_pP,  SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
                               ,NULL, NULL
#endif
                               );
        AssertFatal (result == TRUE, "PDCP data request failed!\n");
        //LOG_D(RRC, "[UE %d] Frame %d Sending MeasReport (%d bytes) through DCCH%d to PDCP \n",ue_mod_idP,frameP, size, DCCH);
      }

      //          measFlag = 0; //re-setting measFlag so that no more MeasReports are sent in this frameP
      //          }
    }
  }
}

// Measurement report triggering, described in 36.331 Section 5.5.4.1: called periodically
//-----------------------------------------------------------------------------
void ue_measurement_report_triggering(protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index )
{
  uint8_t               i,j;
  LTE_Hysteresis_t     hys;
  LTE_TimeToTrigger_t  ttt_ms;
  LTE_Q_OffsetRange_t  ofn;
  LTE_Q_OffsetRange_t  ocn;
  LTE_Q_OffsetRange_t  ofs = 0;
  LTE_Q_OffsetRange_t  ocs = 0;
  long             a3_offset;
  LTE_MeasObjectId_t   measObjId;
  LTE_ReportConfigId_t reportConfigId;

  for(i=0 ; i<NB_CNX_UE ; i++) {
    for(j=0 ; j<MAX_MEAS_ID ; j++) {
      if(UE_rrc_inst[ctxt_pP->module_id].MeasId[i][j] != NULL) {
        measObjId = UE_rrc_inst[ctxt_pP->module_id].MeasId[i][j]->measObjectId;
        reportConfigId = UE_rrc_inst[ctxt_pP->module_id].MeasId[i][j]->reportConfigId;

        if( /*UE_rrc_inst[ctxt_pP->module_id].MeasId[i][j] != NULL && */ UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1] != NULL) {
          if(UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1]->measObject.present == LTE_MeasObjectToAddMod__measObject_PR_measObjectEUTRA) {
            /* consider any neighboring cell detected on the associated frequency to be
             * applicable when the concerned cell is not included in the blackCellsToAddModList
             * defined within the VarMeasConfig for this measId */
            //    LOG_I(RRC,"event %d %d %p \n", measObjId,reportConfigId, UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId-1]);
            if((UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId-1] != NULL) &&
                (UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId-1]->reportConfig.present == LTE_ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA) &&
                (UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.present ==
                 LTE_ReportConfigEUTRA__triggerType_PR_event)) {
              hys = UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis;
              ttt_ms = timeToTrigger_ms[UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId
                                        -1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger];
              // Freq specific offset of neighbor cell freq
              ofn = 5;//((UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1]->measObject.choice.measObjectEUTRA.offsetFreq != NULL) ?
              // *UE_rrc_inst[ctxt_pP->module_id].MeasObj[i][measObjId-1]->measObject.choice.measObjectEUTRA.offsetFreq : 15); //  /* 15 is the Default */
              // cellIndividualOffset of neighbor cell - not defined yet
              ocn = 0;
              a3_offset = UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId
                          -1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset;

              switch (UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present) {
              case LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1:
                LOG_D(RRC,"[UE %d] Frame %d : A1 event: check if serving becomes better than threshold\n",
                      ctxt_pP->module_id, ctxt_pP->frame);
                break;

              case LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2:
                LOG_D(RRC,"[UE %d] Frame %d : A2 event, check if serving becomes worse than a threshold\n",
                      ctxt_pP->module_id, ctxt_pP->frame);
                break;

              case LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3:
                LOG_D(RRC,"[UE %d] Frame %d : A3 event: check if a neighboring cell becomes offset better than serving to trigger a measurement event \n",
                      ctxt_pP->module_id, ctxt_pP->frame);

                if ((check_trigger_meas_event(
                       ctxt_pP->module_id,
                       ctxt_pP->frame,
                       eNB_index,
                       i,j,ofn,ocn,hys,ofs,ocs,a3_offset,ttt_ms)) &&
                    (UE_rrc_inst[ctxt_pP->module_id].Info[0].State >= RRC_CONNECTED) &&
                    (UE_rrc_inst[ctxt_pP->module_id].Info[0].T304_active == 0 )      &&
                    (UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag == 1)) {
                  //trigger measurement reporting procedure (36.331, section 5.5.5)
                  if (UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j] == NULL) {
                    UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j] = malloc(sizeof(MEAS_REPORT_LIST));
                  }

                  UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j]->measId = UE_rrc_inst[ctxt_pP->module_id].MeasId[i][j]->measId;
                  UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j]->numberOfReportsSent = 0;
                  rrc_ue_generate_MeasurementReport(
                    ctxt_pP,
                    eNB_index);
                  UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
                  LOG_I(RRC,"[UE %d] Frame %d: A3 event detected, state: %d \n",
                        ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[0].State);
                } else {
                  if(UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j] != NULL) {
                    free(UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j]);
                  }

                  UE_rrc_inst[ctxt_pP->module_id].measReportList[i][j] = NULL;
                }

                break;

              case LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA4:
                LOG_D(RRC,"[UE %d] Frame %d : received an A4 event, neighbor becomes offset better than a threshold\n",
                      ctxt_pP->module_id, ctxt_pP->frame);
                break;

              case LTE_ReportConfigEUTRA__triggerType__event__eventId_PR_eventA5:
                LOG_D(RRC,"[UE %d] Frame %d: received an A5 event, serving becomes worse than threshold 1 and neighbor becomes better than threshold 2\n",
                      ctxt_pP->module_id, ctxt_pP->frame);
                break;

              default:
                LOG_D(RRC,"Invalid ReportConfigEUTRA__triggerType__event__eventId: %d",
                      UE_rrc_inst[ctxt_pP->module_id].ReportConfig[i][j]->reportConfig.choice.reportConfigEUTRA.triggerType.present);
                break;
              }
            }
          }
        }
      }
    }
  }
}

//check_trigger_meas_event(ue_mod_idP, frameP, eNB_index, i,j,ofn,ocn,hys,ofs,ocs,a3_offset,ttt_ms)
//-----------------------------------------------------------------------------

 uint8_t check_trigger_meas_event(
  module_id_t     ue_mod_idP,
  frame_t         frameP,
  uint8_t         eNB_index,
  uint8_t         ue_cnx_index,
  uint8_t         meas_index,
  LTE_Q_OffsetRange_t ofn,
  LTE_Q_OffsetRange_t ocn,
  LTE_Hysteresis_t    hys,
  LTE_Q_OffsetRange_t ofs,
  LTE_Q_OffsetRange_t ocs,
  long            a3_offset,
  LTE_TimeToTrigger_t ttt )
{
  uint8_t eNB_offset;
  //  uint8_t currentCellIndex = frame_parms->Nid_cell;
  uint8_t tmp_offset;

  LOG_I(RRC,"[UE %d] ofn(%ld) ocn(%ld) hys(%ld) ofs(%ld) ocs(%ld) a3_offset(%ld) ttt(%ld) rssi %3.1f\n",
        ue_mod_idP,
        ofn,ocn,hys,ofs,ocs,a3_offset,ttt,
        10*log10(get_RSSI(ue_mod_idP,0))-get_rx_total_gain_dB(ue_mod_idP,0));

  for (eNB_offset = 0; eNB_offset<1+get_n_adj_cells(ue_mod_idP,0); eNB_offset++) {
    /* RHS: Verify that idx 0 corresponds to currentCellIndex in rsrp array */
    if((eNB_offset!=eNB_index)&&(eNB_offset<NB_eNB_INST)) {
      if(eNB_offset<eNB_index) {
        tmp_offset = eNB_offset;
      } else {
        tmp_offset = eNB_offset-1;
      }

      if(UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset]+ofn+ocn-hys > UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_index]+ofs+ocs-1/*+a3_offset*/) {
        UE_rrc_inst->measTimer[ue_cnx_index][meas_index][tmp_offset] += 2; //Called every subframe = 2ms
        LOG_D(RRC,"[UE %d] Frame %d: Entry measTimer[%d][%d][%d]: %d currentCell: %d betterCell: %d \n",
              ue_mod_idP, frameP, ue_cnx_index,meas_index,tmp_offset,UE_rrc_inst->measTimer[ue_cnx_index][meas_index][tmp_offset],0,eNB_offset);
      } else {
        UE_rrc_inst->measTimer[ue_cnx_index][meas_index][tmp_offset] = 0; //Exit condition: Resetting the measurement timer
        LOG_D(RRC,"[UE %d] Frame %d: Exit measTimer[%d][%d][%d]: %d currentCell: %d betterCell: %d \n",
              ue_mod_idP, frameP, ue_cnx_index,meas_index,tmp_offset,UE_rrc_inst->measTimer[ue_cnx_index][meas_index][tmp_offset],0,eNB_offset);
      }

      if (UE_rrc_inst->measTimer[ue_cnx_index][meas_index][tmp_offset] >= ttt) {
        UE_rrc_inst->HandoverInfoUe.targetCellId = get_adjacent_cell_id(ue_mod_idP,tmp_offset); //WARNING!!!...check this!
        LOG_D(RRC,"[UE %d] Frame %d eNB %d: Handover triggered: targetCellId: %ld currentCellId: %d eNB_offset: %d rsrp source: %3.1f rsrp target: %3.1f\n",
              ue_mod_idP, frameP, eNB_index,
              UE_rrc_inst->HandoverInfoUe.targetCellId,ue_cnx_index,eNB_offset,
	      get_RSRP(ue_mod_idP,0,0),
	      get_RSRP(ue_mod_idP,0,1));
        UE_rrc_inst->Info[0].handoverTarget = eNB_offset;
        //LOG_D(RRC,"PHY_ID: %d \n",UE_rrc_inst->HandoverInfoUe.targetCellId);
        return 1;
      }

      // else{
      //  LOG_D(RRC,"Condition does not hold\n");
      // }
    }
  }

  return 0;
}

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
//-----------------------------------------------------------------------------
int decode_MCCH_Message( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, const uint8_t* const Sdu, const uint8_t Sdu_len, const uint8_t mbsfn_sync_area )
{

  LTE_MCCH_Message_t               *mcch=NULL;
  LTE_MBSFNAreaConfiguration_r9_t** mcch_message=&UE_rrc_inst[ctxt_pP->module_id].mcch_message[eNB_index];

  asn_dec_rval_t                dec_rval;

  if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].MCCHStatus[mbsfn_sync_area] == 1) {
    LOG_D(RRC,"[UE %d] Frame %d: MCCH MESSAGE for MBSFN sync area %d has been already received!\n",
          ctxt_pP->module_id,
          ctxt_pP->frame,
          mbsfn_sync_area);
    return 0; // avoid decoding to prevent memory bloating
  } else {
    dec_rval = uper_decode_complete(NULL,
                                    &asn_DEF_LTE_MCCH_Message,
                                    (void **)&mcch,
                                    (const void *)Sdu,
                                    Sdu_len);

    if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) {
      LOG_E(RRC,"[UE %d] Failed to decode MCCH__MESSAGE (%lu bits)\n",
            ctxt_pP->module_id,
            dec_rval.consumed);
      //free the memory
      SEQUENCE_free(&asn_DEF_LTE_MCCH_Message, (void*)mcch, 1);
      return -1;
    }

    if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
      xer_fprint(stdout, &asn_DEF_LTE_MCCH_Message, (void*)mcch);
    }

    if (mcch->message.present == LTE_MCCH_MessageType_PR_c1) {
      LOG_D(RRC,"[UE %d] Found mcch message \n",
            ctxt_pP->module_id);

      if(mcch->message.choice.c1.present == LTE_MCCH_MessageType__c1_PR_mbsfnAreaConfiguration_r9) {
        /*
        memcpy((void*)*mcch_message,
         (void*)&mcch->message.choice.c1.choice.mbsfnAreaConfiguration_r9,
         sizeof(MBSFNAreaConfiguration_r9_t)); */
        *mcch_message = &mcch->message.choice.c1.choice.mbsfnAreaConfiguration_r9;
        LOG_I(RRC,"[UE %d] Frame %d : Found MBSFNAreaConfiguration from eNB %d \n",
              ctxt_pP->module_id,
              ctxt_pP->frame,
              eNB_index);
        decode_MBSFNAreaConfiguration(
          ctxt_pP->module_id,
          eNB_index,
          ctxt_pP->frame,
          mbsfn_sync_area);

      }
    }
  }

  return 0;
}

//-----------------------------------------------------------------------------
 void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_index, frame_t frameP, uint8_t mbsfn_sync_area )
{
  uint8_t i;
  protocol_ctxt_t               ctxt;

  LOG_I(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d  is %d\n",
        ue_mod_idP, frameP, mbsfn_sync_area, UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9.list.count);

  // Configure commonSF_Alloc 
  for(i=0; i< UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.count;i++){
    LOG_W(RRC,"[UE %d] Frame %d, commonSF_Alloc_r9: radioframeAllocationPeriod(%ldn),radioframeAllocationOffset(%ld), subframeAllocation(%x,%x,%x)\n",
          ue_mod_idP, frameP,
          UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->radioframeAllocationPeriod<<1,
          UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->radioframeAllocationOffset,
          UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->subframeAllocation.choice.oneFrame.buf[0],
          UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->subframeAllocation.choice.oneFrame.buf[1],
          UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i]->subframeAllocation.choice.oneFrame.buf[2]);
    UE_mac_inst[ue_mod_idP].commonSF_Alloc_r9_mbsfn_SubframeConfig[i] = UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_Alloc_r9.list.array[i];
  }
  LOG_W(RRC,"[UE %d] Frame %d, commonSF_AllocPeriod_r9 %drf \n",
        ue_mod_idP, frameP,
        4<<UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_AllocPeriod_r9);

  // Configure commonSF_AllocPeriod
  UE_mac_inst[ue_mod_idP].commonSF_AllocPeriod_r9 = UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->commonSF_AllocPeriod_r9;

  //  store to MAC/PHY necessary parameters for receiving MTCHs

  rrc_mac_config_req_ue(ue_mod_idP,0,eNB_index,
			(LTE_RadioResourceConfigCommonSIB_t *)NULL,
			(struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
			(LTE_SCellToAddMod_r10_t *)NULL,
			//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
			(LTE_MeasObjectToAddMod_t **)NULL,
			(LTE_MAC_MainConfig_t *)NULL,
			0,
			(struct LTE_LogicalChannelConfig *)NULL,
			(LTE_MeasGapConfig_t *)NULL,
			(LTE_TDD_Config_t *)NULL,
			(LTE_MobilityControlInfo_t *)NULL,
			NULL,
			NULL,
			NULL,
			NULL,
			NULL,
			(LTE_MBSFN_SubframeConfigList_t *)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
			,
			0,
			(LTE_MBSFN_AreaInfoList_r9_t *)NULL,
			&UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9

#endif
#ifdef CBA
			,
			0,
			0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
           ,
           0,
           NULL,
           NULL
#endif
			);

  UE_rrc_inst[ue_mod_idP].Info[eNB_index].MCCHStatus[mbsfn_sync_area] = 1;

  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_idP, ENB_FLAG_NO, UE_rrc_inst[ue_mod_idP].Info[eNB_index].rnti, frameP, 0,eNB_index);

  // Config Radio Bearer for MBMS user data (similar way to configure for eNB side in init_MBMS function)
  rrc_pdcp_config_asn1_req(&ctxt,
                           NULL, // SRB_ToAddModList
                           NULL, // DRB_ToAddModList
                           (LTE_DRB_ToReleaseList_t*)NULL,
                           0, // security mode
                           NULL, // key rrc encryption
                           NULL, // key rrc integrity
                           NULL // key encryption
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                           ,&(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
#endif
                           ,NULL);

  rrc_rlc_config_asn1_req(&ctxt,
                          NULL,// SRB_ToAddModList
                          NULL,// DRB_ToAddModList
                          NULL,// DRB_ToReleaseList
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                          &(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
                          , 0, 0
#endif
                         );
  // */

}

#endif // rel10

#if defined(ENABLE_ITTI)
//-----------------------------------------------------------------------------
void *rrc_ue_task( void *args_p )
{
  MessageDef   *msg_p;
  instance_t    instance;
  unsigned int  ue_mod_id;
  int           result;
  SRB_INFO     *srb_info_p;

  protocol_ctxt_t  ctxt;
  itti_mark_task_ready (TASK_RRC_UE);

  while(1) {
    // Wait for a message
    itti_receive_msg (TASK_RRC_UE, &msg_p);

    instance = ITTI_MSG_INSTANCE (msg_p);
    ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance);

    switch (ITTI_MSG_ID(msg_p)) {
    case TERMINATE_MESSAGE:
      LOG_W(RRC, " *** Exiting RRC thread\n");
      itti_exit_task ();
      break;

    case MESSAGE_TEST:
      LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
      break;

      /* MAC messages */
    case RRC_MAC_IN_SYNC_IND:
      LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
            RRC_MAC_IN_SYNC_IND (msg_p).frame, RRC_MAC_IN_SYNC_IND (msg_p).enb_index);

      UE_rrc_inst[ue_mod_id].Info[RRC_MAC_IN_SYNC_IND (msg_p).enb_index].N310_cnt = 0;

      if (UE_rrc_inst[ue_mod_id].Info[RRC_MAC_IN_SYNC_IND (msg_p).enb_index].T310_active == 1) {
        UE_rrc_inst[ue_mod_id].Info[RRC_MAC_IN_SYNC_IND (msg_p).enb_index].N311_cnt++;
      }

      break;

    case RRC_MAC_OUT_OF_SYNC_IND:
      LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
            RRC_MAC_OUT_OF_SYNC_IND (msg_p).frame, RRC_MAC_OUT_OF_SYNC_IND (msg_p).enb_index);

      UE_rrc_inst[ue_mod_id].Info[RRC_MAC_OUT_OF_SYNC_IND (msg_p).enb_index].N310_cnt ++;
      break;

    case RRC_MAC_BCCH_DATA_IND:
      LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
            RRC_MAC_BCCH_DATA_IND (msg_p).frame, RRC_MAC_BCCH_DATA_IND (msg_p).enb_index);

      //      PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, NOT_A_RNTI, RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0);
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, NOT_A_RNTI, RRC_MAC_BCCH_DATA_IND (msg_p).frame, 0,RRC_MAC_BCCH_DATA_IND (msg_p).enb_index);
      decode_BCCH_DLSCH_Message (&ctxt,
                                 RRC_MAC_BCCH_DATA_IND (msg_p).enb_index,
                                 RRC_MAC_BCCH_DATA_IND (msg_p).sdu,
                                 RRC_MAC_BCCH_DATA_IND (msg_p).sdu_size,
                                 RRC_MAC_BCCH_DATA_IND (msg_p).rsrq,
                                 RRC_MAC_BCCH_DATA_IND (msg_p).rsrp);
      break;

    case RRC_MAC_CCCH_DATA_CNF:
      LOG_D(RRC, "[UE %d] Received %s: eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
            RRC_MAC_CCCH_DATA_CNF (msg_p).enb_index);

      // reset the tx buffer to indicate RRC that ccch was successfully transmitted (for example if contention resolution succeeds)
      UE_rrc_inst[ue_mod_id].Srb0[RRC_MAC_CCCH_DATA_CNF (msg_p).enb_index].Tx_buffer.payload_size = 0;
      break;

    case RRC_MAC_CCCH_DATA_IND:
      LOG_D(RRC, "[UE %d] RNTI %x Received %s: frameP %d, eNB %d\n",
            ue_mod_id,
            RRC_MAC_CCCH_DATA_IND (msg_p).rnti,
            ITTI_MSG_NAME (msg_p),
            RRC_MAC_CCCH_DATA_IND (msg_p).frame,
            RRC_MAC_CCCH_DATA_IND (msg_p).enb_index);

      srb_info_p = &UE_rrc_inst[ue_mod_id].Srb0[RRC_MAC_CCCH_DATA_IND (msg_p).enb_index];

      memcpy (srb_info_p->Rx_buffer.Payload, RRC_MAC_CCCH_DATA_IND (msg_p).sdu,
              RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size);
      srb_info_p->Rx_buffer.payload_size = RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size;
      //      PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, RRC_MAC_CCCH_DATA_IND (msg_p).rnti, RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0);
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, RRC_MAC_CCCH_DATA_IND (msg_p).rnti, RRC_MAC_CCCH_DATA_IND (msg_p).frame, 0, RRC_MAC_CCCH_DATA_IND (msg_p).enb_index);
      rrc_ue_decode_ccch (&ctxt,
                          srb_info_p,
                          RRC_MAC_CCCH_DATA_IND (msg_p).enb_index);
      break;

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))

    case RRC_MAC_MCCH_DATA_IND:
      LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d, mbsfn SA %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
            RRC_MAC_MCCH_DATA_IND (msg_p).frame, RRC_MAC_MCCH_DATA_IND (msg_p).enb_index, RRC_MAC_MCCH_DATA_IND (msg_p).mbsfn_sync_area);

      //PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, M_RNTI, RRC_MAC_MCCH_DATA_IND (msg_p).frame, 0);
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, M_RNTI, RRC_MAC_MCCH_DATA_IND (msg_p).frame, 0,RRC_MAC_MCCH_DATA_IND (msg_p).enb_index);
      decode_MCCH_Message (
        &ctxt,
        RRC_MAC_MCCH_DATA_IND (msg_p).enb_index,
        RRC_MAC_MCCH_DATA_IND (msg_p).sdu,
        RRC_MAC_MCCH_DATA_IND (msg_p).sdu_size,
        RRC_MAC_MCCH_DATA_IND (msg_p).mbsfn_sync_area);
      break;

  /*  //TTN (for D2D)
    case RRC_MAC_SL_DISCOVERY_DATA_IND:
       LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
             RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).frame, RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).enb_index);
       PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, M_RNTI, RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).frame, 0,RRC_MAC_SL_DISCOVERY_DATA_IND (msg_p).enb_index);
       //send to ProSeApp
       break;
*/
# endif

      /* PDCP messages */
    case RRC_DCCH_DATA_IND:
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, RRC_DCCH_DATA_IND (msg_p).module_id, ENB_FLAG_NO, RRC_DCCH_DATA_IND (msg_p).rnti, RRC_DCCH_DATA_IND (msg_p).frame, 0,RRC_DCCH_DATA_IND (msg_p).eNB_index);
      LOG_D(RRC, "[UE %d] Received %s: frameP %d, DCCH %d, eNB %d\n",
            RRC_DCCH_DATA_IND (msg_p).module_id,
            ITTI_MSG_NAME (msg_p),
            RRC_DCCH_DATA_IND (msg_p).frame,
            RRC_DCCH_DATA_IND (msg_p).dcch_index,
            RRC_DCCH_DATA_IND (msg_p).eNB_index);

      LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT"Received %s DCCH %d, eNB %d\n",
            PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt),
            ITTI_MSG_NAME (msg_p),
            RRC_DCCH_DATA_IND (msg_p).dcch_index,
            RRC_DCCH_DATA_IND (msg_p).eNB_index);
      rrc_ue_decode_dcch (
        &ctxt,
        RRC_DCCH_DATA_IND (msg_p).dcch_index,
        RRC_DCCH_DATA_IND (msg_p).sdu_p,
        RRC_DCCH_DATA_IND (msg_p).eNB_index);
      // Message buffer has been processed, free it now.
      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_IND (msg_p).sdu_p);
      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      break;

# if defined(ENABLE_USE_MME)

    case NAS_KENB_REFRESH_REQ:
        memcpy((void*)UE_rrc_inst[ue_mod_id].kenb, (void*)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(UE_rrc_inst[ue_mod_id].kenb));

        LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KeNB = "
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x"
            "%02x%02x%02x%02x\n",
            ue_mod_id, ITTI_MSG_NAME (msg_p),
            UE_rrc_inst[ue_mod_id].kenb[0],  UE_rrc_inst[ue_mod_id].kenb[1],  UE_rrc_inst[ue_mod_id].kenb[2],  UE_rrc_inst[ue_mod_id].kenb[3],
            UE_rrc_inst[ue_mod_id].kenb[4],  UE_rrc_inst[ue_mod_id].kenb[5],  UE_rrc_inst[ue_mod_id].kenb[6],  UE_rrc_inst[ue_mod_id].kenb[7],
            UE_rrc_inst[ue_mod_id].kenb[8],  UE_rrc_inst[ue_mod_id].kenb[9],  UE_rrc_inst[ue_mod_id].kenb[10], UE_rrc_inst[ue_mod_id].kenb[11],
            UE_rrc_inst[ue_mod_id].kenb[12], UE_rrc_inst[ue_mod_id].kenb[13], UE_rrc_inst[ue_mod_id].kenb[14], UE_rrc_inst[ue_mod_id].kenb[15],
            UE_rrc_inst[ue_mod_id].kenb[16], UE_rrc_inst[ue_mod_id].kenb[17], UE_rrc_inst[ue_mod_id].kenb[18], UE_rrc_inst[ue_mod_id].kenb[19],
            UE_rrc_inst[ue_mod_id].kenb[20], UE_rrc_inst[ue_mod_id].kenb[21], UE_rrc_inst[ue_mod_id].kenb[22], UE_rrc_inst[ue_mod_id].kenb[23],
            UE_rrc_inst[ue_mod_id].kenb[24], UE_rrc_inst[ue_mod_id].kenb[25], UE_rrc_inst[ue_mod_id].kenb[26], UE_rrc_inst[ue_mod_id].kenb[27],
            UE_rrc_inst[ue_mod_id].kenb[28], UE_rrc_inst[ue_mod_id].kenb[29], UE_rrc_inst[ue_mod_id].kenb[30], UE_rrc_inst[ue_mod_id].kenb[31]);

      break;

      /* NAS messages */
    case NAS_CELL_SELECTION_REQ:

      LOG_D(RRC, "[UE %d] Received %s: state %d, plmnID (%d%d%d.%d%d%d), rat %x\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id),
            NAS_CELL_SELECTION_REQ (msg_p).plmnID.MCCdigit1,
            NAS_CELL_SELECTION_REQ (msg_p).plmnID.MCCdigit2,
            NAS_CELL_SELECTION_REQ (msg_p).plmnID.MCCdigit3,
            NAS_CELL_SELECTION_REQ (msg_p).plmnID.MNCdigit1,
            NAS_CELL_SELECTION_REQ (msg_p).plmnID.MNCdigit2,
            NAS_CELL_SELECTION_REQ (msg_p).plmnID.MNCdigit3,
            NAS_CELL_SELECTION_REQ (msg_p).rat);

      if (rrc_get_state(ue_mod_id) == RRC_STATE_INACTIVE) {
        // have a look at MAC/main.c void dl_phy_sync_success(...)
        openair_rrc_ue_init(ue_mod_id,0);
      }

      /* Save cell selection criterion */
      {
        UE_rrc_inst[ue_mod_id].plmnID = NAS_CELL_SELECTION_REQ (msg_p).plmnID;
        UE_rrc_inst[ue_mod_id].rat = NAS_CELL_SELECTION_REQ (msg_p).rat;
        LOG_D(RRC, "[UE %d] Save cell selection criterion MCC %X%X%X MNC %X%X%X\n",
              ue_mod_id,
              UE_rrc_inst[ue_mod_id].plmnID.MCCdigit1,
              UE_rrc_inst[ue_mod_id].plmnID.MCCdigit2,
              UE_rrc_inst[ue_mod_id].plmnID.MCCdigit3,
              UE_rrc_inst[ue_mod_id].plmnID.MNCdigit1,
              UE_rrc_inst[ue_mod_id].plmnID.MNCdigit2,
              UE_rrc_inst[ue_mod_id].plmnID.MNCdigit3);

      }

      switch (rrc_get_state(ue_mod_id)) {
      case RRC_STATE_INACTIVE: {
        /* Need to first activate lower layers */
        MessageDef *message_p;

        message_p = itti_alloc_new_message(TASK_RRC_UE, ACTIVATE_MESSAGE);

        itti_send_msg_to_task(TASK_L2L1, UE_MODULE_ID_TO_INSTANCE(ue_mod_id), message_p);

        rrc_set_state (ue_mod_id, RRC_STATE_IDLE);
        /* Fall through to next case */
      }

      case RRC_STATE_IDLE: {
        /* Ask to layer 1 to find a cell matching the criterion */
        MessageDef *message_p;

        message_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_CELL_REQ);

        PHY_FIND_CELL_REQ (message_p).earfcn_start = 1;
        PHY_FIND_CELL_REQ (message_p).earfcn_end = 1;

        itti_send_msg_to_task(TASK_PHY_UE, UE_MODULE_ID_TO_INSTANCE(ue_mod_id), message_p);
        rrc_set_sub_state (ue_mod_id, RRC_SUB_STATE_IDLE_SEARCHING);

        break;
      }

      case RRC_STATE_CONNECTED:
        /* should not happen */
        LOG_E(RRC, "[UE %d] request %s in RRC state %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id));
        break;

      default:
        LOG_E(RRC, "[UE %d] Invalid RRC state %d\n", ue_mod_id, rrc_get_state(ue_mod_id));
        break;
      }

      break;

    case NAS_CONN_ESTABLI_REQ:
      LOG_D(RRC, "[UE %d] Received %s: cause %d, type %d, s_tmsi (mme code %"PRIu8", m-tmsi %"PRIu32"), plmnID (%d%d%d.%d%d%d)\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NAS_CONN_ESTABLI_REQ (msg_p).cause,
            NAS_CONN_ESTABLI_REQ (msg_p).type,
            NAS_CONN_ESTABLI_REQ (msg_p).s_tmsi.MMEcode,
            NAS_CONN_ESTABLI_REQ (msg_p).s_tmsi.m_tmsi,
            NAS_CONN_ESTABLI_REQ (msg_p).plmnID.MCCdigit1,
            NAS_CONN_ESTABLI_REQ (msg_p).plmnID.MCCdigit2,
            NAS_CONN_ESTABLI_REQ (msg_p).plmnID.MCCdigit3,
            NAS_CONN_ESTABLI_REQ (msg_p).plmnID.MNCdigit1,
            NAS_CONN_ESTABLI_REQ (msg_p).plmnID.MNCdigit2,
            NAS_CONN_ESTABLI_REQ (msg_p).plmnID.MNCdigit3);

      //PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_NO, NOT_A_RNTI, 0, 0);
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, NOT_A_RNTI, 0, 0, 0);

      UE_rrc_inst[ue_mod_id].initialNasMsg = NAS_CONN_ESTABLI_REQ (msg_p).initialNasMsg;

      switch (rrc_get_state(ue_mod_id)) {
      case RRC_STATE_IDLE: {
        if (rrc_get_sub_state(ue_mod_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE) {
          rrc_ue_generate_RRCConnectionRequest(&ctxt, 0);
          LOG_D(RRC, "not sending connection request\n");

          rrc_set_sub_state (ue_mod_id, RRC_SUB_STATE_IDLE_CONNECTING);
        }

        break;
      }

      case RRC_STATE_INACTIVE:
      case RRC_STATE_CONNECTED:
        /* should not happen */
        LOG_E(RRC, "[UE %d] request %s in RRC state %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id));
        break;

      default:
        LOG_E(RRC, "[UE %d] Invalid RRC state %d\n", ue_mod_id, rrc_get_state(ue_mod_id));
        break;
      }

      break;

    case NAS_UPLINK_DATA_REQ: {
      uint32_t length;
      uint8_t *buffer;

      LOG_D(RRC, "[UE %d] Received %s: UEid %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NAS_UPLINK_DATA_REQ (msg_p).UEid);

      /* Create message for PDCP (ULInformationTransfer_t) */
      length = do_ULInformationTransfer(&buffer, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.length, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.data);

      /* Transfer data to PDCP */
      PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0,0);

      // check if SRB2 is created, if yes request data_req on DCCH1 (SRB2)
      if(UE_rrc_inst[ue_mod_id].SRB2_config[0] == NULL)
      {
          rrc_data_req_ue (&ctxt,
                  DCCH,
                  rrc_mui++,
                  SDU_CONFIRM_NO,
                  length, buffer,
                  PDCP_TRANSMISSION_MODE_CONTROL);
      }
      else
      {
          rrc_data_req_ue (&ctxt,
                  DCCH1,
                  rrc_mui++,
                  SDU_CONFIRM_NO,
                  length, buffer,
                  PDCP_TRANSMISSION_MODE_CONTROL);
      }
      break;
    }

# endif

# if ENABLE_RAL

    case RRC_RAL_SCAN_REQ:
      LOG_D(RRC, "[UE %d] Received %s: state %d\n", ue_mod_id,ITTI_MSG_NAME (msg_p) );

      switch (rrc_get_state(ue_mod_id)) {
      case RRC_STATE_INACTIVE: {
        /* Need to first activate lower layers */
        MessageDef *message_p;

        message_p = itti_alloc_new_message(TASK_RRC_UE, ACTIVATE_MESSAGE);

        itti_send_msg_to_task(TASK_L2L1, instance, message_p);

        rrc_set_state (ue_mod_id, RRC_STATE_IDLE);
        /* Fall through to next case */
      }

      case RRC_STATE_IDLE: {
        if (rrc_get_sub_state(ue_mod_id) != RRC_SUB_STATE_IDLE_SEARCHING) {
          /* Ask to layer 1 to find a cell matching the criterion */
          MessageDef *message_p;

          message_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_CELL_REQ);

          rrc_set_sub_state (ue_mod_id, RRC_SUB_STATE_IDLE_SEARCHING);

          PHY_FIND_CELL_REQ (message_p).transaction_id = RRC_RAL_SCAN_REQ (msg_p).transaction_id;
          PHY_FIND_CELL_REQ (message_p).earfcn_start   = 1;
          PHY_FIND_CELL_REQ (message_p).earfcn_end     = 1; //44

          itti_send_msg_to_task(TASK_PHY_UE, instance, message_p);
        }

        break;
      }

      case RRC_STATE_CONNECTED:
        /* should not happen */
        LOG_E(RRC, "[UE %d] request %s in RRC state %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id));
        break;

      default:
        LOG_E(RRC, "[UE %d] Invalid RRC state %d\n", ue_mod_id, rrc_get_state(ue_mod_id));
        break;
      }

      break;

    case PHY_FIND_CELL_IND:
      LOG_D(RRC, "[UE %d] Received %s: state %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id));

      switch (rrc_get_state(ue_mod_id)) {
      case RRC_STATE_IDLE:
        switch (rrc_get_sub_state(ue_mod_id)) {
        case RRC_SUB_STATE_IDLE_SEARCHING: {
          MessageDef *message_p;
          int         i;

          message_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_SCAN_CONF);

          RRC_RAL_SCAN_CONF (message_p).transaction_id = PHY_FIND_CELL_IND(msg_p).transaction_id;
          RRC_RAL_SCAN_CONF (message_p).num_scan_resp  = PHY_FIND_CELL_IND(msg_p).cell_nb;

          for (i = 0 ; i < PHY_FIND_CELL_IND(msg_p).cell_nb; i++) {
            // TO DO
            memset(&RRC_RAL_SCAN_CONF (message_p).link_scan_resp[i].link_addr,  0, sizeof(ral_link_addr_t));
            // TO DO
            memset(&RRC_RAL_SCAN_CONF (message_p).link_scan_resp[i].network_id, 0, sizeof(ral_network_id_t));

            RRC_RAL_SCAN_CONF (message_p).link_scan_resp[i].sig_strength.choice     = RAL_SIG_STRENGTH_CHOICE_DBM;
            RRC_RAL_SCAN_CONF (message_p).link_scan_resp[i].sig_strength._union.dbm = PHY_FIND_CELL_IND(msg_p).cells[i].rsrp;
          }

          rrc_set_sub_state (ue_mod_id, RRC_SUB_STATE_IDLE);

          itti_send_msg_to_task(TASK_RAL_UE, instance, message_p);
          break;
        }

        default:
          LOG_E(RRC, "[UE %d] Invalid RRC state %d substate %d\n",
                ue_mod_id,
                rrc_get_state(ue_mod_id),
                rrc_get_sub_state(ue_mod_id));
        }

        break;

      case RRC_STATE_INACTIVE:
      case RRC_STATE_CONNECTED:
        /* should not happen */
        LOG_E(RRC, "[UE %d] indication %s in RRC state %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id));
        break;

      default:
        LOG_E(RRC, "[UE %d] Invalid RRC state %d\n", ue_mod_id, rrc_get_state(ue_mod_id));
        break;
      }

      break; // PHY_FIND_CELL_IND

    case PHY_MEAS_REPORT_IND: {
      MessageDef *message_p;
      message_p = itti_alloc_new_message(TASK_RRC_UE, RRC_RAL_MEASUREMENT_REPORT_IND);

      memcpy(&RRC_RAL_MEASUREMENT_REPORT_IND (message_p).threshold,
             &PHY_MEAS_REPORT_IND(msg_p).threshold,
             sizeof(RRC_RAL_MEASUREMENT_REPORT_IND (message_p).threshold));

      memcpy(&RRC_RAL_MEASUREMENT_REPORT_IND (message_p).link_param,
             &PHY_MEAS_REPORT_IND(msg_p).link_param,
             sizeof(RRC_RAL_MEASUREMENT_REPORT_IND (message_p).link_param));

      LOG_D(RRC, "[UE %d] PHY_MEAS_REPORT_IN: sending msg %s to %s \n", ue_mod_id, "RRC_RAL_MEASUREMENT_REPORT_IND", "TASK_RAL_UE");
      itti_send_msg_to_task(TASK_RAL_UE, instance, message_p);
      break;
    }

    case RRC_RAL_CONFIGURE_THRESHOLD_REQ:
      rrc_ue_ral_handle_configure_threshold_request(ue_mod_id, msg_p);
      break;

    case RRC_RAL_CONNECTION_ESTABLISHMENT_REQ:
      LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));

      switch (rrc_get_state(ue_mod_id)) {
      case RRC_STATE_IDLE: {
        if (rrc_get_sub_state(ue_mod_id) == RRC_SUB_STATE_IDLE_SIB_COMPLETE) {
          PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, ENB_FLAG_NO, UE_rrc_inst[ue_mod_id].Info[0].rnti, 0, 0, 0);
          rrc_ue_generate_RRCConnectionRequest(&ctxt, 0);
          LOG_D(RRC, "not sending connection request\n");
          rrc_set_sub_state (ue_mod_id, RRC_SUB_STATE_IDLE_CONNECTING);
        }

        break;
      }

      case RRC_STATE_INACTIVE:
      case RRC_STATE_CONNECTED:
        /* should not happen */
        LOG_E(RRC, "[UE %d] request %s in RRC state %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), rrc_get_state(ue_mod_id));
        break;

      default:
        LOG_E(RRC, "[UE %d] Invalid RRC state %d\n", ue_mod_id, rrc_get_state(ue_mod_id));
        break;
      }

      break;

    case RRC_RAL_CONNECTION_RELEASE_REQ:
      LOG_D(RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
      break;
#endif

    default:
      LOG_E(RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
      break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    msg_p = NULL;
  }
}
#endif



/*------------------------------------------------------------------------------*/
void
openair_rrc_top_init_ue(
			int eMBMS_active,
			char* uecap_xer,
			uint8_t cba_group_active,
			uint8_t HO_active
)
//-----------------------------------------------------------------------------
{

  module_id_t         module_id;
  OAI_UECapability_t *UECap     = NULL;
  int                 CC_id;

  /* for no gcc warnings */
  (void)CC_id;

  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);

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

    for (module_id = 0; module_id < NB_UE_INST; module_id++) {
      UE_rrc_inst[module_id].UECap = UECap;
      UE_rrc_inst[module_id].UECapability = UECap->sdu;
      UE_rrc_inst[module_id].UECapability_size = UECap->sdu_size;
    }

#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
    LOG_I(RRC,"[UE] eMBMS active state is %d \n", eMBMS_active);

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

#endif

#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
  /* TODO: this is disabled for the moment because the standard UE
   * crashes when calling this function.
   */
  //init_SL_preconfig(&UE_rrc_inst[module_id],0);
#endif

  } else {
    UE_rrc_inst = NULL;
  }

}

//-----------------------------------------------------------------------------
void
rrc_top_cleanup_ue(
  void
)
//-----------------------------------------------------------------------------
{

  if (NB_UE_INST > 0) free (UE_rrc_inst);


}


//-----------------------------------------------------------------------------
uint8_t rrc_ue_generate_SidelinkUEInformation( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index,LTE_SL_DestinationInfoList_r12_t  *destinationInfoList, long *discTxResourceReq, SL_TRIGGER_t mode)
{
   uint8_t    size=0;
   uint8_t buffer[100];

   //Generate SidelinkUEInformation
   if (((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&8192) > 0) && (destinationInfoList != NULL)) {//if SIB18 is available
      size = do_SidelinkUEInformation(ctxt_pP->module_id, buffer, destinationInfoList, NULL, mode);
      LOG_I(RRC,"[UE %d][RRC_UE] Frame %d : Logical Channel UL-DCCH, Generating SidelinkUEInformation (bytes%d, eNB %d)\n",
            ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index);
      //return size;
   }
   if (((UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].SIStatus&16384) > 0) && (discTxResourceReq != NULL)) {//if SIB19 is available
      size = do_SidelinkUEInformation(ctxt_pP->module_id, buffer, NULL, discTxResourceReq, mode);
      LOG_I(RRC,"[UE %d][RRC_UE] Frame %d : Logical Channel UL-DCCH, Generating SidelinkUEInformation (bytes%d, eNB %d)\n",
            ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index);
     //return size;
   }

   rrc_data_req_ue (
       ctxt_pP,
       DCCH,
       rrc_mui++,
       SDU_CONFIRM_NO,
       size,
       buffer,
       PDCP_TRANSMISSION_MODE_CONTROL);
   return size;
}


// 3GPP 36.331 (Section 5.10.7.3)
uint8_t fill_SLSS(const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_index, LTE_SLSSID_r12_t *slss_id, uint8_t *subframe, uint8_t mode)
{
   long syncOffsetIndicator = 0;
   switch(mode) {
   case 1: //if triggered by SL discovery announcement and in-coverage
      //discSyncConfig_r12 contains only one element
      *slss_id = UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index]->discConfig_r12->discSyncConfig_r12->list.array[0]->slssid_r12;
      syncOffsetIndicator = UE_rrc_inst[ctxt_pP->module_id].sib19[eNB_index]->discConfig_r12->discSyncConfig_r12->list.array[0]->syncOffsetIndicator_r12;
      //select subframe for SLSS
      break;
   case 2: //if triggered by SL communication and in-coverage

      if (UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->txParameters_r12) {
         *slss_id = UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->slssid_r12;
         syncOffsetIndicator = UE_rrc_inst[ctxt_pP->module_id].sib18[eNB_index]->commConfig_r12->commSyncConfig_r12->list.array[0]->syncOffsetIndicator_r12;

         //if RRC_CONNECTED (Todo: and if networkControlledSyncTx (RRCConnectionReconfiguration) is configured and set to On)
         if (UE_rrc_inst[ctxt_pP->module_id].Info[eNB_index].State == RRC_CONNECTED){
            //select subframe(s) indicated by syncOffsetIndicator
            *subframe = syncOffsetIndicator;
         } else {
            //select subframe(s) indicated by syncOffsetIndicator within SC period
         }
         break;
   case 3: //if triggered by V2X communication and in coverage

      break;
   case 4: //if triggered by V2X communication and out-of-coverage

      break;
   case 5: //if triggered by V2X communication and UE has GNSS as the synchronization reference

   default:
      //if UE has a selected SyncRefUE
      //TODO
      //else (no SyncRefUE Selected)
      //Todo  if trigger by V2X
      //else randomly select an SLSSID from the set defined for out-of-coverage
      *slss_id = 170;//hardcoded
      //select the subframe according to syncOffsetIndicator1/2 from the preconfigured parameters
      break;
      }
   }
   return 0;
}


//-----------------------------------------------------------------------------
void
rrc_ue_process_sidelink_radioResourceConfig(
      module_id_t                      Mod_idP,
      uint8_t                          eNB_index,
      LTE_SystemInformationBlockType18_r12_t     *sib18,
      LTE_SystemInformationBlockType19_r12_t     *sib19,
      LTE_SL_CommConfig_r12_t* sl_CommConfig,
      LTE_SL_DiscConfig_r12_t* sl_DiscConfig
)
//-----------------------------------------------------------------------------
{
   //process SIB18, configure MAC/PHY for receiving SL communication (RRC_IDLE and RRC_CONNECTED), for transmitting SL communication (RRC_IDLE)
   if (sib18 != NULL) {
      if (sib18->commConfig_r12 != NULL) {
         //do not consider commTXPoolExceptional for the moment
         //configure PHY/MAC to receive SL communication by using the RPs indicated by commRxPool
         //sib18->commConfig_r12->commRxPool_r12
         //TODO

         if (sib18->commConfig_r12->commTxPoolNormalCommon_r12 !=NULL) { //commTxPoolNormalCommon - to transmit SL communication in RRC_IDLE
            //maybe we don't consider this case for the moment since UE will immediately establish a RRC connection after receiving SIB messages
            //configure PHY/MAC to transmit SL communication using the RPs indicated by the first entry in commTxPoolNormalCommon
            //SL_CommResourcePool_r12_t sl_CommResourcePool = sib18->commConfig_r12->commTxPoolNormalCommon_r12->list.array[0];
         }
      }
   }

   //process SIB19, configure MAC/PHY for receiving SL discovery (RRC_IDLE and RRC_CONNECTED), for transmitting SL discovery (RRC_IDLE)
   if (sib19 != NULL) {
      //to receive non-PS related discovery announcements (discRxPool)
      //sib19->discConfig_r12->discRxPool_r12;

      //to receive PS related discovery announcements (discRxPoolPS)
      //sib19->ext1->discConfigPS_13->discRxPoolPS_r13;

      //to transmit non-PS related discovery in RRC_IDLE
      //sib19->discConfig_r12->discTxPoolCommon_r12;

      //to transmit PS related discovery in RRC_IDLE
      //sib19->ext1->discConfigPS_13->discTxPoolPS_Common_r13;
   }

   //process sl_CommConfig, configure MAC/PHY for transmitting SL communication (RRC_CONNECTED)
   if (sl_CommConfig != NULL) {

      if (sl_CommConfig->commTxResources_r12 != NULL) {
         switch (sl_CommConfig->commTxResources_r12->present){
         case LTE_SL_CommConfig_r12__commTxResources_r12_PR_setup:
            if (sl_CommConfig->commTxResources_r12->choice.setup.present == LTE_SL_CommConfig_r12__commTxResources_r12__setup_PR_scheduled_r12 ){

               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, sl_RNTI size %lu  \n",
                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.size );
               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, sl_RNTI buf 0x%p \n",
                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.sl_RNTI_r12.buf );
               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, Mac_MainConfig_r12.retx_BSR_TimerSL %ld \n",
                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mac_MainConfig_r12.retx_BSR_TimerSL );
               LOG_I(RRC,"[UE %d][RRC_UE] scheduled resource for SL, sc_CommTxConfig %ld \n",
                     Mod_idP, sl_CommConfig->commTxResources_r12->choice.setup.choice.scheduled_r12.mac_MainConfig_r12.retx_BSR_TimerSL );
               //configure scheduled resource for SL
               //TODO
            } else if (sl_CommConfig->commTxResources_r12->choice.setup.present == LTE_SL_CommConfig_r12__commTxResources_r12__setup_PR_ue_Selected_r12){
               //configure dedicated resources (commTxPoolNormalDedicated) for SL from which UE can autonomously select
               //sl_CommConfig->commTxResources_r12->choice.setup.choice.ue_Selected_r12.commTxPoolNormalDedicated_r12;

               //for the moment, only pass the first entry (e.g., do not consider priorityList in commTxPoolNormalDedicated (3GPP 36.331 Section 5.10.4 1>2>3>4))
               //sl_CommConfig->commTxResources_r12->choice.setup.choice.ue_Selected_r12.commTxPoolNormalDedicated_r12.poolToAddModList_r12->list.array[0];
            } else {
               //SL_CommConfig_r12__commTxResources_r12__setup_PR_NOTHING /* No components present */
            }
            break;

         case LTE_SL_CommConfig_r12__commTxResources_r12_PR_release:
            //release dedicated resources for SL communication
            break;

         case LTE_SL_CommConfig_r12__commTxResources_r12_PR_NOTHING: /* No components present */
            break;

         default:
            break;
         }
      }

   }

   //process sl_DiscConfig, configure MAC/PHY for transmitting SL discovery announcements (RRC_CONNECTED)
   if (sl_DiscConfig != NULL) {
      //dedicated resources for transmitting non-PS related discovery
      if (sl_DiscConfig->discTxResources_r12 != NULL) {

         switch (sl_DiscConfig->discTxResources_r12->present) {
         case LTE_SL_DiscConfig_r12__discTxResources_r12_PR_setup:
            if (sl_DiscConfig->discTxResources_r12->choice.setup.present == LTE_SL_DiscConfig_r12__discTxResources_r12__setup_PR_scheduled_r12) {
               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.scheduled_r12.discHoppingConfig_r12;
               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.scheduled_r12.discTF_IndexList_r12;
               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.scheduled_r12.discTxConfig_r12;
            } else if (sl_DiscConfig->discTxResources_r12->choice.setup.present == LTE_SL_DiscConfig_r12__discTxResources_r12__setup_PR_ue_Selected_r12) {
               //sl_DiscConfig->discTxResources_r12->choice.setup.choice.ue_Selected_r12.discTxPoolDedicated_r12;
            } else {
               //SL_DiscConfig_r12__discTxResources_r12__setup_PR_NOTHING,   /* No components present */
            }
            break;
         case LTE_SL_DiscConfig_r12__discTxResources_r12_PR_release:
            //release dedicated resources for SL discovery
            break;
         case LTE_SL_DiscConfig_r12__discTxResources_r12_PR_NOTHING: /* No components present */
            break;
         default:
            break;
         }

      }
      //dedicated resources for transmitting PS related discovery
      if (sl_DiscConfig->ext2->discTxResourcesPS_r13 != NULL){
         switch (sl_DiscConfig->ext2->discTxResourcesPS_r13->present) {
         case LTE_SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_setup:
            if (sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.present == LTE_SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_scheduled_r13) {
               //sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.choice.scheduled_r13.discHoppingConfig_r13;
               //sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.choice.scheduled_r13.discTxConfig_r13
            } else if (sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.present == LTE_SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_ue_Selected_r13) {
               //sl_DiscConfig->ext2->discTxResourcesPS_r13->choice.setup.choice.ue_Selected_r13.discTxPoolPS_Dedicated_r13;
            } else {
               //SL_DiscConfig_r12__ext2__discTxResourcesPS_r13__setup_PR_NOTHING, /* No components present */
            }

            break;
         case LTE_SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_release:
            break;
         case LTE_SL_DiscConfig_r12__ext2__discTxResourcesPS_r13_PR_NOTHING:
            /* No components present */
            break;
         default:
            break;
         }
      }
   }
}

#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
//-----------------------------------------------------------
void
rrc_control_socket_init(){

   struct sockaddr_in rrc_ctrl_socket_addr;
   pthread_attr_t     attr;
   struct sched_param sched_param;
   int optval; // flag value for setsockopt
   //int n; // message byte size


   // create the control socket
   ctrl_sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
   if (ctrl_sock_fd == -1) {
      LOG_E(RRC,"[rrc_control_socket_init] :Error opening socket %d (%d:%s)\n",ctrl_sock_fd,errno, strerror(errno));
      exit(EXIT_FAILURE);
   }
   //   if (ctrl_sock_fd < 0)
   //      error("ERROR: Failed on opening socket");
   optval = 1;
   setsockopt(ctrl_sock_fd, SOL_SOCKET, SO_REUSEADDR,
         (const void *)&optval , sizeof(int));

   //build the server's  address
   bzero((char *) &rrc_ctrl_socket_addr, sizeof(rrc_ctrl_socket_addr));
   rrc_ctrl_socket_addr.sin_family = AF_INET;
   rrc_ctrl_socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
   rrc_ctrl_socket_addr.sin_port = htons(CONTROL_SOCKET_PORT_NO);
   // associate the parent socket with a port
   if (bind(ctrl_sock_fd, (struct sockaddr *) &rrc_ctrl_socket_addr,
         sizeof(rrc_ctrl_socket_addr)) < 0) {
      LOG_E(RRC,"[rrc_control_socket_init] ERROR: Failed on binding the socket\n");
      exit(1);
   }
   //create thread to listen to incoming packets
   if (pthread_attr_init(&attr) != 0) {
      LOG_E(RRC, "[rrc_control_socket_init]Failed to initialize pthread attribute for ProSe -> RRC communication (%d:%s)\n",
            errno, strerror(errno));
      exit(EXIT_FAILURE);
   }

   sched_param.sched_priority = 10;

   pthread_attr_setschedpolicy(&attr, SCHED_RR);
   pthread_attr_setschedparam(&attr, &sched_param);

   pthread_t rrc_control_socket_thread;

   if (pthread_create(&rrc_control_socket_thread, &attr, rrc_control_socket_thread_fct, NULL) != 0) {
      LOG_E(RRC, "[rrc_control_socket_init]Failed to create new thread for RRC/ProSeApp communication (%d:%s)\n",
            errno, strerror(errno));
      exit(EXIT_FAILURE);
   }

   pthread_setname_np( rrc_control_socket_thread, "RRC Control Socket" );

}

//--------------------------------------------------------
void *rrc_control_socket_thread_fct(void *arg)
{

   int prose_addr_len;
   char send_buf[BUFSIZE];
   char receive_buf[BUFSIZE];
   //int optval;
   int n;
   struct sidelink_ctrl_element *sl_ctrl_msg_recv = NULL;
   struct sidelink_ctrl_element *sl_ctrl_msg_send = NULL;
   uint32_t sourceL2Id, groupL2Id, destinationL2Id;
   module_id_t         module_id = 0; //hardcoded for testing only
   uint8_t type;
   UE_RRC_INST *UE  = NULL;
   protocol_ctxt_t ctxt;
   struct LTE_RLC_Config                  *DRB_rlc_config                   = NULL;
   struct LTE_PDCP_Config                 *DRB_pdcp_config                  = NULL;
   struct LTE_PDCP_Config__rlc_UM         *PDCP_rlc_UM                      = NULL;
   struct LTE_LogicalChannelConfig        *DRB_lchan_config                 = NULL;
   struct LTE_LogicalChannelConfig__ul_SpecificParameters  *DRB_ul_SpecificParameters = NULL;
   long                               *logicalchannelgroup_drb          = NULL;
   int j = 0;
   int i = 0;

   //from the main program, listen for the incoming messages from control socket (ProSe App)
   prose_addr_len = sizeof(prose_app_addr);
   //int enable_notification = 1;
   while (1) {
      LOG_I(RRC,"Listening to incoming connection from ProSe App \n");
      // receive a message from ProSe App
      memset(receive_buf, 0, BUFSIZE);
      n = recvfrom(ctrl_sock_fd, receive_buf, BUFSIZE, 0,
            (struct sockaddr *) &prose_app_addr, (socklen_t *)&prose_addr_len);
      if (n < 0){
         LOG_E(RRC, "ERROR: Failed to receive from ProSe App\n");
         exit(EXIT_FAILURE);
      }
      //TODO: should store the address of ProSeApp [UE_rrc_inst] to be able to send UE state notification to the App

      //sl_ctrl_msg_recv = (struct sidelink_ctrl_element *) receive_buf;
      sl_ctrl_msg_recv = calloc(1, sizeof(struct sidelink_ctrl_element));
      memcpy((void *)sl_ctrl_msg_recv, (void *)receive_buf, sizeof(struct sidelink_ctrl_element));

      //process the message
      switch (sl_ctrl_msg_recv->type) {
      case SESSION_INIT_REQ:
         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           LOG_UI(RRC,"Received SessionInitializationRequest on socket from ProSe App (msg type: %d)\n", sl_ctrl_msg_recv->type);
         }
         //TODO: get SL_UE_STATE from lower layer

         LOG_I(RRC,"Send UEStateInformation to ProSe App \n");
         memset(send_buf, 0, BUFSIZE);

         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
         sl_ctrl_msg_send->type = UE_STATUS_INFO;
         sl_ctrl_msg_send->sidelinkPrimitive.ue_state = UE_STATE_OFF_NETWORK; //off-network
         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
         free(sl_ctrl_msg_send);

         prose_addr_len = sizeof(prose_app_addr);
         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
         if (n < 0) {
            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }

         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
           ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
           LOG_UI(RRC,"[UEStateInformation] msg type: %d\n",ptr_ctrl_msg->type);
           LOG_UI(RRC,"[UEStateInformation] UE state: %d\n",ptr_ctrl_msg->sidelinkPrimitive.ue_state);
         }
         /*  if (enable_notification > 0) {
              //create thread to send status notification (for testing purpose, status notification will be sent e.g., every 20 seconds)
              pthread_t notification_thread;
              if( pthread_create( &notification_thread , NULL ,  send_UE_status_notification , (void*) &sockfd) < 0)
                 error("ERROR: could not create thread");
           }
           enable_notification = 0;
          */
         break;

      case GROUP_COMMUNICATION_ESTABLISH_REQ:
         sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id;
         groupL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id;

         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           LOG_UI(RRC,"[GroupCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
           LOG_UI(RRC,"[GroupCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
           LOG_UI(RRC,"[GroupCommunicationEstablishReq] group Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
           LOG_UI(RRC,"[GroupCommunicationEstablishReq] group IP Address: " IPV4_ADDR "\n",IPV4_ADDR_FORMAT(sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupIpAddress));
         }

         //store sourceL2Id/groupL2Id
         UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
         UE_rrc_inst[module_id].groupL2Id = groupL2Id;
         j = 0;
         i = 0;
         for (i=0; i< MAX_NUM_DEST; i++) {
            if ((UE_rrc_inst[module_id].destinationList[i] == 0) && (j == 0)) j = i+1;
            if (UE_rrc_inst[module_id].destinationList[i] == groupL2Id) break; //group already exists!
         }
         if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[module_id].destinationList[j-1] = groupL2Id;

         // configure lower layers PDCP/MAC/PHY for this communication
         //Establish a new RBID/LCID for this communication
         // Establish a SLRB (using DRB 3 for now)
         UE  = &UE_rrc_inst[module_id];
         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);

         UE->DRB_config[0][0] = CALLOC(1,sizeof(struct LTE_DRB_ToAddMod));
         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
         UE->DRB_config[0][0]->drb_Identity =  3;
         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
         // allowed value 5..15, value : x+4
         *(UE->DRB_config[0][0]->eps_BearerIdentity) = 3;
         UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
         *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2

         DRB_rlc_config                   = CALLOC(1,sizeof(struct LTE_RLC_Config));
         DRB_pdcp_config                  = CALLOC(1,sizeof(struct LTE_PDCP_Config));
         PDCP_rlc_UM                      = CALLOC(1,sizeof(struct LTE_PDCP_Config__rlc_UM));
         DRB_lchan_config                 = CALLOC(1,sizeof(struct LTE_LogicalChannelConfig));
         DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LTE_LogicalChannelConfig__ul_SpecificParameters));
         logicalchannelgroup_drb          = CALLOC(1, sizeof(long));

         DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional;
         DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10;
         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10;
         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35;
         UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;

         DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
         UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
         DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
         *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity;
         DRB_pdcp_config->rlc_AM = NULL;
         DRB_pdcp_config->rlc_UM = NULL;

         /* avoid gcc warnings */
         (void)PDCP_rlc_UM;

         DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
         PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
         DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed;

         UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
         DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
         DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;

         DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
         DRB_ul_SpecificParameters->prioritisedBitRate =LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
         //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
         DRB_ul_SpecificParameters->bucketSizeDuration =
               LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;

         // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)

         *logicalchannelgroup_drb = 1;
         DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;

         UE->DRB_configList = CALLOC(1,sizeof(LTE_DRB_ToAddModList_t));
         ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);

         rrc_pdcp_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t *) NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*) NULL,
               0xff, NULL, NULL, NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               , (LTE_PMCH_InfoList_r9_t *) NULL
#endif
               ,NULL);


         rrc_rlc_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t*)NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,(LTE_PMCH_InfoList_r9_t *)NULL
               , 0, 0
#endif
         );

         rrc_rlc_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t*)NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
               ,(LTE_PMCH_InfoList_r9_t *)NULL
               , sourceL2Id, groupL2Id
#endif
         );


         //configure MAC with sourceL2Id/groupL2ID
         rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
               (LTE_RadioResourceConfigCommonSIB_t *)NULL,
               (struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               (LTE_SCellToAddMod_r10_t *)NULL,
               //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
               (LTE_MeasObjectToAddMod_t **)NULL,
               (LTE_MAC_MainConfig_t *)NULL,
               3, //LCID
               (struct LTE_LogicalChannelConfig *)NULL,
               (LTE_MeasGapConfig_t *)NULL,
               (LTE_TDD_Config_t *)NULL,
               (LTE_MobilityControlInfo_t *)NULL,
               NULL,
               NULL,
               NULL,
               NULL,
               NULL,
               NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,0,
               (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
               (LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
               ,
               0,
               0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,CONFIG_ACTION_ADD,
               &sourceL2Id,
               &groupL2Id
#endif
         );

         LOG_I(RRC,"Send GroupCommunicationEstablishResp to ProSe App\n");
         memset(send_buf, 0, BUFSIZE);
         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
         sl_ctrl_msg_send->type = GROUP_COMMUNICATION_ESTABLISH_RSP;
         sl_ctrl_msg_send->sidelinkPrimitive.slrb_id = 3; //slrb_id

         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
         free(sl_ctrl_msg_send);

         prose_addr_len = sizeof(prose_app_addr);
         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
         if (n < 0){
            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }

         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
           ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
           LOG_UI(RRC,"[GroupCommunicationEstablishResponse]  msg type: %d\n",ptr_ctrl_msg->type);
           LOG_UI(RRC,"[GroupCommunicationEstablishResponse]  slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
         }
         break;

      case GROUP_COMMUNICATION_RELEASE_REQ:
         printf("-----------------------------------\n");
         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           LOG_UI(RRC,"[GroupCommunicationReleaseRequest] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
           LOG_UI(RRC,"[GroupCommunicationReleaseRequest] Slrb Id: %i\n",sl_ctrl_msg_recv->sidelinkPrimitive.slrb_id);
         }
         //reset groupL2ID from MAC LAYER
         UE_rrc_inst[module_id].groupL2Id = 0x00000000;
         sourceL2Id = UE_rrc_inst[module_id].sourceL2Id;

         rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
                    (LTE_RadioResourceConfigCommonSIB_t *)NULL,
                    (struct LTE_PhysicalConfigDedicated *)NULL,
         #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                    (LTE_SCellToAddMod_r10_t *)NULL,
                    //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
         #endif
                    (LTE_MeasObjectToAddMod_t **)NULL,
                    (LTE_MAC_MainConfig_t *)NULL,
                    0,
                    (struct LTE_LogicalChannelConfig *)NULL,
                    (LTE_MeasGapConfig_t *)NULL,
                    (LTE_TDD_Config_t *)NULL,
                    (LTE_MobilityControlInfo_t *)NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    NULL
         #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                    ,0,
                    (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
                    (LTE_PMCH_InfoList_r9_t *)NULL

         #endif
         #ifdef CBA
                    ,
                    0,
                    0
         #endif
         #if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                    ,CONFIG_ACTION_REMOVE,
                    &sourceL2Id,
                    &destinationL2Id
         #endif
                    );


         LOG_I(RRC,"Send GroupCommunicationReleaseResponse to ProSe App \n");
         memset(send_buf, 0, BUFSIZE);

         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
         sl_ctrl_msg_send->type = GROUP_COMMUNICATION_RELEASE_RSP;
         //if the requested id exists -> release this ID
         if (sl_ctrl_msg_recv->sidelinkPrimitive.slrb_id == slrb_id) {
            sl_ctrl_msg_send->sidelinkPrimitive.group_comm_release_rsp = GROUP_COMMUNICATION_RELEASE_OK;
            slrb_id = 0; //Reset slrb_id
         } else {
            sl_ctrl_msg_send->sidelinkPrimitive.group_comm_release_rsp = GROUP_COMMUNICATION_RELEASE_FAILURE;
         }
         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
         free(sl_ctrl_msg_send);

         prose_addr_len = sizeof(prose_app_addr);
         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
         if (n < 0){
            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }
         break;


      case DIRECT_COMMUNICATION_ESTABLISH_REQ:
         sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.direct_comm_establish_req.sourceL2Id;
         destinationL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.direct_comm_establish_req.destinationL2Id;

         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           LOG_UI(RRC,"[DirectCommunicationEstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
           LOG_UI(RRC,"[DirectCommunicationEstablishReq] source Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.sourceL2Id);
           LOG_UI(RRC,"[DirectCommunicationEstablishReq] destination Id: 0x%08x\n",sl_ctrl_msg_recv->sidelinkPrimitive.group_comm_establish_req.groupL2Id);
         }

         //store sourceL2Id/destinationL2Id
         UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
         i = 0;
         j = 0;
         for (i=0; i< MAX_NUM_DEST; i++) {
            if ((UE_rrc_inst[module_id].destinationList[i] == 0) && (j == 0)) j = i+1;
            if (UE_rrc_inst[module_id].destinationList[i] == destinationL2Id) break; //destination already exists!
         }
         if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[module_id].destinationList[j-1] = destinationL2Id;

         // configure lower layers PDCP/MAC/PHY for this communication
         //Establish a new RBID/LCID for this communication
         // Establish a SLRB (using DRB 3 for now)
         UE  = &UE_rrc_inst[module_id];
         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);

         UE->DRB_config[0][0] = CALLOC(1,sizeof(struct LTE_DRB_ToAddMod));
         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
         UE->DRB_config[0][0]->drb_Identity =  3;
         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
         // allowed value 5..15, value : x+4
         *(UE->DRB_config[0][0]->eps_BearerIdentity) = 3;
         UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
         *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2

         DRB_rlc_config                   = CALLOC(1,sizeof(struct LTE_RLC_Config));
         DRB_pdcp_config                  = CALLOC(1,sizeof(struct LTE_PDCP_Config));
         PDCP_rlc_UM                      = CALLOC(1,sizeof(struct LTE_PDCP_Config__rlc_UM));
         DRB_lchan_config                 = CALLOC(1,sizeof(struct LTE_LogicalChannelConfig));
         DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LTE_LogicalChannelConfig__ul_SpecificParameters));
         logicalchannelgroup_drb          = CALLOC(1, sizeof(long));

         DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional;
         DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10;
         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10;
         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35;
         UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;

         DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
         UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
         DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
         *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity;
         DRB_pdcp_config->rlc_AM = NULL;
         DRB_pdcp_config->rlc_UM = NULL;

         /* avoid gcc warnings */
         (void)PDCP_rlc_UM;

         DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
         PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
         DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed;

         UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
         DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
         DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;

         DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
         DRB_ul_SpecificParameters->prioritisedBitRate =LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
         //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
         DRB_ul_SpecificParameters->bucketSizeDuration =
               LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;

         // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)

         *logicalchannelgroup_drb = 1;
         DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;

         UE->DRB_configList = CALLOC(1,sizeof(LTE_DRB_ToAddModList_t));
         ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);

         rrc_pdcp_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t *) NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*) NULL,
               0xff, NULL, NULL, NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               , (LTE_PMCH_InfoList_r9_t *) NULL
#endif
               ,NULL);


         rrc_rlc_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t*)NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,(LTE_PMCH_InfoList_r9_t *)NULL
               , 0, 0
#endif
         );

         rrc_rlc_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t*)NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
               ,(LTE_PMCH_InfoList_r9_t *)NULL
               , sourceL2Id, destinationL2Id
#endif
         );


         //configure MAC with sourceL2Id/destinationL2Id
         rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
               (LTE_RadioResourceConfigCommonSIB_t *)NULL,
               (struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               (LTE_SCellToAddMod_r10_t *)NULL,
               //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
               (LTE_MeasObjectToAddMod_t **)NULL,
               (LTE_MAC_MainConfig_t *)NULL,
               3, //LCID
               (struct LTE_LogicalChannelConfig *)NULL,
               (LTE_MeasGapConfig_t *)NULL,
               (LTE_TDD_Config_t *)NULL,
               (LTE_MobilityControlInfo_t *)NULL,
               NULL,
               NULL,
               NULL,
               NULL,
               NULL,
               NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,0,
               (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
               (LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
               ,
               0,
               0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,CONFIG_ACTION_ADD,
               &sourceL2Id,
               &destinationL2Id
#endif
         );

         LOG_I(RRC,"Send DirectCommunicationEstablishResp to ProSe App\n");
         memset(send_buf, 0, BUFSIZE);
         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
         sl_ctrl_msg_send->type = DIRECT_COMMUNICATION_ESTABLISH_RSP;
         sl_ctrl_msg_send->sidelinkPrimitive.slrb_id = 3; //slrb_id

         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
         free(sl_ctrl_msg_send);

         prose_addr_len = sizeof(prose_app_addr);
         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
         if (n < 0){
            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }


         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           struct sidelink_ctrl_element *ptr_ctrl_msg = NULL;
           ptr_ctrl_msg = (struct sidelink_ctrl_element *) send_buf;
           LOG_UI(RRC,"[DirectCommunicationEstablishResponse]  msg type: %d\n",ptr_ctrl_msg->type);
           LOG_UI(RRC,"[DirectCommunicationEstablishResponse]  slrb_id: %d\n",ptr_ctrl_msg->sidelinkPrimitive.slrb_id);
         }
         break;

      case PC5S_ESTABLISH_REQ:
           type =  sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type;
           sourceL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id;
           if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
             LOG_UI(RRC,"[PC5EstablishReq] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
             LOG_UI(RRC,"[PC5EstablishReq] type: %d\n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.type); //RX/TX
             LOG_UI(RRC,"[PC5EstablishReq] source Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.sourceL2Id);
           }
         if (type > 0) {
            destinationL2Id = sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id;
            if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
              LOG_UI(RRC,"[PC5EstablishReq] destination Id: 0x%08x \n",sl_ctrl_msg_recv->sidelinkPrimitive.pc5s_establish_req.destinationL2Id);
            }
         }

         //store sourceL2Id/destinationL2Id
         if (type > 0) { //TX
            UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
            j = 0;
            i = 0;
            for (i=0; i< MAX_NUM_DEST; i++) {
               if ((UE_rrc_inst[module_id].destinationList[i] == 0) && (j == 0)) j = i+1;
               if (UE_rrc_inst[module_id].destinationList[i] == destinationL2Id) break; //group already exists!
            }
            if ((i == MAX_NUM_DEST) && (j > 0))  UE_mac_inst[module_id].destinationList[j-1] = destinationL2Id;
         } else {//RX
            UE_rrc_inst[module_id].sourceL2Id = sourceL2Id;
         }

         // configure lower layers PDCP/MAC/PHY for this communication
         //Establish a new RBID/LCID for this communication
         // Establish a SLRB (using DRB 10 for now)
         UE  = &UE_rrc_inst[module_id];
         PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, 0, ENB_FLAG_NO, 0x1234, 0, 0,0);

         UE->DRB_config[0][0] = CALLOC(1,sizeof(struct LTE_DRB_ToAddMod));
         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
         UE->DRB_config[0][0]->drb_Identity =  10;
         UE->DRB_config[0][0]->eps_BearerIdentity = CALLOC(1, sizeof(long));
         // allowed value 5..15, value : x+4
         *(UE->DRB_config[0][0]->eps_BearerIdentity) = 10;
         UE->DRB_config[0][0]->logicalChannelIdentity = CALLOC(1, sizeof(long));
         *(UE->DRB_config[0][0]->logicalChannelIdentity) = UE->DRB_config[0][0]->drb_Identity; //(long) (ue_context_pP->ue_context.e_rab[i].param.e_rab_id + 2); // value : x+2

         DRB_rlc_config                   = CALLOC(1,sizeof(struct LTE_RLC_Config));
         DRB_pdcp_config                  = CALLOC(1,sizeof(struct LTE_PDCP_Config));
         PDCP_rlc_UM                      = CALLOC(1,sizeof(struct LTE_PDCP_Config__rlc_UM));
         DRB_lchan_config                 = CALLOC(1,sizeof(struct LTE_LogicalChannelConfig));
         DRB_ul_SpecificParameters                                         = CALLOC(1, sizeof(struct LTE_LogicalChannelConfig__ul_SpecificParameters));
         logicalchannelgroup_drb          = CALLOC(1, sizeof(long));

         DRB_rlc_config->present = LTE_RLC_Config_PR_um_Bi_Directional;
         DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10;
         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = LTE_SN_FieldLength_size10;
         DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = LTE_T_Reordering_ms35;
         UE->DRB_config[0][0]->rlc_Config = DRB_rlc_config;

         DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
         UE->DRB_config[0][0]->pdcp_Config = DRB_pdcp_config;
         DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
         *DRB_pdcp_config->discardTimer = LTE_PDCP_Config__discardTimer_infinity;
         DRB_pdcp_config->rlc_AM = NULL;
         DRB_pdcp_config->rlc_UM = NULL;

         /* avoid gcc warnings */
         (void)PDCP_rlc_UM;

         DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
         PDCP_rlc_UM->pdcp_SN_Size = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
         DRB_pdcp_config->headerCompression.present = LTE_PDCP_Config__headerCompression_PR_notUsed;

         UE->DRB_config[0][0]->logicalChannelConfig = DRB_lchan_config;
         DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
         DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;

         DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
         DRB_ul_SpecificParameters->prioritisedBitRate = LTE_LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
         //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
         DRB_ul_SpecificParameters->bucketSizeDuration =
               LTE_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;

         // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)

         *logicalchannelgroup_drb = 1;
         DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;

         UE->DRB_configList = CALLOC(1,sizeof(LTE_DRB_ToAddModList_t));
         ASN_SEQUENCE_ADD(&UE->DRB_configList->list,UE->DRB_config[0][0]);

         rrc_pdcp_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t *) NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*) NULL,
               0xff, NULL, NULL, NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               , (LTE_PMCH_InfoList_r9_t *) NULL
#endif
               ,NULL);


         rrc_rlc_config_asn1_req(&ctxt,
               (LTE_SRB_ToAddModList_t*)NULL,
               UE->DRB_configList,
               (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
               ,(LTE_PMCH_InfoList_r9_t *)NULL
               , 0, 0
#endif
         );

         //TX
         if (type > 0) {
            rrc_rlc_config_asn1_req(&ctxt,
                  (LTE_SRB_ToAddModList_t*)NULL,
                  UE->DRB_configList,
                  (LTE_DRB_ToReleaseList_t*)NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
                  ,(LTE_PMCH_InfoList_r9_t *)NULL
                  , sourceL2Id, destinationL2Id
#endif
            );

            //configure MAC with sourceL2Id/groupL2ID
            rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
                  (LTE_RadioResourceConfigCommonSIB_t *)NULL,
                  (struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                  (LTE_SCellToAddMod_r10_t *)NULL,
                  //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
                  (LTE_MeasObjectToAddMod_t **)NULL,
                  (LTE_MAC_MainConfig_t *)NULL,
                  10, //LCID
                  (struct LTE_LogicalChannelConfig *)NULL,
                  (LTE_MeasGapConfig_t *)NULL,
                  (LTE_TDD_Config_t *)NULL,
                  (LTE_MobilityControlInfo_t *)NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                  ,0,
                  (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
                  (LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
                  ,
                  0,
                  0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                  ,CONFIG_ACTION_ADD,
                  &sourceL2Id,
                  &destinationL2Id
#endif
            );
         } else {//RX
            //configure MAC with sourceL2Id/groupL2ID
            rrc_mac_config_req_ue(module_id,0,0, //eNB_index =0
                  (LTE_RadioResourceConfigCommonSIB_t *)NULL,
                  (struct LTE_PhysicalConfigDedicated *)NULL,
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                  (LTE_SCellToAddMod_r10_t *)NULL,
                  //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
                  (LTE_MeasObjectToAddMod_t **)NULL,
                  (LTE_MAC_MainConfig_t *)NULL,
                  10, //LCID
                  (struct LTE_LogicalChannelConfig *)NULL,
                  (LTE_MeasGapConfig_t *)NULL,
                  (LTE_TDD_Config_t *)NULL,
                  (LTE_MobilityControlInfo_t *)NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                  ,0,
                  (LTE_MBSFN_AreaInfoList_r9_t *)NULL,
                  (LTE_PMCH_InfoList_r9_t *)NULL

#endif
#ifdef CBA
                  ,
                  0,
                  0
#endif
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
                  ,CONFIG_ACTION_ADD,
                  &sourceL2Id,
                  NULL
#endif
            );

         }

         LOG_I(RRC,"Send PC5EstablishRsp to ProSe App\n");
         memset(send_buf, 0, BUFSIZE);
         sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
         sl_ctrl_msg_send->type = PC5S_ESTABLISH_RSP;
         sl_ctrl_msg_send->sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid28 = 10;
         sl_ctrl_msg_send->sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid29 = 10;
         sl_ctrl_msg_send->sidelinkPrimitive.pc5s_establish_rsp.slrbid_lcid30 = 10;
         memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));

         prose_addr_len = sizeof(prose_app_addr);
         n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
//         free(sl_ctrl_msg_send);
         if (n < 0){
            LOG_E(RRC, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }
         break;


      case PC5_DISCOVERY_MESSAGE:

         if (LOG_DEBUGFLAG(DEBUG_CTRLSOCKET)){
           LOG_UI(RRC,"[PC5DiscoveryMessage] Received on socket from ProSe App (msg type: %d)\n",sl_ctrl_msg_recv->type);
         }
        //prepare SL_Discovery buffer
         if (UE_rrc_inst) {
           memcpy((void*)&UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.Payload[0], (void*)&sl_ctrl_msg_recv->sidelinkPrimitive.pc5_discovery_message.payload[0], PC5_DISCOVERY_PAYLOAD_SIZE);
           UE_rrc_inst[module_id].SL_Discovery[0].Tx_buffer.payload_size = PC5_DISCOVERY_PAYLOAD_SIZE;
           LOG_I(RRC,"[PC5DiscoveryMessage] Copied %d bytes\n",PC5_DISCOVERY_PAYLOAD_SIZE);
         }
         break;
      default:
         break;
      }
   }
   free (sl_ctrl_msg_recv);
   return 0;
}


//-----------------------------------------------------------------------------
int decode_SL_Discovery_Message(
  const protocol_ctxt_t* const ctxt_pP,
  const uint8_t                eNB_index,
  const uint8_t*               Sdu,
  const uint8_t                Sdu_len)
{

   int prose_addr_len;
   char send_buf[BUFSIZE];
   int n;
   struct sidelink_ctrl_element *sl_ctrl_msg_send = NULL;

   //from the main program, listen for the incoming messages from control socket (ProSe App)
   prose_addr_len = sizeof(prose_app_addr);

   //Store in Rx_buffer
   memcpy((void*)&UE_rrc_inst[ctxt_pP->module_id].SL_Discovery[0].Rx_buffer.Payload[0], (void*)Sdu, Sdu_len);
   UE_rrc_inst[ctxt_pP->module_id].SL_Discovery[0].Rx_buffer.payload_size = Sdu_len;

   memset(send_buf, 0, BUFSIZE);
   //send to ProSeApp
   memcpy((void *)send_buf, (void*)Sdu, Sdu_len);
   prose_addr_len = sizeof(prose_app_addr);

   sl_ctrl_msg_send = calloc(1, sizeof(struct sidelink_ctrl_element));
   sl_ctrl_msg_send->type = PC5_DISCOVERY_MESSAGE;
   // TODO:  Add a check for the SDU size.
   memcpy((void*)&sl_ctrl_msg_send->sidelinkPrimitive.pc5_discovery_message.payload[0], (void*) Sdu,  PC5_DISCOVERY_PAYLOAD_SIZE);

   memcpy((void *)send_buf, (void *)sl_ctrl_msg_send, sizeof(struct sidelink_ctrl_element));
   free(sl_ctrl_msg_send);

   prose_addr_len = sizeof(prose_app_addr);

   n = sendto(ctrl_sock_fd, (char *)send_buf, sizeof(struct sidelink_ctrl_element), 0, (struct sockaddr *)&prose_app_addr, prose_addr_len);
   if (n < 0){
      // TODO:  We should not just exit if the Prose App has not yet attached.  It creates a race condition.
      LOG_I(RRC, "ERROR: Failed to send to ProSe App\n");
      //exit(EXIT_FAILURE);
   }



  return(0);
}

#endif

//-----------------------------------------------------------------------------
RRC_status_t
rrc_rx_tx_ue(
  protocol_ctxt_t* const ctxt_pP,
  const uint8_t      enb_indexP,
  const int          CC_id
)
//-----------------------------------------------------------------------------
{

#ifdef LOCALIZATION
  double                         estimated_distance;
  protocol_ctxt_t                ctxt;
#endif
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);

    // check timers

    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)
        LOG_D(RRC,
              "[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);

      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;
        // ALLOW CCCH to be used
        UE_rrc_inst[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
        rrc_ue_generate_RRCConnectionRequest (ctxt_pP, enb_indexP);
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
        return (RRC_ConnSetup_failed);
      }

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

    if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
      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]) {
	LOG_I(RRC,"Activating T310\n");
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
      }
    } else { // in case we have not received SIB2 yet
      /*      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;

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

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

      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);
      }

      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);
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n"); 
        return RRC_PHY_RESYNCH;
      }

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

    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);

      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;
        LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n",
              ctxt_pP->module_id);
        //Implement 36.331, section 5.3.5.6 here
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
        return(RRC_Handover_failed);
      }

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

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

    ue_measurement_report_triggering(ctxt_pP,enb_indexP);

    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);
    }

    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;
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
      return(RRC_HO_STARTED);
    }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
  return (RRC_OK);
}

