/*******************************************************************************
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE

*******************************************************************************/
/*! \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

#include "assertions.h"
#include "asn1_conversions.h"
#include "defs.h"
#include "PHY/TOOLS/dB_routines.h"
#include "extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "LAYER2/RLC/rlc.h"
#include "COMMON/mac_rrc_primitives.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#ifndef CELLULAR
#include "RRC/LITE/MESSAGES/asn1_msg.h"
#endif
#include "RRCConnectionRequest.h"
#include "RRCConnectionReconfiguration.h"
#include "UL-CCCH-Message.h"
#include "DL-CCCH-Message.h"
#include "UL-DCCH-Message.h"
#include "DL-DCCH-Message.h"
#include "BCCH-DL-SCH-Message.h"
#ifdef Rel10
#include "MCCH-Message.h"
#endif
#include "MeasConfig.h"
#include "MeasGapConfig.h"
#include "MeasObjectEUTRA.h"
#include "TDD-Config.h"
#include "UECapabilityEnquiry.h"
#include "UE-CapabilityRequest.h"
#ifdef PHY_ABSTRACTION
#include "OCG.h"
#include "OCG_extern.h"
#endif
#ifdef USER_MODE
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#endif
#ifdef ENABLE_RAL
#include "rrc_UE_ral.h"
#endif

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

#include "pdcp.h"

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

#ifdef PHY_EMUL
extern EMULATION_VARS *Emul_vars;
#endif
extern eNB_MAC_INST *eNB_mac_inst;
extern UE_MAC_INST *UE_mac_inst;
#ifdef BIGPHYSAREA
extern void *bigphys_malloc(int);
#endif

//#define XER_PRINT

extern inline unsigned int taus(void);
extern int8_t dB_fixed2(uint32_t x,uint32_t y);

/*------------------------------------------------------------------------------*/
static Rrc_State_t rrc_get_state (module_id_t ue_mod_idP) {
  return UE_rrc_inst[ue_mod_idP].RrcState;
}

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, NB_eNB_INST + 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) || defined(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, NB_eNB_INST + ue_mod_idP, msg_p);
      }
#endif
      return (1);
  }

  return (0);
}

/*------------------------------------------------------------------------------*/
void init_SI_UE(module_id_t ue_mod_idP,uint8_t eNB_index) {

  int i;


  UE_rrc_inst[ue_mod_idP].sizeof_SIB1[eNB_index] = 0;
  UE_rrc_inst[ue_mod_idP].sizeof_SI[eNB_index] = 0;

  UE_rrc_inst[ue_mod_idP].SIB1[eNB_index] = (uint8_t *)malloc16(32);
  UE_rrc_inst[ue_mod_idP].sib1[eNB_index] = (SystemInformationBlockType1_t *)malloc16(sizeof(SystemInformationBlockType1_t));
  UE_rrc_inst[ue_mod_idP].SI[eNB_index] = (uint8_t *)malloc16(64);

  for (i=0;i<NB_CNX_UE;i++) {
      UE_rrc_inst[ue_mod_idP].si[eNB_index][i] = (SystemInformation_t *)malloc16(sizeof(SystemInformation_t));
  }

  UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1Status = 0;
  UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus = 0;
}

#ifdef Rel10
void init_MCCH_UE(module_id_t ue_mod_idP, uint8_t eNB_index) {
  int i;
  UE_rrc_inst[ue_mod_idP].sizeof_MCCH_MESSAGE[eNB_index] = 0;
  UE_rrc_inst[ue_mod_idP].MCCH_MESSAGE[eNB_index] = (uint8_t *)malloc16(32);
  UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index] = (MBSFNAreaConfiguration_r9_t *)malloc16(sizeof(MBSFNAreaConfiguration_r9_t));
  for (i=0; i<8;i++) // MAX MBSFN Area
    UE_rrc_inst[ue_mod_idP].Info[eNB_index].MCCHStatus[i] = 0;

}
#endif

static
void openair_rrc_lite_ue_init_security(module_id_t ue_mod_idP)
{
#if defined(ENABLE_SECURITY)
  //    uint8_t *kRRCenc;
  //    uint8_t *kRRCint;
  char ascii_buffer[65];
  uint8_t i;

  memset(UE_rrc_inst[ue_mod_idP].kenb, ue_mod_idP, 32);

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

  LOG_T(RRC, "[OSA][UE %02d] kenb    = %s\n", ue_mod_idP, ascii_buffer);
#endif
}

/*------------------------------------------------------------------------------*/
char openair_rrc_lite_ue_init(module_id_t ue_mod_idP, unsigned char eNB_index){
  /*-----------------------------------------------------------------------------*/
  rrc_set_state (ue_mod_idP, RRC_STATE_INACTIVE);
  rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_INACTIVE);

  LOG_D(RRC,"[UE %d] INIT State = RRC_IDLE (eNB %d)\n",ue_mod_idP,eNB_index);
  LOG_D(RRC,"[MSC_NEW][FRAME 00000][RRC_UE][MOD %02d][]\n", ue_mod_idP+NB_eNB_INST);
  LOG_D(RRC, "[MSC_NEW][FRAME 00000][IP][MOD %02d][]\n", ue_mod_idP+NB_eNB_INST);

  UE_rrc_inst[ue_mod_idP].Info[eNB_index].State=RRC_IDLE;
  UE_rrc_inst[ue_mod_idP].Info[eNB_index].T300_active = 0;
  UE_rrc_inst[ue_mod_idP].Info[eNB_index].T304_active = 0;
  UE_rrc_inst[ue_mod_idP].Info[eNB_index].T310_active = 0;
  UE_rrc_inst[ue_mod_idP].Info[eNB_index].UE_index=0xffff;
  UE_rrc_inst[ue_mod_idP].Srb0[eNB_index].Active=0;
  UE_rrc_inst[ue_mod_idP].Srb1[eNB_index].Active=0;
  UE_rrc_inst[ue_mod_idP].Srb2[eNB_index].Active=0;
  UE_rrc_inst[ue_mod_idP].HandoverInfoUe.measFlag=1;

  UE_rrc_inst[ue_mod_idP].ciphering_algorithm = SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
#ifdef Rel10
  UE_rrc_inst[ue_mod_idP].integrity_algorithm = SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920;
#else
  UE_rrc_inst[ue_mod_idP].integrity_algorithm = SecurityAlgorithmConfig__integrityProtAlgorithm_reserved;
#endif

  openair_rrc_lite_ue_init_security(ue_mod_idP);

  init_SI_UE(ue_mod_idP,eNB_index);
  LOG_D(RRC,"[UE %d] INIT: phy_sync_2_ch_ind\n", ue_mod_idP);

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

#ifdef NO_RRM //init ch SRB0, SRB1 & BDTCH
  openair_rrc_on(ue_mod_idP,0);
#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(module_id_t ue_mod_idP, frame_t frameP, uint8_t eNB_index){
  /*------------------------------------------------------------------------------*/

  uint8_t i=0,rv[6];

  if(UE_rrc_inst[ue_mod_idP].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[ue_mod_idP].Srb0[eNB_index].Tx_buffer.payload_size = do_RRCConnectionRequest(ue_mod_idP, (uint8_t *)UE_rrc_inst[ue_mod_idP].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",
          ue_mod_idP, frameP, UE_rrc_inst[ue_mod_idP].Srb0[eNB_index].Tx_buffer.payload_size, eNB_index);

      for (i=0;i<UE_rrc_inst[ue_mod_idP].Srb0[eNB_index].Tx_buffer.payload_size;i++) {
          LOG_T(RRC,"%x.",UE_rrc_inst[ue_mod_idP].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;

/* 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,
    };

/* NAS Attach request with GUTI */
static const char const nas_attach_req_guti[] =
    {
        0x07, 0x41,
        /* EPS Mobile identity = GUTI */
        0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00,
        0xDA, 0x1F,
        /* 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,
    };

/*------------------------------------------------------------------------------*/
void rrc_ue_generate_RRCConnectionSetupComplete(module_id_t ue_mod_idP, frame_t frameP, uint8_t eNB_index, 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[ue_mod_idP].initialNasMsg.data;
  nas_msg_length  = UE_rrc_inst[ue_mod_idP].initialNasMsg.length;
#else
  nas_msg         = nas_attach_req_imsi;
  nas_msg_length  = sizeof(nas_attach_req_imsi);
#endif

  size = do_RRCConnectionSetupComplete(ue_mod_idP, 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",
      ue_mod_idP,frameP, size, eNB_index);

  LOG_D(RLC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCConnectionSetupComplete to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
      frameP, ue_mod_idP+NB_eNB_INST, size, eNB_index, rrc_mui, ue_mod_idP+NB_eNB_INST, DCCH);

  //  rrc_rlc_data_req(ue_mod_idP+NB_eNB_INST,frameP, 0 ,DCCH,rrc_mui++,0,size,(char*)buffer);
  pdcp_rrc_data_req (eNB_index, ue_mod_idP, frameP, 0, DCCH, rrc_mui++, 0, size, buffer, 1);
}

void rrc_ue_generate_RRCConnectionReconfigurationComplete(module_id_t ue_mod_idP, frame_t frameP, uint8_t eNB_index, uint8_t Transaction_id) {

  uint8_t buffer[32], size;

  size = do_RRCConnectionReconfigurationComplete(ue_mod_idP, buffer, Transaction_id);

  LOG_I(RRC,"[UE %d] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionReconfigurationComplete (bytes %d, eNB_index %d)\n",
      ue_mod_idP,frameP, size, eNB_index);
  LOG_D(RLC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- PDCP_DATA_REQ/%d Bytes (RRCConnectionReconfigurationComplete to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
      frameP, ue_mod_idP+NB_eNB_INST, size, eNB_index, rrc_mui, ue_mod_idP+NB_eNB_INST, DCCH);

  //rrc_rlc_data_req(ue_mod_idP+NB_eNB_INST,frameP, 0 ,DCCH,rrc_mui++,0,size,(char*)buffer);
  pdcp_rrc_data_req (eNB_index, ue_mod_idP, frameP, 0, DCCH, rrc_mui++, 0, size, buffer, 1);
}

/*------------------------------------------------------------------------------*/
int rrc_ue_decode_ccch(module_id_t ue_mod_idP, frame_t frameP, SRB_INFO *Srb_info, uint8_t eNB_index){
  /*------------------------------------------------------------------------------*/

  //DL_CCCH_Message_t dlccchmsg;
  DL_CCCH_Message_t *dl_ccch_msg=NULL;//&dlccchmsg;
  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);

  //memset(dl_ccch_msg,0,sizeof(DL_CCCH_Message_t));

  //  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_DL_CCCH_Message,
      (void**)&dl_ccch_msg,
      (uint8_t*)Srb_info->Rx_buffer.Payload,
      100,0,0);

#ifdef XER_PRINT
  xer_fprint(stdout,&asn_DEF_DL_CCCH_Message,(void*)dl_ccch_msg);
#endif

#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, ue_mod_idP + NB_eNB_INST, 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_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, ue_mod_idP + NB_eNB_INST, 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 (%d bytes)\n",ue_mod_idP,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 == DL_CCCH_MessageType_PR_c1) {

      if (UE_rrc_inst[ue_mod_idP].Info[eNB_index].State == RRC_SI_RECEIVED) {

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

          case DL_CCCH_MessageType__c1_PR_NOTHING:
            LOG_I(RRC, "[UE%d] Frame %d : Received PR_NOTHING on DL-CCCH-Message\n", ue_mod_idP, frameP);
            rval = 0;
            break;

          case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishment:
            LOG_D(RRC,
                "[MSC_MSG][FRAME %05d][MAC_UE][MOD %02d][][--- MAC_DATA_IND (rrcConnectionReestablishment ENB %d) --->][RRC_UE][MOD %02d][]\n", frameP, ue_mod_idP+NB_eNB_INST, eNB_index, ue_mod_idP+NB_eNB_INST);

            LOG_I(RRC,
                "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishment\n", ue_mod_idP, frameP);
            rval = 0;
            break;

          case DL_CCCH_MessageType__c1_PR_rrcConnectionReestablishmentReject:
            LOG_D(RRC,
                "[MSC_MSG][FRAME %05d][MAC_UE][MOD %02d][][--- MAC_DATA_IND (RRCConnectionReestablishmentReject ENB %d) --->][RRC_UE][MOD %02d][]\n", frameP, ue_mod_idP+NB_eNB_INST, eNB_index, ue_mod_idP+NB_eNB_INST);
            LOG_I(RRC,
                "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReestablishmentReject\n", ue_mod_idP, frameP);
            rval = 0;
            break;

          case DL_CCCH_MessageType__c1_PR_rrcConnectionReject:
            LOG_D(RRC,
                "[MSC_MSG][FRAME %05d][MAC_UE][MOD %02d][][--- MAC_DATA_IND (rrcConnectionReject ENB %d) --->][RRC_UE][MOD %02d][]\n", frameP, ue_mod_idP+NB_eNB_INST, eNB_index, ue_mod_idP+NB_eNB_INST);

            LOG_I(RRC,
                "[UE%d] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionReject \n", ue_mod_idP, frameP);
            rval = 0;
            break;

          case DL_CCCH_MessageType__c1_PR_rrcConnectionSetup:
            LOG_D(RRC,
                "[MSC_MSG][FRAME %05d][MAC_UE][MOD %02d][][--- MAC_DATA_IND (rrcConnectionSetup ENB %d) --->][RRC_UE][MOD %02d][]\n", frameP, ue_mod_idP+NB_eNB_INST, eNB_index, ue_mod_idP+NB_eNB_INST);

            LOG_I(RRC,
                "[UE%d][RAPROC] Frame %d : Logical Channel DL-CCCH (SRB0), Received RRCConnectionSetup \n", ue_mod_idP, frameP);
            // Get configuration

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

            rrc_set_state (ue_mod_idP, RRC_STATE_CONNECTED);
            rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_CONNECTED);
            rrc_ue_generate_RRCConnectionSetupComplete(ue_mod_idP, frameP, 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", ue_mod_idP, frameP);
            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 SRB_ToAddMod *SRB_config) {
  // add descriptor from RRC PDU

  uint8_t lchan_id = DCCH;

  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,lchan_id,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 SRB_ToAddMod *SRB_config) {
  // add descriptor from RRC PDU

  uint8_t lchan_id = DCCH1;

  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,lchan_id,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 DRB_ToAddMod *DRB_config) { // add descriptor from RRC PDU
#ifdef NAS_NETLINK
  int oip_ifup=0,ip_addr_offset3=0,ip_addr_offset4=0;
#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 NAS_NETLINK
#    ifdef OAI_EMU
  ip_addr_offset3 = oai_emulation.info.nb_enb_local;
  ip_addr_offset4 = NB_eNB_INST;
#    else
  ip_addr_offset3 = 0;
  ip_addr_offset4 = 8;
#    endif
#    if !defined(OAI_NW_DRIVER_TYPE_ETHERNET) && !defined(EXMIMO)
  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
#        ifdef OAI_EMU
      oai_emulation.info.oai_ifup[ue_mod_idP]=1;
#        endif
      LOG_I(OIP,"[UE %d] Config the oai%d to send/receive pkt on DRB %d to/from the protocol stack\n",
          ue_mod_idP,
          ip_addr_offset3+ue_mod_idP,
          (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);
  }
#    else
#        ifdef OAI_EMU
  oai_emulation.info.oai_ifup[ue_mod_idP]=1;
#        endif
#    endif
#endif

  return(0);
}


void  rrc_ue_process_measConfig(module_id_t ue_mod_idP, frame_t frameP, uint8_t eNB_index,MeasConfig_t *measConfig){

  // This is the procedure described in 36.331 Section 5.5.2.1
  int i;
  long ind;
  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[ue_mod_idP].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[ue_mod_idP].MeasObj[eNB_index][ind-1]) {
              LOG_D(RRC,"Modifying measurement object %d\n",ind);
              memcpy((char*)UE_rrc_inst[ue_mod_idP].MeasObj[eNB_index][ind-1],
                  (char*)measObj,
                  sizeof(MeasObjectToAddMod_t));
          }
          else {
              LOG_I(RRC,"Adding measurement object %d\n",ind);
              if (measObj->measObject.present == MeasObjectToAddMod__measObject_PR_measObjectEUTRA) {
                  LOG_I(RRC,"EUTRA Measurement : carrierFreq %d, allowedMeasBandwidth %d,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[ue_mod_idP].MeasObj[eNB_index][ind-1]=measObj;
              }
          }
      }
      rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
          (RadioResourceConfigCommonSIB_t *)NULL,
          (struct PhysicalConfigDedicated *)NULL,
#ifdef Rel10
			 (SCellToAddMod_r10_t *)NULL,
	  //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
          UE_rrc_inst[ue_mod_idP].MeasObj[eNB_index],
          (MAC_MainConfig_t *)NULL,
          0,
          (struct LogicalChannelConfig *)NULL,
          (MeasGapConfig_t *)NULL,
          (TDD_Config_t *)NULL,
          (MobilityControlInfo_t *)NULL,
          NULL,
          NULL,
          NULL,
          NULL,
          NULL,
          NULL
#ifdef Rel10
          ,
          0,
          (MBSFN_AreaInfoList_r9_t *)NULL,
          (PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
          ,
          0,
          0
#endif
      );
  }
  if (measConfig->reportConfigToRemoveList != NULL) {
      for (i=0;i<measConfig->reportConfigToRemoveList->list.count;i++) {
          ind   = *measConfig->reportConfigToRemoveList->list.array[i];
          free(UE_rrc_inst[ue_mod_idP].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[ue_mod_idP].ReportConfig[eNB_index][ind-1]) {
              LOG_I(RRC,"Modifying Report Configuration %d\n",ind-1);
              memcpy((char*)UE_rrc_inst[ue_mod_idP].ReportConfig[eNB_index][ind-1],
                  (char*)measConfig->reportConfigToAddModList->list.array[i],
                  sizeof(ReportConfigToAddMod_t));
          }
          else {
              LOG_D(RRC,"Adding Report Configuration %d %p \n",ind-1,measConfig->reportConfigToAddModList->list.array[i]);
              UE_rrc_inst[ue_mod_idP].ReportConfig[eNB_index][ind-1] = measConfig->reportConfigToAddModList->list.array[i];
          }
      }
  }

  if (measConfig->quantityConfig != NULL) {
      if (UE_rrc_inst[ue_mod_idP].QuantityConfig[eNB_index]) {
          LOG_D(RRC,"Modifying Quantity Configuration \n");
          memcpy((char*)UE_rrc_inst[ue_mod_idP].QuantityConfig[eNB_index],
              (char*)measConfig->quantityConfig,
              sizeof(QuantityConfig_t));
      }
      else {
          LOG_D(RRC,"Adding Quantity configuration\n");
          UE_rrc_inst[ue_mod_idP].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[ue_mod_idP].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[ue_mod_idP].MeasId[eNB_index][ind-1]) {
              LOG_D(RRC,"Modifying Measurement ID %d\n",ind-1);
              memcpy((char*)UE_rrc_inst[ue_mod_idP].MeasId[eNB_index][ind-1],
                  (char*)measConfig->measIdToAddModList->list.array[i],
                  sizeof(MeasIdToAddMod_t));
          }
          else {
              LOG_D(RRC,"Adding Measurement ID %d %p\n",ind-1,measConfig->measIdToAddModList->list.array[i]);
              UE_rrc_inst[ue_mod_idP].MeasId[eNB_index][ind-1] = measConfig->measIdToAddModList->list.array[i];
          }
      }
  }

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

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

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

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

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

  if (measConfig->speedStatePars != NULL) {
      if (UE_rrc_inst[ue_mod_idP].speedStatePars)
        memcpy((char*)UE_rrc_inst[ue_mod_idP].speedStatePars,(char*)measConfig->speedStatePars,sizeof(struct MeasConfig__speedStatePars));
      else
        UE_rrc_inst[ue_mod_idP].speedStatePars = measConfig->speedStatePars;
      LOG_I(RRC,"[UE %d] Configuring mobility optimization params for UE %d \n",
          ue_mod_idP,UE_rrc_inst[ue_mod_idP].Info[0].UE_index);
  }
}

void    
rrc_ue_process_radioResourceConfigDedicated(module_id_t ue_mod_idP, frame_t frameP, uint8_t eNB_index,
    RadioResourceConfigDedicated_t *radioResourceConfigDedicated) {

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

  // Save physicalConfigDedicated if present
  if (radioResourceConfigDedicated->physicalConfigDedicated) {
      if (UE_rrc_inst[ue_mod_idP].physicalConfigDedicated[eNB_index]) {
          memcpy((char*)UE_rrc_inst[ue_mod_idP].physicalConfigDedicated[eNB_index],(char*)radioResourceConfigDedicated->physicalConfigDedicated,
              sizeof(struct PhysicalConfigDedicated));

      }
      else {
          UE_rrc_inst[ue_mod_idP].physicalConfigDedicated[eNB_index] = radioResourceConfigDedicated->physicalConfigDedicated;
      }
  }
  // Apply macMainConfig if present
  if (radioResourceConfigDedicated->mac_MainConfig) {
      if (radioResourceConfigDedicated->mac_MainConfig->present == RadioResourceConfigDedicated__mac_MainConfig_PR_explicitValue) {
          if (UE_rrc_inst[ue_mod_idP].mac_MainConfig[eNB_index]) {
              memcpy((char*)UE_rrc_inst[ue_mod_idP].mac_MainConfig[eNB_index],(char*)&radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue,
                  sizeof(MAC_MainConfig_t));
          }
          else
            UE_rrc_inst[ue_mod_idP].mac_MainConfig[eNB_index] = &radioResourceConfigDedicated->mac_MainConfig->choice.explicitValue;
      }
  }

  // Apply spsConfig if present
  if (radioResourceConfigDedicated->sps_Config) {
      if (UE_rrc_inst[ue_mod_idP].sps_Config[eNB_index]) {
          memcpy(UE_rrc_inst[ue_mod_idP].sps_Config[eNB_index],radioResourceConfigDedicated->sps_Config,
              sizeof(struct SPS_Config));
      }
      else {
          UE_rrc_inst[ue_mod_idP].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[ue_mod_idP].cba_rnti[i] == cba_RNTI ) {
              cba_found=1;
              break;
          } else if (UE_rrc_inst[ue_mod_idP].cba_rnti[i] == 0 )
            break;
      }
      if (cba_found==0) {
          UE_rrc_inst[ue_mod_idP].num_active_cba_groups++;
          UE_rrc_inst[ue_mod_idP].cba_rnti[i]=cba_RNTI;
          LOG_D(RRC, "[UE %d] Frame %d: radioResourceConfigDedicated reveived CBA_RNTI = %x for group %d from eNB %d \n",
              ue_mod_idP,frameP, UE_rrc_inst[ue_mod_idP].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[ue_mod_idP].ciphering_algorithm,
          UE_rrc_inst[ue_mod_idP].kenb, &kRRCenc);
      derive_key_rrc_int(UE_rrc_inst[ue_mod_idP].integrity_algorithm,
          UE_rrc_inst[ue_mod_idP].kenb, &kRRCint);
#endif

      ctxt.enb_module_id = eNB_index;
      ctxt.ue_module_id  = ue_mod_idP;
      ctxt.frame         = frameP;
      ctxt.enb_flag      = ENB_FLAG_NO;
      // Refresh SRBs
      rrc_pdcp_config_asn1_req(&ctxt,
          radioResourceConfigDedicated->srb_ToAddModList,
          (DRB_ToAddModList_t*)NULL,
          (DRB_ToReleaseList_t*)NULL,
          UE_rrc_inst[ue_mod_idP].ciphering_algorithm |
          (UE_rrc_inst[ue_mod_idP].integrity_algorithm << 4),
          kRRCenc,
          kRRCint,
          NULL
#ifdef Rel10
,(PMCH_InfoList_r9_t *)NULL
#endif
      );

      // Refresh SRBs
      rrc_rlc_config_asn1_req(&ctxt,
          radioResourceConfigDedicated->srb_ToAddModList,
          (DRB_ToAddModList_t*)NULL,
          (DRB_ToReleaseList_t*)NULL
#ifdef Rel10
          ,(PMCH_InfoList_r9_t *)NULL
#endif
      );

#ifdef ENABLE_RAL
	// first msg that includes srb config	
	UE_rrc_inst[ue_mod_idP].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",ue_mod_idP,frameP,cnt,SRB_id);
          if (SRB_id == 1) {
              if (UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index]) {
                  memcpy(UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index],radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt],
                      sizeof(struct SRB_ToAddMod));
              }
              else {
                  UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index] = radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt];

                  rrc_ue_establish_srb1(ue_mod_idP,frameP,eNB_index,radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt]);
                  if (UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index]->logicalChannelConfig) {
                      if (UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index]->logicalChannelConfig->present == SRB_ToAddMod__logicalChannelConfig_PR_explicitValue) {
                          SRB1_logicalChannelConfig = &UE_rrc_inst[ue_mod_idP].SRB1_config[eNB_index]->logicalChannelConfig->choice.explicitValue;
                      }
                      else {
                          SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
                      }
                  }
                  else {
                      SRB1_logicalChannelConfig = &SRB1_logicalChannelConfig_defaultValue;
                  }

                  LOG_D(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                      frameP, ue_mod_idP, eNB_index, ue_mod_idP);
                  rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
                      (RadioResourceConfigCommonSIB_t *)NULL,
                      UE_rrc_inst[ue_mod_idP].physicalConfigDedicated[eNB_index],
#ifdef Rel10
				     (SCellToAddMod_r10_t *)NULL,
		       //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
                      (MeasObjectToAddMod_t **)NULL,
                      UE_rrc_inst[ue_mod_idP].mac_MainConfig[eNB_index],
                      1,
                      SRB1_logicalChannelConfig,
                      (MeasGapConfig_t *)NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL
#ifdef Rel10	       
                      ,
                      0,
                      (MBSFN_AreaInfoList_r9_t *)NULL,
                      (PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
                      ,
                      0,
                      0
#endif
                  );
              }
          }
          else {
              if (UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index]) {
                  memcpy(UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index],radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt],
                      sizeof(struct SRB_ToAddMod));
              }
              else {

                  UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index] = radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt];

                  rrc_ue_establish_srb2(ue_mod_idP,frameP,eNB_index,radioResourceConfigDedicated->srb_ToAddModList->list.array[cnt]);
                  if (UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index]->logicalChannelConfig) {
                      if (UE_rrc_inst[ue_mod_idP].SRB2_config[eNB_index]->logicalChannelConfig->present == SRB_ToAddMod__logicalChannelConfig_PR_explicitValue){
                          LOG_I(RRC,"Applying Explicit SRB2 logicalChannelConfig\n");
                          SRB2_logicalChannelConfig = &UE_rrc_inst[ue_mod_idP].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_D(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                      frameP, ue_mod_idP, eNB_index, ue_mod_idP);
                  rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
                      (RadioResourceConfigCommonSIB_t *)NULL,
                      UE_rrc_inst[ue_mod_idP].physicalConfigDedicated[eNB_index],
#ifdef Rel10
				     (SCellToAddMod_r10_t *)NULL,
		       //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
                      (MeasObjectToAddMod_t **)NULL,
                      UE_rrc_inst[ue_mod_idP].mac_MainConfig[eNB_index],
                      2,
                      SRB2_logicalChannelConfig,
                      UE_rrc_inst[ue_mod_idP].measGapConfig[eNB_index],
                      (TDD_Config_t *)NULL,
                      (MobilityControlInfo_t *)NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL,
                      NULL
#ifdef Rel10
,
0,
(MBSFN_AreaInfoList_r9_t *)NULL,
(PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
,
0,
0
#endif
                  );
              }
          }
      }
  }

  // Establish DRBs if present
  if (radioResourceConfigDedicated->drb_ToAddModList) {
      uint8_t *kUPenc = NULL;

#if defined(ENABLE_SECURITY)
      derive_key_up_enc(UE_rrc_inst[ue_mod_idP].integrity_algorithm,
          UE_rrc_inst[ue_mod_idP].kenb, &kUPenc);
#endif

      ctxt.enb_module_id = eNB_index;
      ctxt.ue_module_id  = ue_mod_idP;
      ctxt.frame         = frameP;
      ctxt.enb_flag      = ENB_FLAG_NO;
      // Refresh DRBs
      rrc_pdcp_config_asn1_req(&ctxt,
          (SRB_ToAddModList_t*)NULL,
          radioResourceConfigDedicated->drb_ToAddModList,
          (DRB_ToReleaseList_t*)NULL,
          UE_rrc_inst[ue_mod_idP].ciphering_algorithm |
          (UE_rrc_inst[ue_mod_idP].integrity_algorithm << 4),
          NULL,
          NULL,
          kUPenc
#ifdef Rel10
,(PMCH_InfoList_r9_t *)NULL
#endif
      );

      // Refresh DRBs
      rrc_rlc_config_asn1_req(&ctxt,
          (SRB_ToAddModList_t*)NULL,
          radioResourceConfigDedicated->drb_ToAddModList,
          (DRB_ToReleaseList_t*)NULL
#ifdef Rel10
          ,(PMCH_InfoList_r9_t *)NULL
#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[ue_mod_idP].DRB_config[eNB_index][DRB_id]) {
              memcpy(UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][DRB_id],radioResourceConfigDedicated->drb_ToAddModList->list.array[i],
                  sizeof(struct DRB_ToAddMod));
          }
          else {
              UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][DRB_id] = radioResourceConfigDedicated->drb_ToAddModList->list.array[i];

              rrc_ue_establish_drb(ue_mod_idP,frameP,eNB_index,radioResourceConfigDedicated->drb_ToAddModList->list.array[i]);
              // MAC/PHY Configuration
              LOG_D(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (DRB %d eNB %d) --->][MAC_UE][MOD %02d][]\n",
                  frameP, ue_mod_idP, radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity, eNB_index, ue_mod_idP);
              rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
                  (RadioResourceConfigCommonSIB_t *)NULL,
                  UE_rrc_inst[ue_mod_idP].physicalConfigDedicated[eNB_index],
#ifdef Rel10
				 (SCellToAddMod_r10_t *)NULL,
		       //struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10,
#endif
                  (MeasObjectToAddMod_t **)NULL,
                  UE_rrc_inst[ue_mod_idP].mac_MainConfig[eNB_index],
                  *UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][DRB_id]->logicalChannelIdentity,
                  UE_rrc_inst[ue_mod_idP].DRB_config[eNB_index][DRB_id]->logicalChannelConfig,
                  UE_rrc_inst[ue_mod_idP].measGapConfig[eNB_index],
                  (TDD_Config_t*)NULL,
                  (MobilityControlInfo_t *)NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  NULL
#ifdef Rel10
,
0,
(MBSFN_AreaInfoList_r9_t *)NULL,
(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
              );

          }
      }
  }

  UE_rrc_inst[ue_mod_idP].Info[eNB_index].State = RRC_CONNECTED;
  LOG_I(RRC,"[UE %d] State = RRC_CONNECTED (eNB %d)\n",ue_mod_idP,eNB_index);


}

void rrc_ue_process_securityModeCommand(uint8_t ue_mod_idP, frame_t frameP,SecurityModeCommand_t *securityModeCommand,uint8_t eNB_index) {

  asn_enc_rval_t enc_rval;

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

  LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing securityModeCommand (eNB %d)\n",
      ue_mod_idP,frameP,eNB_index);

  switch (securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm){
  case SecurityAlgorithmConfig__cipheringAlgorithm_eea0:
    LOG_I(RRC,"[UE %d] Security algorithm is set to eea0\n",ue_mod_idP);
    securityMode= SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
    break;
  case SecurityAlgorithmConfig__cipheringAlgorithm_eea1:
    LOG_I(RRC,"[UE %d] Security algorithm is set to eea1\n",ue_mod_idP);
    securityMode= SecurityAlgorithmConfig__cipheringAlgorithm_eea1;
    break;
  case SecurityAlgorithmConfig__cipheringAlgorithm_eea2:
    LOG_I(RRC,"[UE %d] Security algorithm is set to eea2\n",ue_mod_idP);
    securityMode = SecurityAlgorithmConfig__cipheringAlgorithm_eea2;
    break;
  default:
    LOG_I(RRC,"[UE %d] Security algorithm is set to none\n",ue_mod_idP);
    securityMode = SecurityAlgorithmConfig__cipheringAlgorithm_spare1;
    break;
  }
  switch (securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm){
  case SecurityAlgorithmConfig__integrityProtAlgorithm_eia1:
    LOG_I(RRC,"[UE %d] Integrity protection algorithm is set to eia1\n",ue_mod_idP);
    securityMode |= 1 << 5;
    break;
  case SecurityAlgorithmConfig__integrityProtAlgorithm_eia2:
    LOG_I(RRC,"[UE %d] Integrity protection algorithm is set to eia2\n",ue_mod_idP);
    securityMode |= 1 << 6;
    break;
  default:
    LOG_I(RRC,"[UE %d] Integrity protection algorithm is set to none\n",ue_mod_idP);
    securityMode |= 0x70 ;
    break;
  }
  LOG_D(RRC,"[UE %d] security mode is %x \n",ue_mod_idP, securityMode);

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

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

  ul_dcch_msg.message.present           = UL_DCCH_MessageType_PR_c1;
  if (securityMode >= NO_SECURITY_MODE)
    ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeComplete;
  else 
    ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeFailure;

  if (securityModeCommand->criticalExtensions.present == SecurityModeCommand__criticalExtensions_PR_c1) {
      if (securityModeCommand->criticalExtensions.choice.c1.present == SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8) {

          ul_dcch_msg.message.choice.c1.choice.securityModeComplete.rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier;
          ul_dcch_msg.message.choice.c1.choice.securityModeComplete.criticalExtensions.present = SecurityModeCommand__criticalExtensions_PR_c1;
          ul_dcch_msg.message.choice.c1.choice.securityModeComplete.criticalExtensions.choice.securityModeComplete_r8.nonCriticalExtension =NULL;

          LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), encoding securityModeComplete (eNB %d)\n",
              ue_mod_idP,frameP,eNB_index);

          enc_rval = uper_encode_to_buffer(&asn_DEF_UL_DCCH_Message,
              (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);

#ifdef XER_PRINT
          xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
#endif	  

#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_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, NB_eNB_INST + ue_mod_idP, msg_p);
              }
          }
# endif
#endif

#ifdef USER_MODE
          LOG_D(RRC, "securityModeComplete Encoded %d bits (%d bytes)\n", enc_rval.encoded, (enc_rval.encoded+7)/8);
#endif
          for (i = 0; i < (enc_rval.encoded + 7) / 8; i++)
            LOG_T(RRC, "%02x.", buffer[i]);
          LOG_T(RRC, "\n");
          pdcp_rrc_data_req (eNB_index, ue_mod_idP, frameP, 0, DCCH, rrc_mui++, 0, (enc_rval.encoded + 7) / 8, buffer, 1);
      }
  }

}
void rrc_ue_process_ueCapabilityEnquiry(uint8_t ue_mod_idP, frame_t frameP,UECapabilityEnquiry_t *UECapabilityEnquiry,uint8_t eNB_index) {

  asn_enc_rval_t enc_rval;

  UL_DCCH_Message_t ul_dcch_msg;


  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",
      ue_mod_idP,frameP,eNB_index);


  memset((void *)&ul_dcch_msg,0,sizeof(UL_DCCH_Message_t));
  memset((void *)&ue_CapabilityRAT_Container,0,sizeof(UE_CapabilityRAT_Container_t));

  ul_dcch_msg.message.present           = UL_DCCH_MessageType_PR_c1;
  ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_ueCapabilityInformation;
  ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier;

  ue_CapabilityRAT_Container.rat_Type = RAT_Type_eutra;
  OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ueCapabilityRAT_Container,
      (const char*)UE_rrc_inst[ue_mod_idP].UECapability,
      UE_rrc_inst[ue_mod_idP].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;


  if (UECapabilityEnquiry->criticalExtensions.present == UECapabilityEnquiry__criticalExtensions_PR_c1) {
      if (UECapabilityEnquiry->criticalExtensions.choice.c1.present == UECapabilityEnquiry__criticalExtensions__c1_PR_ueCapabilityEnquiry_r8) {
          ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.present           = UECapabilityInformation__criticalExtensions_PR_c1;
          ul_dcch_msg.message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.choice.c1.present = 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]
                                                                                                                                   == 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_UL_DCCH_Message, (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);

#ifdef XER_PRINT
                  xer_fprint(stdout, &asn_DEF_UL_DCCH_Message, (void*)&ul_dcch_msg);
#endif

#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_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, NB_eNB_INST + ue_mod_idP, msg_p);
                      }
                  }
# endif
#endif

#ifdef USER_MODE
                  LOG_D(RRC,"UECapabilityInformation Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
#endif
                  for (i = 0; i < (enc_rval.encoded + 7) / 8; i++)
                    LOG_T(RRC, "%02x.", buffer[i]);
                  LOG_T(RRC, "\n");
                  pdcp_rrc_data_req (eNB_index, ue_mod_idP, frameP, 0, DCCH, rrc_mui++, 0, (enc_rval.encoded + 7) / 8, buffer, 1);
              }
          }
      }
  }
}


void rrc_ue_process_rrcConnectionReconfiguration(module_id_t ue_mod_idP, frame_t frameP,
    RRCConnectionReconfiguration_t *rrcConnectionReconfiguration,
    uint8_t eNB_index) {

  LOG_I(RRC,"[UE %d] Frame %d: Receiving from SRB1 (DL-DCCH), Processing RRCConnectionReconfiguration (eNB %d)\n",
      ue_mod_idP,frameP,eNB_index);
  if (rrcConnectionReconfiguration->criticalExtensions.present == RRCConnectionReconfiguration__criticalExtensions_PR_c1) {
      if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.present ==
          RRCConnectionReconfiguration__criticalExtensions__c1_PR_rrcConnectionReconfiguration_r8) {
          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(ue_mod_idP, eNB_index, frameP, rrcConnectionReconfiguration_r8->mobilityControlInfo);
          }
          if (rrcConnectionReconfiguration_r8->measConfig != NULL) {
              LOG_I(RRC,"Measurement Configuration is present\n");
              rrc_ue_process_measConfig(ue_mod_idP,frameP, eNB_index,
                  rrcConnectionReconfiguration_r8->measConfig);
          }
          if (rrcConnectionReconfiguration_r8->radioResourceConfigDedicated) {
              LOG_I(RRC,"Radio Resource Configuration is present\n");
              rrc_ue_process_radioResourceConfigDedicated(ue_mod_idP,frameP,eNB_index, rrcConnectionReconfiguration_r8->radioResourceConfigDedicated);
          }

#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, ue_mod_idP, msg_p);
              }

              free (rrcConnectionReconfiguration_r8->dedicatedInfoNASList);
          }
#ifdef 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            = ue_mod_idP;
            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[ue_mod_idP].num_srb;
		
            } else {
 	              connection_reestablishment_ind.num_srb      += UE_rrc_inst[ue_mod_idP].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, ue_mod_idP + NB_eNB_INST, 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(uint8_t eNB_index, uint8_t UE_id, frame_t frameP, struct MobilityControlInfo *mobilityControlInfo)
{
  module_id_t          ue_mod_idP = UE_id;
  protocol_ctxt_t      ctxt;
  /*
  DRB_ToReleaseList_t*  drb2release_list;
  DRB_Identity_t *lcid;
   */
  LOG_N(RRC,"Note: This function needs some updates\n");
  if(UE_rrc_inst[UE_id].Info[eNB_index].T310_active == 1)
    UE_rrc_inst[UE_id].Info[eNB_index].T310_active = 0;
  UE_rrc_inst[UE_id].Info[eNB_index].T304_active = 1;
  UE_rrc_inst[UE_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);
  }
   */

  ctxt.enb_module_id = eNB_index;
  ctxt.ue_module_id  = ue_mod_idP;
  ctxt.frame         = frameP;
  ctxt.enb_flag      = ENB_FLAG_NO;
  //Removing SRB1 and SRB2 and DRB0
  LOG_N(RRC,"[UE %d] : Update needed for rrc_pdcp_config_req (deprecated) and rrc_rlc_config_req commands(deprecated)\n", UE_id);
  rrc_pdcp_config_req (&ctxt, SRB_FLAG_YES, CONFIG_ACTION_REMOVE, DCCH,UNDEF_SECURITY_MODE);
  rrc_rlc_config_req(&ctxt, SRB_FLAG_YES, MBMS_FLAG_NO, CONFIG_ACTION_REMOVE,ue_mod_idP+DCCH,Rlc_info_am_config);

  rrc_pdcp_config_req (&ctxt, SRB_FLAG_YES, CONFIG_ACTION_REMOVE, DCCH1,UNDEF_SECURITY_MODE);
  rrc_rlc_config_req(&ctxt, SRB_FLAG_YES,CONFIG_ACTION_REMOVE, MBMS_FLAG_NO,ue_mod_idP+DCCH1,Rlc_info_am_config);

  rrc_pdcp_config_req (&ctxt, SRB_FLAG_NO, CONFIG_ACTION_REMOVE, DTCH,UNDEF_SECURITY_MODE);
  rrc_rlc_config_req(&ctxt, SRB_FLAG_NO,CONFIG_ACTION_REMOVE, MBMS_FLAG_NO,ue_mod_idP+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
#ifdef Rel10
			   ,NULL
#endif
			   );

  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
#ifdef Rel10
			  ,NULL
#endif 
			  );
   */


  //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_N(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_D(RRC,"HO: Reset PDCP and RLC for configured RBs.. \n[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB2 eNB %d) --->][MAC_UE][MOD %02d][]\n",
      frameP, ue_mod_idP, eNB_index, ue_mod_idP);

  // Reset MAC and configure PHY
  rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
      (RadioResourceConfigCommonSIB_t *)NULL,
      (struct PhysicalConfigDedicated *)NULL,
#ifdef Rel10
	(SCellToAddMod_r10_t *)NULL,
	//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
      (MeasObjectToAddMod_t **)NULL,
      (MAC_MainConfig_t *)NULL,
      0,
      (struct LogicalChannelConfig *)NULL,
      (MeasGapConfig_t *)NULL,
      (TDD_Config_t *)NULL,
      mobilityControlInfo,
      (uint8_t *)NULL,
      (uint16_t *)NULL,
      NULL,
      NULL,
      NULL,
      NULL
#ifdef Rel10
      ,0,
      (MBSFN_AreaInfoList_r9_t *)NULL,
      (PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
      ,0,
      0
#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[ue_mod_idP].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(module_id_t ue_mod_idP, frame_t frameP,uint8_t Srb_id, uint8_t *Buffer,uint8_t eNB_index){
  /*------------------------------------------------------------------------------------------*/

  //DL_DCCH_Message_t dldcchmsg;
  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",
          ue_mod_idP, frameP, 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_DL_DCCH_Message,
      (void**)&dl_dcch_msg,
      (uint8_t*)Buffer,
      RRC_BUF_SIZE,0,0);

#ifdef XER_PRINT
  xer_fprint(stdout,&asn_DEF_DL_DCCH_Message,(void*)dl_dcch_msg);
#endif

#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, ue_mod_idP + NB_eNB_INST, 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_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, ue_mod_idP + NB_eNB_INST, msg_p);
      }
  }
# endif
#endif

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

      if (UE_rrc_inst[ue_mod_idP].Info[eNB_index].State >= RRC_CONNECTED) {

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

          case DL_DCCH_MessageType__c1_PR_NOTHING:
            LOG_I(RRC, "[UE %d] Frame %d : Received PR_NOTHING on DL-DCCH-Message\n", ue_mod_idP, frameP);
            return;

          case DL_DCCH_MessageType__c1_PR_csfbParametersResponseCDMA2000:
            break;

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

            if ((dlInformationTransfer->criticalExtensions.present == DLInformationTransfer__criticalExtensions_PR_c1)
                && (dlInformationTransfer->criticalExtensions.choice.c1.present
                    == DLInformationTransfer__criticalExtensions__c1_PR_dlInformationTransfer_r8)
                    && (dlInformationTransfer->criticalExtensions.choice.c1.choice.dlInformationTransfer_r8.dedicatedInfoType.present
                        == DLInformationTransfer_r8_IEs__dedicatedInfoType_PR_dedicatedInfoNAS)) {
                /* This message hold a dedicated info NAS payload, forward it to NAS */
                struct 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 = ue_mod_idP; // 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, ue_mod_idP + NB_eNB_INST, msg_p);
            }
#endif
            break;
          }

          case DL_DCCH_MessageType__c1_PR_handoverFromEUTRAPreparationRequest:
            break;

          case DL_DCCH_MessageType__c1_PR_mobilityFromEUTRACommand:
            break;

          case 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[ue_mod_idP].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 (%d) is different from RSRP measured target (%d)..\n", ue_mod_idP, frameP, dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo->targetPhysCellId, UE_rrc_inst[ue_mod_idP].HandoverInfoUe.targetCellId);
                    return;
                }
                else
                  if ((target_eNB_index = get_adjacent_cell_mod_id(UE_rrc_inst[ue_mod_idP].HandoverInfoUe.targetCellId))
                      == 0xFF) {
                      LOG_W(RRC,
                          "[UE %d] Frame %d: ue_mod_idP of the target eNB not found, check the network topology\n", ue_mod_idP, frameP);
                      return;
                  }
                  else {
                      LOG_I(RRC,
                          "[UE% d] Frame %d: Received rrcConnectionReconfiguration with mobilityControlInfo \n", ue_mod_idP, frameP);
                      UE_rrc_inst[ue_mod_idP].HandoverInfoUe.measFlag = 1; // Ready to send more MeasReports if required
                  }
            }
            rrc_ue_process_rrcConnectionReconfiguration(ue_mod_idP, frameP,
                &dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration, eNB_index);
            if (target_eNB_index != 0xFF) {
                rrc_ue_generate_RRCConnectionReconfigurationComplete(ue_mod_idP, frameP, target_eNB_index,
                    dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.rrc_TransactionIdentifier);
                UE_rrc_inst[ue_mod_idP].Info[eNB_index].State = RRC_HO_EXECUTION;
                UE_rrc_inst[ue_mod_idP].Info[target_eNB_index].State = RRC_RECONFIGURED;
                LOG_I(RRC, "[UE %d] State = RRC_RECONFIGURED during HO (eNB %d)\n", ue_mod_idP, target_eNB_index);
#if defined(ENABLE_ITTI)
#ifdef 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 = ue_mod_idP;
                  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[ue_mod_idP].num_srb;
                  } else {
                      connection_reconfiguration_ho_ind.num_srb      += UE_rrc_inst[ue_mod_idP].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, ue_mod_idP + NB_eNB_INST, message_ral_p);
                }
#endif
#endif
            }
            else {
                rrc_ue_generate_RRCConnectionReconfigurationComplete(ue_mod_idP, frameP, eNB_index,
                    dl_dcch_msg->message.choice.c1.choice.rrcConnectionReconfiguration.rrc_TransactionIdentifier);
                UE_rrc_inst[ue_mod_idP].Info[eNB_index].State = RRC_RECONFIGURED;
                LOG_I(RRC, "[UE %d] State = RRC_RECONFIGURED (eNB %d)\n", ue_mod_idP, eNB_index);
#if defined(ENABLE_ITTI)
#ifdef 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 = ue_mod_idP;
                  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[ue_mod_idP].num_srb;
                  } else {
                      connection_reconfiguration_ind.num_srb      +=UE_rrc_inst[ue_mod_idP].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, ue_mod_idP + NB_eNB_INST, message_ral_p);
                }
#endif
#endif

            }
            break;

          case 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
                == RRCConnectionRelease__criticalExtensions_PR_c1)
                && (dl_dcch_msg->message.choice.c1.choice.rrcConnectionRelease.criticalExtensions.choice.c1.present
                    == 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, ue_mod_idP + NB_eNB_INST, msg_p);
#if defined(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 = ue_mod_idP;
            itti_send_msg_to_task(TASK_RAL_UE, ue_mod_idP + NB_eNB_INST, msg_p);
#endif
#endif
            break;

          case DL_DCCH_MessageType__c1_PR_securityModeCommand:
            LOG_I(RRC, "[UE %d] Received securityModeCommand (eNB %d)\n", ue_mod_idP, eNB_index);
            rrc_ue_process_securityModeCommand(ue_mod_idP, frameP, &dl_dcch_msg->message.choice.c1.choice.securityModeCommand,
                eNB_index);
            break;

          case DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry:
            LOG_I(RRC, "[UE %d] Received Capability Enquiry (eNB %d)\n", ue_mod_idP, eNB_index);
            rrc_ue_process_ueCapabilityEnquiry(ue_mod_idP, frameP, &dl_dcch_msg->message.choice.c1.choice.ueCapabilityEnquiry,
                eNB_index);
            break;

          case DL_DCCH_MessageType__c1_PR_counterCheck:
            break;

#ifdef Rel10
          case DL_DCCH_MessageType__c1_PR_ueInformationRequest_r9:
            break;
          case DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r10:
            break;
          case DL_DCCH_MessageType__c1_PR_rnReconfiguration_r10:
            break;
#endif

          case DL_DCCH_MessageType__c1_PR_spare1:
          case DL_DCCH_MessageType__c1_PR_spare2:
          case DL_DCCH_MessageType__c1_PR_spare3:
          case DL_DCCH_MessageType__c1_PR_spare4:
            break;

          default:
            break;
          }
      }
  }
#ifndef NO_RRM
  send_msg(&S_rrc,msg_rrc_end_scan_req(ue_mod_idP,eNB_index));
#endif
}

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

const char SIBType[16][6] ={"SIB3\0","SIB4\0","SIB5\0","SIB6\0","SIB7\0","SIB8\0","SIB9\0","SIB10\0","SIB11\0","SIB12\0","SIB13\0","Sp2\0","Sp3\0","Sp4\0"};
const char SIBPeriod[7][7]= {"80ms\0","160ms\0","320ms\0","640ms\0","1280ms\0","2560ms\0","5120ms\0"};
int siPeriod_int[7] = {80,160,320,640,1280,2560,5120};

int
decode_BCCH_DLSCH_Message(
                module_id_t ue_mod_idP,
                frame_t     frameP,
                uint8_t     eNB_index,
                uint8_t    *Sdu,
                uint8_t     Sdu_len,
                uint8_t     rsrq,
                uint8_t     rsrp
                )
{

  //BCCH_DL_SCH_Message_t bcch_message;
  BCCH_DL_SCH_Message_t *bcch_message=NULL;//_ptr=&bcch_message;
  SystemInformationBlockType1_t **sib1=&UE_rrc_inst[ue_mod_idP].sib1[eNB_index];
  SystemInformation_t **si=UE_rrc_inst[ue_mod_idP].si[eNB_index];
  asn_dec_rval_t dec_rval;
  uint32_t si_window;//, sib1_decoded=0, si_decoded=0;
  // int i;

  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN);


  if ((UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1Status == 1) &&
      (UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus == 1)) {
      // Avoid decoding to prevent memory bloating
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT);
      return 0;
  } 
  else {

      rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_IDLE_RECEIVING_SIB);

      //memset(&bcch_message,0,sizeof(BCCH_DL_SCH_Message_t));
      /*
      LOG_D(RRC,"[UE %d] Decoding DL_BCCH_DLSCH_Message\n",ue_mod_idP);
      int i;
      for (i=0;i<Sdu_len;i++)
	printf("%x.",Sdu[i]);
      printf("\n");
      */

      dec_rval = uper_decode_complete(NULL,
          &asn_DEF_BCCH_DL_SCH_Message,
          (void **)&bcch_message,
          (const void *)Sdu,
          Sdu_len);//,0,0);

      if ((dec_rval.code != RC_OK) && (dec_rval.consumed==0)) {
          LOG_E(RRC,"[UE %d] Failed to decode BCCH_DLSCH_MESSAGE (%d bits)\n",ue_mod_idP,dec_rval.consumed);
          //free the memory
          SEQUENCE_free(&asn_DEF_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;
      }
      //  xer_fprint(stdout,  &asn_DEF_BCCH_DL_SCH_Message, (void*)&bcch_message);

#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, ue_mod_idP + NB_eNB_INST, 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_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, ue_mod_idP + NB_eNB_INST, msg_p);
          }
      }
# endif
#endif

      if (bcch_message->message.present == BCCH_DL_SCH_MessageType_PR_c1) {
          switch (bcch_message->message.choice.c1.present) {
          case BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
            if ((frameP %2) == 0) {
                if (UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1Status == 0) {
                    memcpy((void*)*sib1,
                        (void*)&bcch_message->message.choice.c1.choice.systemInformationBlockType1,
                        sizeof(SystemInformationBlockType1_t));
                    LOG_D(RRC,"[UE %d] Decoding First SIB1\n",ue_mod_idP);
                    decode_SIB1(ue_mod_idP, eNB_index, rsrq, rsrp);
                    //mac_xface->macphy_exit("after decode_SIB1");
                }
            }
            break;

          case BCCH_DL_SCH_MessageType__c1_PR_systemInformation:
            if ((UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1Status == 1) &&
                (UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus == 0)) {
                //                                                if ((frameP %8) == 1) {  // check only in odd frames for SI
                si_window = (frameP%(UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIperiod/10))/(UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIwindowsize/10);
                memcpy((void*)si[si_window],
                    (void*)&bcch_message->message.choice.c1.choice.systemInformation,
                    sizeof(SystemInformation_t));
                LOG_D(RRC,"[UE %d] Decoding SI for frameP %d, si_window %d\n",ue_mod_idP,frameP,si_window);
                decode_SI(ue_mod_idP,frameP,eNB_index,si_window);
                //mac_xface->macphy_exit("after decode_SI");

                //                                }
            }
            break;

          case BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
          default:
            break;
          }
      }
  }

  if ((rrc_get_sub_state(ue_mod_idP) == RRC_SUB_STATE_IDLE_SIB_COMPLETE)
# if defined(ENABLE_USE_MME)
      && (UE_rrc_inst[ue_mod_idP].initialNasMsg.data != NULL)
#endif
  ) {
      rrc_ue_generate_RRCConnectionRequest(ue_mod_idP, frameP, 0);
      LOG_I(RRC, "not sending connection request\n");

      rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_IDLE_CONNECTING);
  }

  /*  if ((UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1Status == 1) &&
      (UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus == 1) && (frameP >= ue_mod_idP * 20 + 10))
      SEQUENCE_free(&asn_DEF_BCCH_DL_SCH_Message, (void*)bcch_message, 0);*/
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT);

  return 0;
}


int
decode_SIB1(
                module_id_t ue_mod_idP,
                uint8_t eNB_index,
                uint8_t rsrq,
                uint8_t rsrp
                )
{
  SystemInformationBlockType1_t **sib1=&UE_rrc_inst[ue_mod_idP].sib1[eNB_index];
  int i;

  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN);

  LOG_D(RRC,"[UE %d] : Dumping SIB 1\n",ue_mod_idP);

  //  xer_fprint(stdout,&asn_DEF_SystemInformationBlockType1, (void*)*sib1);

  LOG_D(RRC,"cellAccessRelatedInfo.cellIdentity : %x.%x.%x.%x\n",
      (*sib1)->cellAccessRelatedInfo.cellIdentity.buf[0],
      (*sib1)->cellAccessRelatedInfo.cellIdentity.buf[1],
      (*sib1)->cellAccessRelatedInfo.cellIdentity.buf[2],
      (*sib1)->cellAccessRelatedInfo.cellIdentity.buf[3]);

  LOG_D(RRC,"cellSelectionInfo.q_RxLevMin       : %d\n",(int)(*sib1)->cellSelectionInfo.q_RxLevMin);
  LOG_D(RRC,"freqBandIndicator                  : %d\n",(int)(*sib1)->freqBandIndicator);
  LOG_D(RRC,"siWindowLength                     : %s\n",siWindowLength[(*sib1)->si_WindowLength]);
  if ((*sib1)->schedulingInfoList.list.count>0) {
      for (i=0;i<(*sib1)->schedulingInfoList.list.count;i++) {
          LOG_D(RRC,"siSchedulingInfoPeriod[%d]          : %s\n",i,SIBPeriod[(int)(*sib1)->schedulingInfoList.list.array[i]->si_Periodicity]);
          if ((*sib1)->schedulingInfoList.list.array[i]->sib_MappingInfo.list.count>0)
            LOG_D(RRC,"siSchedulingInfoSIBType[%d]         : %s\n",i,SIBType[(int)(*(*sib1)->schedulingInfoList.list.array[i]->sib_MappingInfo.list.array[0])]);
          else {
              LOG_W(RRC,"mapping list %d is null\n",i);
          }
      }
  }
  else {
      LOG_E(RRC,"siSchedulingInfoPeriod[0]          : PROBLEM!!!\n");
      return -1;
  }

  if ((*sib1)->tdd_Config) {
      LOG_D(RRC,"TDD subframe assignment            : %d\n",(int)(*sib1)->tdd_Config->subframeAssignment);
      LOG_D(RRC,"S-Subframe Config                  : %d\n",(int)(*sib1)->tdd_Config->specialSubframePatterns);
  }

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

  rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
      (RadioResourceConfigCommonSIB_t *)NULL,
      (struct PhysicalConfigDedicated *)NULL,
#ifdef Rel10
	(SCellToAddMod_r10_t *)NULL,
	//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
      (MeasObjectToAddMod_t **)NULL,
      (MAC_MainConfig_t *)NULL,
      0,
      (struct LogicalChannelConfig *)NULL,
      (MeasGapConfig_t *)NULL,
      UE_rrc_inst[ue_mod_idP].sib1[eNB_index]->tdd_Config,
      (MobilityControlInfo_t *) NULL,
      &UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIwindowsize,
      &UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIperiod,
      NULL,
      NULL,
      NULL,
      (MBSFN_SubframeConfigList_t *)NULL
#ifdef Rel10
      ,0,
      (MBSFN_AreaInfoList_r9_t *)NULL,
      (PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
      ,
      0,
      0
#endif
  );

  UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1Status = 1;
  UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIB1systemInfoValueTag = (*sib1)->systemInfoValueTag;

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

    if ((*sib1)->cellAccessRelatedInfo.cellBarred == 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++) {
            PLMN_Identity_t *plmn_Identity;

            plmn_Identity = &(*sib1)->cellAccessRelatedInfo.plmn_IdentityList.list.array[plmn]->plmn_Identity;
            if (((plmn_Identity->mcc == NULL)
                ||
                ((UE_rrc_inst[ue_mod_idP].plmnID.MCCdigit1 == *(plmn_Identity->mcc->list.array[0])) &&
                    (UE_rrc_inst[ue_mod_idP].plmnID.MCCdigit2 == *(plmn_Identity->mcc->list.array[1])) &&
                    (UE_rrc_inst[ue_mod_idP].plmnID.MCCdigit3 == *(plmn_Identity->mcc->list.array[2]))))
                    &&
                    (UE_rrc_inst[ue_mod_idP].plmnID.MNCdigit1 == *(plmn_Identity->mnc.list.array[0])) &&
                    (UE_rrc_inst[ue_mod_idP].plmnID.MNCdigit2 == *(plmn_Identity->mnc.list.array[1])) &&
                    (((UE_rrc_inst[ue_mod_idP].plmnID.MNCdigit3 == 0xf) && (plmn_Identity->mnc.list.count == 2))
                        ||
                        (UE_rrc_inst[ue_mod_idP].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, ue_mod_idP + NB_eNB_INST, 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, ue_mod_idP + NB_eNB_INST, 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(
                SystemInformationBlockType2_t *sib2
                )
{

  LOG_D(RRC,"radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.numberOfRA_Preambles : %ld\n",
      sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.numberOfRA_Preambles);

  //  if (radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig)
  //msg("radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig ",sib2->radioResourceConfigCommon.rach_ConfigCommon.preambleInfo.preamblesGroupAConfig = NULL;

  LOG_D(RRC,"[UE]radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.powerRampingStep : %ld\n",sib2->radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.powerRampingStep);

  LOG_D(RRC,"[UE]radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.preambleInitialReceivedTargetPower : %ld\n",sib2->radioResourceConfigCommon.rach_ConfigCommon.powerRampingParameters.preambleInitialReceivedTargetPower);

  LOG_D(RRC,"radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.preambleTransMax  : %ld\n",sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.preambleTransMax);

  LOG_D(RRC,"radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.ra_ResponseWindowSize : %ld\n",sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.ra_ResponseWindowSize);

  LOG_D(RRC,"radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.mac_ContentionResolutionTimer : %ld\n",sib2->radioResourceConfigCommon.rach_ConfigCommon.ra_SupervisionInfo.mac_ContentionResolutionTimer);

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

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

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

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

  // PUCCH-Config

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

  LOG_D(RRC,"radioResourceConfigCommon.soundingRS_UL_ConfigCommon.present : %d\n",sib2-> radioResourceConfigCommon.soundingRS_UL_ConfigCommon.present);


  // uplinkPowerControlCommon

  LOG_D(RRC,"radioResourceConfigCommon.uplinkPowerControlCommon.p0_NominalPUSCH : %ld\n",sib2->radioResourceConfigCommon.uplinkPowerControlCommon.p0_NominalPUSCH);
  LOG_D(RRC,"radioResourceConfigCommon.uplinkPowerControlCommon.alpha : %ld\n",sib2->radioResourceConfigCommon.uplinkPowerControlCommon.alpha);

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

  LOG_D(RRC,"radioResourceConfigCommon.uplinkPowerControlCommon.deltaPreambleMsg3 : %ld\n",sib2->radioResourceConfigCommon.uplinkPowerControlCommon.deltaPreambleMsg3);

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

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

  LOG_D(RRC,"freqInfo.additionalSpectrumEmission : %ld\n",sib2->freqInfo.additionalSpectrumEmission);
  LOG_D(RRC,"freqInfo.ul_CarrierFreq : %p\n", sib2->freqInfo.ul_CarrierFreq);
  LOG_D(RRC,"freqInfo.ul_Bandwidth : %p\n", sib2->freqInfo.ul_Bandwidth);
  LOG_D(RRC,"mbsfn_SubframeConfigList : %p\n", sib2->mbsfn_SubframeConfigList);
  LOG_D(RRC,"timeAlignmentTimerCommon : %ld\n", sib2->timeAlignmentTimerCommon);
}

void
dump_sib3(
                SystemInformationBlockType3_t *sib3
                )
{

}

#ifdef Rel10
void
dump_sib13(
                SystemInformationBlockType13_r9_t *sib13
                )
{

  LOG_D(RRC,"[RRC][UE] Dumping SIB13\n");
  LOG_D(RRC,"[RRC][UE] dumping sib13 second time\n");
  LOG_D(RRC,"[RRC][UE] NotificationRepetitionCoeff-r9 : %ld\n", sib13->notificationConfig_r9.notificationRepetitionCoeff_r9);
  LOG_D(RRC,"[RRC][UE] NotificationOffset-r9 : %d\n", (int)sib13->notificationConfig_r9.notificationOffset_r9);
  LOG_D(RRC,"[RRC][UE] NotificationSF-Index-r9 : %d\n", (int)sib13->notificationConfig_r9.notificationSF_Index_r9);

}
#endif

//const char SIBPeriod[7][7]= {"80ms\0","160ms\0","320ms\0","640ms\0","1280ms\0","2560ms\0","5120ms\0"};

int
decode_SI(
                module_id_t ue_mod_idP,
                frame_t frameP,
                uint8_t eNB_index,
                uint8_t si_window
                )
{

  SystemInformation_t **si=&UE_rrc_inst[ue_mod_idP].si[eNB_index][si_window];
  int i;
  struct SystemInformation_r8_IEs__sib_TypeAndInfo__Member *typeandinfo;

  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI  , VCD_FUNCTION_IN);

  // Dump contents
  if ((*si)->criticalExtensions.present==SystemInformation__criticalExtensions_PR_systemInformation_r8) {
      LOG_D(RRC,"(*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 (i=0;i<(*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.count;i++) {
      LOG_D(RRC,"SI count %d\n",i);
      typeandinfo=(*si)->criticalExtensions.choice.systemInformation_r8.sib_TypeAndInfo.list.array[i];

      switch(typeandinfo->present) {
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2:
        UE_rrc_inst[ue_mod_idP].sib2[eNB_index] = &typeandinfo->choice.sib2;
        LOG_D(RRC,"[UE %d] Frame %d Found SIB2 from eNB %d\n",ue_mod_idP,frameP,eNB_index);
        dump_sib2(UE_rrc_inst[ue_mod_idP].sib2[eNB_index]);
        LOG_D(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SIB2 params  eNB %d) --->][MAC_UE][MOD %02d][]\n",
            frameP, ue_mod_idP, eNB_index, ue_mod_idP);
        rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
            &UE_rrc_inst[ue_mod_idP].sib2[eNB_index]->radioResourceConfigCommon,
            (struct PhysicalConfigDedicated *)NULL,
#ifdef Rel10
  	(SCellToAddMod_r10_t *)NULL,
	//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif			   
            (MeasObjectToAddMod_t **)NULL,
            (MAC_MainConfig_t *)NULL,
            0,
            (struct LogicalChannelConfig *)NULL,
            (MeasGapConfig_t *)NULL,
            (TDD_Config_t *)NULL,
            (MobilityControlInfo_t *)NULL,
            NULL,
            NULL,
            UE_rrc_inst[ue_mod_idP].sib2[eNB_index]->freqInfo.ul_CarrierFreq,
            UE_rrc_inst[ue_mod_idP].sib2[eNB_index]->freqInfo.ul_Bandwidth,
            &UE_rrc_inst[ue_mod_idP].sib2[eNB_index]->freqInfo.additionalSpectrumEmission,
            UE_rrc_inst[ue_mod_idP].sib2[eNB_index]->mbsfn_SubframeConfigList
#ifdef Rel10
,0,
(MBSFN_AreaInfoList_r9_t *)NULL,
(PMCH_InfoList_r9_t *)NULL
#endif
#ifdef CBA
,0,
0
#endif
        );
        UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus = 1;
        // After SI is received, prepare RRCConnectionRequest
#ifdef Rel10
        if (UE_rrc_inst[ue_mod_idP].MBMS_flag < 3) // see -Q option
#endif
#if !(defined(ENABLE_ITTI) && defined(ENABLE_USE_MME))
          rrc_ue_generate_RRCConnectionRequest(ue_mod_idP,frameP,eNB_index);
        LOG_I(RRC, "not sending connection request\n");
#endif

        if (UE_rrc_inst[ue_mod_idP].Info[eNB_index].State == RRC_IDLE) {
            LOG_I(RRC,"[UE %d] Received SIB1/SIB2/SIB3 Switching to RRC_SI_RECEIVED\n",ue_mod_idP);
            UE_rrc_inst[ue_mod_idP].Info[eNB_index].State = RRC_SI_RECEIVED;
#ifdef 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_mod_idP + NB_eNB_INST, message_ral_p);
            }
#endif
        }
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3:
        UE_rrc_inst[ue_mod_idP].sib3[eNB_index] = &typeandinfo->choice.sib3;
        LOG_I(RRC,"[UE %d] Frame %d Found SIB3 from eNB %d\n",ue_mod_idP,frameP,eNB_index);
        dump_sib3(UE_rrc_inst[ue_mod_idP].sib3[eNB_index]);
        UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus = 1;

        rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_IDLE_SIB_COMPLETE);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4:
        UE_rrc_inst[ue_mod_idP].sib4[eNB_index] = &typeandinfo->choice.sib4;
        LOG_I(RRC,"[UE %d] Frame %d Found SIB4 from eNB %d\n",ue_mod_idP,frameP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5:
        UE_rrc_inst[ue_mod_idP].sib5[eNB_index] = &typeandinfo->choice.sib5;
        LOG_I(RRC,"[UE %d] Found SIB5 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6:
        UE_rrc_inst[ue_mod_idP].sib6[eNB_index] = &typeandinfo->choice.sib6;
        LOG_I(RRC,"[UE %d] Found SIB6 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7:
        UE_rrc_inst[ue_mod_idP].sib7[eNB_index] = &typeandinfo->choice.sib7;
        LOG_I(RRC,"[UE %d] Found SIB7 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8:
        UE_rrc_inst[ue_mod_idP].sib8[eNB_index] = &typeandinfo->choice.sib8;
        LOG_I(RRC,"[UE %d] Found SIB8 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9:
        UE_rrc_inst[ue_mod_idP].sib9[eNB_index] = &typeandinfo->choice.sib9;
        LOG_I(RRC,"[UE %d] Found SIB9 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10:
        UE_rrc_inst[ue_mod_idP].sib10[eNB_index] = &typeandinfo->choice.sib10;
        LOG_I(RRC,"[UE %d] Found SIB10 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11:
        UE_rrc_inst[ue_mod_idP].sib11[eNB_index] = &typeandinfo->choice.sib11;
        LOG_I(RRC,"[UE %d] Found SIB11 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
#ifdef Rel10
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib12_v920:
        UE_rrc_inst[ue_mod_idP].sib12[eNB_index] = &typeandinfo->choice.sib12_v920;
        LOG_I(RRC,"[RRC][UE %d] Found SIB12 from eNB %d\n",ue_mod_idP,eNB_index);
        break;
      case SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920:
        UE_rrc_inst[ue_mod_idP].sib13[eNB_index] = &typeandinfo->choice.sib13_v920;
        LOG_I(RRC,"[RRC][UE %d] Found SIB13 from eNB %d\n",ue_mod_idP,eNB_index);
        dump_sib13(UE_rrc_inst[ue_mod_idP].sib13[eNB_index]);
        // adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer
        LOG_D(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ (SIB13 params eNB %d) --->][MAC_UE][MOD %02d][]\n",
            frameP, ue_mod_idP, eNB_index, ue_mod_idP);
        rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
            (RadioResourceConfigCommonSIB_t *)NULL,
            (struct PhysicalConfigDedicated *)NULL,
#ifdef Rel10
	(SCellToAddMod_r10_t *)NULL,
	//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
            (MeasObjectToAddMod_t **)NULL,
            (MAC_MainConfig_t *)NULL,
            0,
            (struct LogicalChannelConfig *)NULL,
            (MeasGapConfig_t *)NULL,
            (TDD_Config_t *)NULL,
            (MobilityControlInfo_t *)NULL,
            NULL,
            NULL,
            NULL,
            NULL,
            NULL,
            (MBSFN_SubframeConfigList_t *)NULL
            ,0,
            &UE_rrc_inst[ue_mod_idP].sib13[eNB_index]->mbsfn_AreaInfoList_r9,
            (PMCH_InfoList_r9_t *)NULL
#ifdef CBA
,0,
0
#endif
        );
        UE_rrc_inst[ue_mod_idP].Info[eNB_index].SIStatus = 1;
        break;
#endif
      default:
        break;
      }

  }

  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(
                module_id_t ue_mod_idP,
                frame_t frameP,
                uint8_t eNB_index
                )
{
  float a  = UE_rrc_inst[ue_mod_idP].filter_coeff_rsrp; // 'a' in 36.331 Sec. 5.5.3.2
  float a1 = UE_rrc_inst[ue_mod_idP].filter_coeff_rsrq;
  //float rsrp_db, rsrq_db;
  uint8_t    eNB_offset;

  if(UE_rrc_inst[ue_mod_idP].QuantityConfig[0] != NULL) { // Only consider 1 serving cell (index: 0)
      if (UE_rrc_inst[ue_mod_idP].QuantityConfig[0]->quantityConfigEUTRA != NULL) {
          if(UE_rrc_inst[ue_mod_idP].QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRP != NULL) {
              for (eNB_offset = 0;eNB_offset<1+mac_xface->get_n_adj_cells(ue_mod_idP,0);eNB_offset++) {
                  //filter_factor = 1/power(2,*UE_rrc_inst[ue_mod_idP].QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRP/4);
                  // LOG_N(RRC,"[UE %d] Frame %d : check proper operation in abstraction mode rsrp (%d), rx gain (%d) N_RB_DL (%d)\n",
                  //	ue_mod_idP,frameP,mac_xface->get_RSRP(ue_mod_idP,0,eNB_offset),mac_xface->get_rx_total_gain_dB(ue_mod_idP,0),mac_xface->lte_frame_parms->N_RB_DL);
                  UE_rrc_inst[ue_mod_idP].rsrp_db[eNB_offset] = (dB_fixed_times10(mac_xface->get_RSRP(ue_mod_idP,0,eNB_offset))/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12);
                  UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset] = (1.0-a)*UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset] +  a*UE_rrc_inst[ue_mod_idP].rsrp_db[eNB_offset];
                  //mac_xface->set_RSRP_filtered(ue_mod_idP,eNB_offset,UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset]);


                  //LOG_D(RRC,"RSRP_total_dB: %3.2f \n",(dB_fixed_times10(mac_xface->get_RSRP(ue_mod_idP,0,eNB_offset))/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12));

                  LOG_D(RRC,"RSRP_dBm: %3.2f \n",(dB_fixed_times10(mac_xface->get_RSRP(ue_mod_idP,0,eNB_offset))/10.0));
                  LOG_D(RRC,"gain_loss_dB: %d \n",mac_xface->get_rx_total_gain_dB(ue_mod_idP,0));
                  LOG_D(RRC,"gain_fixed_dB: %d \n",dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12));
                  LOG_D(PHY,"[UE %d] Frame %d, RRC Measurements => rssi %3.1f dBm (digital: %3.1f dB)\n",
              			ue_mod_idP, frameP,	10*log10(mac_xface->get_RSSI(ue_mod_idP,0))-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0),10*log10(mac_xface->get_RSSI(ue_mod_idP,0)));
                  LOG_D(RRC,"[UE %d] Frame %d: Meas RSRP: eNB_offset: %d rsrp_coef: %3.1f filter_coef: %d before L3 filtering: rsrp: %3.1f after L3 filtering: rsrp: %3.1f \n ",
                      ue_mod_idP, frameP, eNB_offset,a,
                      *UE_rrc_inst->QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRP,
                      UE_rrc_inst[ue_mod_idP].rsrp_db[eNB_offset],
                      UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset]);
              }
          }
      }
      else {
          for (eNB_offset = 0;eNB_offset<1+mac_xface->get_n_adj_cells(ue_mod_idP,0);eNB_offset++) {
              UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset]= mac_xface->get_RSRP(ue_mod_idP,0,eNB_offset);
              // phy_vars_ue->PHY_measurements.rsrp_filtered[eNB_offset]=UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset];
              //mac_xface->set_RSRP_filtered(ue_mod_idP,eNB_offset,UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset]);
          }
      }
      if (UE_rrc_inst[ue_mod_idP].QuantityConfig[0]->quantityConfigEUTRA != NULL) {
          if(UE_rrc_inst[ue_mod_idP].QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRQ != NULL) {
              for (eNB_offset = 0;eNB_offset<1+mac_xface->get_n_adj_cells(ue_mod_idP,0);eNB_offset++) {
                  // LOG_N(RRC,"[UE %d] Frame %d : check if this operation workes properly in abstraction mode\n",ue_mod_idP,frameP);
                  UE_rrc_inst[ue_mod_idP].rsrq_db[eNB_offset] = (10*log10(mac_xface->get_RSRQ(ue_mod_idP,0,eNB_offset)))-20;
                  UE_rrc_inst[ue_mod_idP].rsrq_db_filtered[eNB_offset]=(1-a1)*UE_rrc_inst[ue_mod_idP].rsrq_db_filtered[eNB_offset] + a1 *UE_rrc_inst[ue_mod_idP].rsrq_db[eNB_offset];
                  //mac_xface->set_RSRP_filtered(ue_mod_idP,eNB_offset,UE_rrc_inst[ue_mod_idP].rsrp_db_filtered[eNB_offset]);
                  /*
          LOG_D(RRC,"[UE %d] Frame %d: Meas RSRQ: eNB_offset: %d rsrq_coef: %3.2f filter_coef: %d before L3 filtering: rsrq: %3.1f after L3 filtering: rsrq: %3.1f \n ",
            ue_mod_idP,frameP,eNB_offset,a1,
                   *UE_rrc_inst->QuantityConfig[0]->quantityConfigEUTRA->filterCoefficientRSRQ,
            mac_xface->get_RSRQ(ue_mod_idP,0,eNB_offset),
            UE_rrc_inst[ue_mod_idP].rsrq_db[eNB_offset],
            UE_rrc_inst[ue_mod_idP].rsrq_db_filtered[eNB_offset]);
                   */
              }
          }
      }
      else{
          for (eNB_offset = 0;eNB_offset<1+mac_xface->get_n_adj_cells(ue_mod_idP,0);eNB_offset++) {
              UE_rrc_inst[ue_mod_idP].rsrq_db_filtered[eNB_offset]= mac_xface->get_RSRQ(ue_mod_idP,0,eNB_offset);
          }
      }
  }
}

//Below routine implements Measurement Reporting procedure from 36.331 Section 5.5.5
void
rrc_ue_generate_MeasurementReport(
                module_id_t eNB_id,
                module_id_t UE_id,
                frame_t frameP
                )
{

  uint8_t             buffer[32], size;
  uint8_t             i;
  uint8_t             target_eNB_offset;
  MeasId_t         measId;
  PhysCellId_t     cellId, 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;
  protocol_ctxt_t  ctxt;

  ctxt.enb_module_id = eNB_id;
  ctxt.ue_module_id  = UE_id;
  ctxt.frame         = frameP;
  ctxt.enb_flag      = ENB_FLAG_NO;



  nElem = 98;
  nElem1 = 35;
  target_eNB_offset = UE_rrc_inst[UE_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[UE_id].measReportList[0][i] != NULL) {
          measId = UE_rrc_inst[UE_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[UE_id].rsrp_db_filtered[eNB_id];//nid_cell];
          rsrp_s = binary_search_float(RSRP_meas_mapping,nElem, rsrp_filtered);

          rsrq_filtered = UE_rrc_inst[UE_id].rsrq_db_filtered[eNB_id];//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",
              UE_id, frameP, eNB_id, rsrp_s,rsrq_s,rsrp_filtered,rsrq_filtered);

          rsrp_t = binary_search_float(RSRP_meas_mapping,nElem,UE_rrc_inst[UE_id].rsrp_db_filtered[target_eNB_offset]); //RSRP of target cell
          rsrq_t = binary_search_float(RSRQ_meas_mapping,nElem1,UE_rrc_inst[UE_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",
              UE_id, frameP, target_eNB_offset, rsrp_t,rsrq_t,UE_rrc_inst[UE_id].rsrp_db_filtered[target_eNB_offset],UE_rrc_inst[UE_id].rsrq_db_filtered[target_eNB_offset]);

          //  if (measFlag == 1) {
          cellId = get_adjacent_cell_id(UE_id, eNB_id); //PhycellId of serving cell
          targetCellId = UE_rrc_inst[UE_id].HandoverInfoUe.targetCellId ;//get_adjacent_cell_id(ue_mod_idP,target_eNB_offset); //PhycellId of target cell

          if (pframe!=frameP){
              pframe=frameP;
              LOG_D(RRC, "[UE %d] Frame %d: doing MeasReport: servingCell(%d) targetCell(%d) rsrp_s(%ld) rsrq_s(%ld) rsrp_t(%ld) rsrq_t(%ld) \n",
                  UE_id, frameP, cellId,targetCellId,rsrp_s,rsrq_s,rsrp_t,rsrq_t);
              size = do_MeasurementReport(UE_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", UE_id, frameP, eNB_id);
              LOG_D(RLC, "[MSC_MSG][FRAME %05d][RRC_UE][UE %02d][][--- PDCP_DATA_REQ/%d Bytes (MeasurementReport to eNB %d MUI %d) --->][PDCP][MOD %02d][RB %02d]\n",
                  frameP, UE_id, size, eNB_id, rrc_mui, eNB_id, DCCH);
              result = pdcp_data_req(&ctxt,  SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA);
              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(
                module_id_t ue_mod_idP,
                frame_t frameP,
                uint8_t eNB_index
                )
{
  uint8_t               i,j;
  Hysteresis_t     hys;
  TimeToTrigger_t  ttt_ms;
  Q_OffsetRange_t  ofn;
  Q_OffsetRange_t  ocn;
  Q_OffsetRange_t  ofs = 0;
  Q_OffsetRange_t  ocs = 0;
  long             a3_offset;
  MeasObjectId_t   measObjId;
  ReportConfigId_t reportConfigId;

  for(i=0 ; i<NB_CNX_UE ; i++) {
      for(j=0 ; j<MAX_MEAS_ID ; j++) {
          if(UE_rrc_inst[ue_mod_idP].MeasId[i][j] != NULL) {
              measObjId = UE_rrc_inst[ue_mod_idP].MeasId[i][j]->measObjectId;
              reportConfigId = UE_rrc_inst[ue_mod_idP].MeasId[i][j]->reportConfigId;
              if( /*UE_rrc_inst[ue_mod_idP].MeasId[i][j] != NULL && */ UE_rrc_inst[ue_mod_idP].MeasObj[i][measObjId-1] != NULL) {
                  if(UE_rrc_inst[ue_mod_idP].MeasObj[i][measObjId-1]->measObject.present == 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[ue_mod_idP].ReportConfig[i][reportConfigId-1]);
                      if((UE_rrc_inst[ue_mod_idP].ReportConfig[i][reportConfigId-1] != NULL) &&
                          (UE_rrc_inst[ue_mod_idP].ReportConfig[i][reportConfigId-1]->reportConfig.present==ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA) &&
                          (UE_rrc_inst[ue_mod_idP].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.present == ReportConfigEUTRA__triggerType_PR_event)) {
                          hys = UE_rrc_inst[ue_mod_idP].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis;
                          //LOG_N(RRC,"[UE%d] Frame %d Check below lines for segfault :), Fix me \n",ue_mod_idP, frameP);
                          ttt_ms = timeToTrigger_ms[UE_rrc_inst[ue_mod_idP].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger];
                          // Freq specific offset of neighbor cell freq
                          ofn = 5;//((UE_rrc_inst[ue_mod_idP].MeasObj[i][measObjId-1]->measObject.choice.measObjectEUTRA.offsetFreq != NULL) ?
                             // *UE_rrc_inst[ue_mod_idP].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[ue_mod_idP].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset;

                          switch (UE_rrc_inst[ue_mod_idP].ReportConfig[i][reportConfigId-1]->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present) {
                          case ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1:
                            LOG_D(RRC,"[UE %d] Frame %d : A1 event: check if serving becomes better than threshold\n",ue_mod_idP, frameP);
                            break;
                          case ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2:
                            LOG_D(RRC,"[UE %d] Frame %d : A2 event, check if serving becomes worse than a threshold\n",ue_mod_idP, frameP);
                            break;
                          case 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",ue_mod_idP, frameP);
                            if ((check_trigger_meas_event(ue_mod_idP,frameP,eNB_index,i,j,ofn,ocn,hys,ofs,ocs,a3_offset,ttt_ms)) &&
                                (UE_rrc_inst[ue_mod_idP].Info[0].State >= RRC_CONNECTED) &&
                                (UE_rrc_inst[ue_mod_idP].Info[0].T304_active == 0 )      &&
                                (UE_rrc_inst[ue_mod_idP].HandoverInfoUe.measFlag == 1)) {
                                //trigger measurement reporting procedure (36.331, section 5.5.5)
                                if (UE_rrc_inst[ue_mod_idP].measReportList[i][j] == NULL) {
                                    UE_rrc_inst[ue_mod_idP].measReportList[i][j] = malloc(sizeof(MEAS_REPORT_LIST));
                                }
                                UE_rrc_inst[ue_mod_idP].measReportList[i][j]->measId = UE_rrc_inst[ue_mod_idP].MeasId[i][j]->measId;
                                UE_rrc_inst[ue_mod_idP].measReportList[i][j]->numberOfReportsSent = 0;
                                rrc_ue_generate_MeasurementReport(eNB_index, ue_mod_idP,frameP);
                                UE_rrc_inst[ue_mod_idP].HandoverInfoUe.measFlag = 1;
                                LOG_I(RRC,"[UE %d] Frame %d: A3 event detected, state: %d \n", ue_mod_idP, frameP, UE_rrc_inst[ue_mod_idP].Info[0].State);
                            }
                            else {
                                if(UE_rrc_inst[ue_mod_idP].measReportList[i][j] != NULL){
                                    free(UE_rrc_inst[ue_mod_idP].measReportList[i][j]);
                                }
                                UE_rrc_inst[ue_mod_idP].measReportList[i][j] = NULL;
                            }
                            break;
                          case 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",ue_mod_idP, frameP);
                            break;
                          case 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",ue_mod_idP, frameP);
                            break;
                          default:
                            LOG_D(RRC,"Invalid ReportConfigEUTRA__triggerType__event__eventId: %d",
                                UE_rrc_inst[ue_mod_idP].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,
                Q_OffsetRange_t ofn,
                Q_OffsetRange_t ocn,
                Hysteresis_t    hys,
                Q_OffsetRange_t ofs,
                Q_OffsetRange_t ocs,
                long            a3_offset,
                TimeToTrigger_t ttt
                )
{
  uint8_t eNB_offset;
  uint8_t currentCellIndex = mac_xface->lte_frame_parms->Nid_cell;
  uint8_t tmp_offset;

  LOG_I(RRC,"[UE %d] ofn(%d) ocn(%d) hys(%d) ofs(%d) ocs(%d) a3_offset(%d) ttt(%d) rssi %3.1f\n",
	ue_mod_idP, 
	ofn,ocn,hys,ofs,ocs,a3_offset,ttt,
	10*log10(mac_xface->get_RSSI(ue_mod_idP,0))-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0));
  for (eNB_offset = 0;eNB_offset<1+mac_xface->get_n_adj_cells(ue_mod_idP,0);eNB_offset++) {
  //for (eNB_offset = 1;(eNB_offset<1+mac_xface->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],currentCellIndex,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],currentCellIndex,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: %d 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,
		    (dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[0])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12),
		    (dB_fixed_times10(UE_rrc_inst[ue_mod_idP].rsrp_db[eNB_offset])/10.0)-mac_xface->get_rx_total_gain_dB(ue_mod_idP,0)-dB_fixed(mac_xface->lte_frame_parms->N_RB_DL*12));
	      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;
}

#ifdef Rel10
int
decode_MCCH_Message(
                module_id_t ue_mod_idP,
                frame_t     frameP,
                uint8_t     eNB_index,
                uint8_t    *Sdu,
                uint8_t     Sdu_len,
                uint8_t     mbsfn_sync_area
                )
{

  MCCH_Message_t               *mcch=NULL;
  MBSFNAreaConfiguration_r9_t **mcch_message=&UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index];
  asn_dec_rval_t                dec_rval;

  if (UE_rrc_inst[ue_mod_idP].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",
          ue_mod_idP, frameP, mbsfn_sync_area);
      return 0; // avoid decoding to prevent memory bloating
  }
  else {
      dec_rval = uper_decode_complete(NULL,
          &asn_DEF_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 (%d bits)\n",ue_mod_idP,dec_rval.consumed);
          //free the memory
          SEQUENCE_free(&asn_DEF_MCCH_Message, (void*)mcch, 1);
          return -1;
      }
#ifdef XER_PRINT
      xer_fprint(stdout, &asn_DEF_MCCH_Message, (void*)mcch);
#endif

      if (mcch->message.present == MCCH_MessageType_PR_c1) {
          LOG_D(RRC,"[UE %d] Found mcch message \n",ue_mod_idP);
          if(mcch->message.choice.c1.present == 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",ue_mod_idP, frameP, eNB_index);
              decode_MBSFNAreaConfiguration(ue_mod_idP,eNB_index,frameP, 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
                )
{
    protocol_ctxt_t               ctxt;

  LOG_D(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);
  //  store to MAC/PHY necessary parameters for receiving MTCHs
  rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
      (RadioResourceConfigCommonSIB_t *)NULL,
      (struct PhysicalConfigDedicated *)NULL,
#ifdef Rel10
	(SCellToAddMod_r10_t *)NULL,
	//(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
#endif
      (MeasObjectToAddMod_t **)NULL,
      (MAC_MainConfig_t *)NULL,
      0,
      (struct LogicalChannelConfig *)NULL,
      (MeasGapConfig_t *)NULL,
      (TDD_Config_t *)NULL,
      (MobilityControlInfo_t *)NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      (MBSFN_SubframeConfigList_t *)NULL
#ifdef Rel10	       
,
0,
(MBSFN_AreaInfoList_r9_t *)NULL,
&UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9
#endif
#ifdef CBA
,
0,
0
#endif
  );

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

  ctxt.enb_module_id = eNB_index;
  ctxt.ue_module_id  = ue_mod_idP;
  ctxt.frame         = frameP;
  ctxt.enb_flag      = ENB_FLAG_NO;

  // 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
      (DRB_ToReleaseList_t*)NULL,
      0, // security mode
      NULL, // key rrc encryption
      NULL, // key rrc integrity
      NULL // key encryption
#ifdef Rel10
      ,&(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
#endif
  );

  rrc_rlc_config_asn1_req(&ctxt,
      NULL,// SRB_ToAddModList
      NULL,// DRB_ToAddModList
      NULL,// DRB_ToReleaseList
#ifdef Rel10
      &(UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9)
#endif 
  );
  // */

}

#endif // rel10

#ifndef USER_MODE
EXPORT_SYMBOL(Rlc_info_am_config);
#endif

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

  itti_mark_task_ready (TASK_RRC_UE);

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

      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);
      ue_mod_id = instance - NB_eNB_INST;

      switch (ITTI_MSG_ID(msg_p)) {
      case TERMINATE_MESSAGE:
        itti_exit_task ();
        break;

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

        /* MAC messages */
      case RRC_MAC_IN_SYNC_IND:
        LOG_D(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, msg_name,
            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_I(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, msg_name,
            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, msg_name,
            RRC_MAC_BCCH_DATA_IND (msg_p).frame, RRC_MAC_BCCH_DATA_IND (msg_p).enb_index);

        decode_BCCH_DLSCH_Message (ue_mod_id, RRC_MAC_BCCH_DATA_IND (msg_p).frame,
            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_I(RRC, "[UE %d] Received %s: eNB %d\n", ue_mod_id, msg_name,
            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_I(RRC, "[UE %d] Received %s: frameP %d, eNB %d\n", ue_mod_id, msg_name,
            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;
        rrc_ue_decode_ccch (ue_mod_id, RRC_MAC_CCCH_DATA_IND (msg_p).frame, srb_info_p,
            RRC_MAC_CCCH_DATA_IND (msg_p).enb_index);
        break;

# ifdef Rel10
      case RRC_MAC_MCCH_DATA_IND:
        LOG_I(RRC, "[UE %d] Received %s: frameP %d, eNB %d, mbsfn SA %d\n", ue_mod_id, msg_name,
            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);

        decode_MCCH_Message (ue_mod_id, RRC_MAC_MCCH_DATA_IND (msg_p).frame, 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;
# endif

/* PDCP messages */
      case RRC_DCCH_DATA_IND:
        LOG_I(RRC, "[UE %d] Received %s: frameP %d, DCCH %d, eNB %d\n", ue_mod_id, msg_name,
            RRC_DCCH_DATA_IND (msg_p).frame, RRC_DCCH_DATA_IND (msg_p).dcch_index, RRC_DCCH_DATA_IND (msg_p).eNB_index);

        rrc_ue_decode_dcch (ue_mod_id, RRC_DCCH_DATA_IND (msg_p).frame,
            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)
        /* NAS messages */
      case NAS_CELL_SELECTION_REQ:
        ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */

        LOG_I(RRC, "[UE %d] Received %s: state %d, plmnID %d, rat %x\n", ue_mod_id, msg_name, rrc_get_state(ue_mod_id),
            NAS_CELL_SELECTION_REQ (msg_p).plmnID, 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;
        }

        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, NB_eNB_INST + 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, NB_eNB_INST + 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, msg_name, rrc_get_state(ue_mod_id));
          break;

        default:
          LOG_C(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_I(RRC, "[UE %d] Received %s: cause %d, type %d, s_tmsi %d, plmnID %d\n", ue_mod_id, msg_name, NAS_CONN_ESTABLI_REQ (msg_p).cause,
              NAS_CONN_ESTABLI_REQ (msg_p).type, NAS_CONN_ESTABLI_REQ (msg_p).s_tmsi, NAS_CONN_ESTABLI_REQ (msg_p).plmnID);

          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(ue_mod_id, 0 /* TODO put frameP number ! */, 0);
                  LOG_I(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, msg_name, rrc_get_state(ue_mod_id));
            break;

          default:
            LOG_C(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_I(RRC, "[UE %d] Received %s: UEid %d\n", ue_mod_id, msg_name, 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 */
              pdcp_rrc_data_req (0, ue_mod_id, 0 /* TODO put frameP number ! */, 0, DCCH, rrc_mui++, 0, length, buffer, 1);
              break;
            }
# endif

# if defined(ENABLE_RAL)
          case RRC_RAL_SCAN_REQ:
            LOG_I(RRC, "[UE %d] Received %s: state %d\n", ue_mod_id, msg_name);

            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, msg_name, rrc_get_state(ue_mod_id));
              break;

            default:
              LOG_C(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_I(RRC, "[UE %d] Received %s: state %d\n", ue_mod_id, msg_name, 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_C(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, msg_name, rrc_get_state(ue_mod_id));
                  break;

                default:
                  LOG_C(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_I(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_I(RRC, "[UE %d] Received %s\n", ue_mod_id, msg_name);
                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(ue_mod_id, 0 /* TODO put frameP number ! */, 0);
                        LOG_I(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, msg_name, rrc_get_state(ue_mod_id));
                  break;

                default:
                  LOG_C(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:
                  ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */
                  LOG_I(RRC, "[UE %d] Received %s\n", ue_mod_id, msg_name);
                  break;
#endif

                default:
                  LOG_E(RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, msg_name);
                  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