diff --git a/common/utils/msc/msc.h b/common/utils/msc/msc.h
index e8a8a4a0e82d7f65f9b9fcd80b54ddc79cff2759..0a4c37bab8ac90d731dfd0981d9c2bec7e4917bf 100644
--- a/common/utils/msc/msc.h
+++ b/common/utils/msc/msc.h
@@ -62,9 +62,9 @@ typedef enum {
     MSC_S11_MME,
     MSC_S6A_MME,
     MSC_HSS,
-    MAX_MSC_PROTOS,
     MSC_X2AP_SRC_ENB,
     MSC_X2AP_TARGET_ENB,
+    MAX_MSC_PROTOS,
 } msc_proto_t;
 
 
diff --git a/openair2/COMMON/s1ap_messages_def.h b/openair2/COMMON/s1ap_messages_def.h
index f98782f19ec238bb32de3fd0ce770372fa032f37..57201721ced6b4019577343a897bae1bdb3db2cd 100644
--- a/openair2/COMMON/s1ap_messages_def.h
+++ b/openair2/COMMON/s1ap_messages_def.h
@@ -39,6 +39,8 @@ MESSAGE_DEF(S1AP_PAGING_LOG    , MESSAGE_PRIORITY_MED, IttiMsgText
 MESSAGE_DEF(S1AP_E_RAB_RELEASE_REQUEST_LOG   , MESSAGE_PRIORITY_MED, IttiMsgText                      , s1ap_e_rab_release_request_log)
 MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE_LOG  , MESSAGE_PRIORITY_MED, IttiMsgText                      , s1ap_e_rab_release_response_log)
 MESSAGE_DEF(S1AP_ERROR_INDICATION_LOG        , MESSAGE_PRIORITY_MED, IttiMsgText                      , s1ap_error_indication_log)
+MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_LOG         , MESSAGE_PRIORITY_MED, IttiMsgText                      , s1ap_path_switch_req_log)
+MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK_LOG     , MESSAGE_PRIORITY_MED, IttiMsgText                      , s1ap_path_switch_req_ack_log)
 
 /* eNB application layer -> S1AP messages */
 MESSAGE_DEF(S1AP_REGISTER_ENB_REQ          , MESSAGE_PRIORITY_MED, s1ap_register_enb_req_t          , s1ap_register_enb_req)
@@ -62,6 +64,8 @@ MESSAGE_DEF(S1AP_E_RAB_SETUP_RESP          , MESSAGE_PRIORITY_MED, s1ap_e_rab_se
 MESSAGE_DEF(S1AP_E_RAB_SETUP_REQUEST_FAIL  , MESSAGE_PRIORITY_MED, s1ap_e_rab_setup_req_fail_t      , s1ap_e_rab_setup_request_fail)
 MESSAGE_DEF(S1AP_E_RAB_MODIFY_RESP          , MESSAGE_PRIORITY_MED, s1ap_e_rab_modify_resp_t          , s1ap_e_rab_modify_resp)
 MESSAGE_DEF(S1AP_E_RAB_RELEASE_RESPONSE    , MESSAGE_PRIORITY_MED, s1ap_e_rab_release_resp_t        , s1ap_e_rab_release_resp)
+MESSAGE_DEF(S1AP_PATH_SWITCH_REQ           , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_t           , s1ap_path_switch_req)
+MESSAGE_DEF(S1AP_PATH_SWITCH_REQ_ACK       , MESSAGE_PRIORITY_MED, s1ap_path_switch_req_ack_t       , s1ap_path_switch_req_ack)
 
 /* S1AP -> RRC messages */
 MESSAGE_DEF(S1AP_DOWNLINK_NAS              , MESSAGE_PRIORITY_MED, s1ap_downlink_nas_t              , s1ap_downlink_nas )
diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h
index 4a5f492b0baa3f4685c8de48f342ff6075e02d8f..3edc3f95c91ba5f1bc55cb3cdcf7414ada0a324e 100644
--- a/openair2/COMMON/s1ap_messages_types.h
+++ b/openair2/COMMON/s1ap_messages_types.h
@@ -42,6 +42,8 @@
 #define S1AP_E_RAB_SETUP_RESP(mSGpTR)           (mSGpTR)->ittiMsg.s1ap_e_rab_setup_resp
 #define S1AP_E_RAB_SETUP_FAIL(mSGpTR)           (mSGpTR)->ittiMsg.s1ap_e_rab_setup_req_fail
 #define S1AP_E_RAB_MODIFY_RESP(mSGpTR)           (mSGpTR)->ittiMsg.s1ap_e_rab_modify_resp
+#define S1AP_PATH_SWITCH_REQ(mSGpTR)            (mSGpTR)->ittiMsg.s1ap_path_switch_req
+#define S1AP_PATH_SWITCH_REQ_ACK(mSGpTR)        (mSGpTR)->ittiMsg.s1ap_path_switch_req_ack
 
 #define S1AP_DOWNLINK_NAS(mSGpTR)               (mSGpTR)->ittiMsg.s1ap_downlink_nas
 #define S1AP_INITIAL_CONTEXT_SETUP_REQ(mSGpTR)  (mSGpTR)->ittiMsg.s1ap_initial_context_setup_req
@@ -269,6 +271,17 @@ typedef struct e_rab_setup_s {
   uint32_t gtp_teid;
 } e_rab_setup_t;
 
+typedef struct e_rab_tobeswitched_s {
+  /* Unique e_rab_id for the UE. */
+  uint8_t e_rab_id;
+
+  /* The transport layer address for the IP packets */
+  transport_layer_addr_t sgw_addr;
+
+  /* S-GW Tunnel endpoint identifier */
+  uint32_t gtp_teid;
+} e_rab_tobeswitched_t;
+
 typedef struct e_rab_modify_s {
   /* Unique e_rab_id for the UE. */
   uint8_t e_rab_id;
@@ -472,6 +485,8 @@ typedef struct s1ap_initial_context_setup_req_s {
   /* eNB ue s1ap id as initialized by S1AP layer */
   unsigned eNB_ue_s1ap_id:24;
 
+  uint32_t mme_ue_s1ap_id;
+
   /* UE aggregate maximum bitrate */
   ambr_t ue_ambr;
 
@@ -525,7 +540,7 @@ typedef struct s1ap_e_rab_setup_req_s {
   uint16_t ue_initial_id;
 
   /* MME UE id  */
-  uint16_t mme_ue_s1ap_id;
+  uint32_t mme_ue_s1ap_id;
 
   /* eNB ue s1ap id as initialized by S1AP layer */
   unsigned eNB_ue_s1ap_id:24;
@@ -552,6 +567,58 @@ typedef struct s1ap_e_rab_setup_resp_s {
   e_rab_failed_t e_rabs_failed[S1AP_MAX_E_RAB];
 } s1ap_e_rab_setup_resp_t;
 
+typedef struct s1ap_path_switch_req_s {
+
+  unsigned  eNB_ue_s1ap_id:24;
+
+  /* Number of e_rab setup-ed in the list */
+  uint8_t       nb_of_e_rabs;
+
+  /* list of e_rab setup-ed by RRC layers */
+  e_rab_setup_t e_rabs_tobeswitched[S1AP_MAX_E_RAB];
+
+  /* MME UE id  */
+  uint32_t mme_ue_s1ap_id;
+
+  s1ap_gummei_t ue_gummei;
+
+  uint16_t ue_initial_id;
+
+   /* Security algorithms */
+  security_capabilities_t security_capabilities;
+
+} s1ap_path_switch_req_t;
+
+typedef struct s1ap_path_switch_req_ack_s {
+
+  /* UE id for initial connection to S1AP */
+  uint16_t ue_initial_id;
+
+  unsigned  eNB_ue_s1ap_id:24;
+
+  /* MME UE id  */
+  uint32_t mme_ue_s1ap_id;
+
+  /* UE aggregate maximum bitrate */
+  ambr_t ue_ambr;
+
+  /* Number of e_rab setup-ed in the list */
+  uint8_t       nb_e_rabs_tobeswitched;
+
+  /* list of e_rab to be switched by RRC layers */
+  e_rab_tobeswitched_t e_rabs_tobeswitched[S1AP_MAX_E_RAB];
+
+  /* Number of e_rabs to be released by RRC */
+  uint8_t        nb_e_rabs_tobereleased;
+
+  /* list of e_rabs to be released */
+  e_rab_failed_t e_rabs_tobereleased[S1AP_MAX_E_RAB];
+
+  /* Security key */
+  int     next_hop_chain_count;
+  uint8_t next_security_key[SECURITY_KEY_LENGTH];
+
+} s1ap_path_switch_req_ack_t;
 
 // S1AP --> RRC messages
 typedef struct s1ap_ue_release_command_s {
@@ -574,7 +641,7 @@ typedef struct s1ap_e_rab_modify_req_s {
   uint16_t ue_initial_id;
 
   /* MME UE id  */
-  uint16_t mme_ue_s1ap_id;
+  uint32_t mme_ue_s1ap_id;
 
   /* eNB ue s1ap id as initialized by S1AP layer */
   unsigned eNB_ue_s1ap_id:24;
@@ -607,7 +674,7 @@ typedef struct e_rab_release_s {
 
 typedef struct s1ap_e_rab_release_command_s {
   /* MME UE id  */
-  uint16_t mme_ue_s1ap_id;
+  uint32_t mme_ue_s1ap_id;
 
   /* eNB ue s1ap id as initialized by S1AP layer */
   unsigned eNB_ue_s1ap_id:24;
@@ -625,7 +692,7 @@ typedef struct s1ap_e_rab_release_command_s {
 
 typedef struct s1ap_e_rab_release_resp_s {
   /* MME UE id  */
-  uint16_t mme_ue_s1ap_id;
+  uint32_t mme_ue_s1ap_id;
 
   /* eNB ue s1ap id as initialized by S1AP layer */
   unsigned eNB_ue_s1ap_id:24;
diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h
index c74a826ff84685c88ea9a36b6226ccbf58eee166..965c614b12c3d022f5d88a7620cd9b5aab1e0956 100644
--- a/openair2/COMMON/x2ap_messages_types.h
+++ b/openair2/COMMON/x2ap_messages_types.h
@@ -132,7 +132,7 @@ typedef struct x2ap_handover_req_s {
   int source_rnti;                       /* TODO: to be fixed/remove */
   int source_x2id;                       /* TODO: to be fixed/remove */
 
-  unsigned  old_eNB_ue_s1ap_id:24;
+  int old_eNB_ue_x2ap_id;
 
   PhysCellId_t target_physCellId;
 
@@ -158,10 +158,14 @@ typedef struct x2ap_handover_req_s {
  /* list of e_rab setup-ed by RRC layers */
   e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
 
-  /* ue_context_pP->ue_context.e_rab[i].param.sgw_addr; */
+  /* list of e_rab to be setup by RRC layers */
+  e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
 
   x2ap_lastvisitedcell_info_t lastvisitedcell_info;
 
+  uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
+  int rrc_buffer_size;
+
   /* TODO: this parameter has to be removed */
   int target_mod_id;
 } x2ap_handover_req_t;
@@ -171,6 +175,15 @@ typedef struct x2ap_handover_req_ack_s {
   int source_x2id;                       /* TODO: to be fixed/remove */
   /* TODO: this parameter has to be removed */
   int target_mod_id;
+
+  uint8_t nb_e_rabs_tobesetup;
+
+ /* list of e_rab setup-ed by RRC layers */
+  e_rab_setup_t e_rabs_tobesetup[S1AP_MAX_E_RAB];
+
+  /* list of e_rab to be setup by RRC layers */
+  e_rab_t  e_rab_param[S1AP_MAX_E_RAB];
+
   uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
   int rrc_buffer_size;
 
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 51976ec0446543cf49ee81da45c9b3d1579707a0..17746637e93f6cad89a382c01ce17a4bf6ac02e7 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -2294,6 +2294,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) {
 
 	      if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
 		S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv4 = 1;
+		S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 0;
 	      } else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
 		S1AP_REGISTER_ENB_REQ (msg_p).mme_ip_address[l].ipv6 = 1;
 	      } else if (strcmp(*(S1ParamList.paramarray[l][ENB_MME_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index 0b4f05a56e1883374afc17d50a35d9ee7a69bd4e..2dc4c63297bcb1524ea5a082152169d176e2dbcf 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -896,6 +896,20 @@ rrc_mac_config_req_eNB(module_id_t Mod_idP,
     }
   } // mib != NULL
 
+  if (mobilityControlInfo !=NULL){
+     if ((UE_id = add_new_ue(Mod_idP, CC_idP,
+                             rntiP, -1
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                             ,
+                             -1
+#endif
+                             )) == -1)
+     {
+       LOG_E(MAC, "%s:%d: fatal\n", __FILE__, __LINE__);
+       abort();
+     }
+  }
+
   // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup
   if (logicalChannelConfig != NULL) {	// check for eMTC specific things
     UE_id = find_UE_id(Mod_idP, rntiP);
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
index 31c11e2c0a942fb42d882132644bcc0376ba148d..336ccf5c4930a275e9bcbe84d094470752c650c8 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c
@@ -323,51 +323,75 @@ rx_sdu(const module_id_t enb_mod_idP,
 	//cancel_ra_proc(enb_mod_idP, CC_idP, frameP,
 	//	       current_rnti);
 	if (old_UE_id != -1) {
-	  /* TODO: if the UE did random access (followed by a MAC uplink with
-	   * CRNTI) because none of its scheduling request was granted, then
-	   * according to 36.321 5.4.4 the UE's MAC will notify RRC to release
-	   * PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply
-	   * default configuration for CQI reporting and scheduling requests,
-	   * which basically means that the CQI requests won't work anymore and
-	   * that the UE won't do any scheduling request anymore as long as the
-	   * eNB doesn't reconfigure the UE.
-	   * We have to take care of this. As the code is, nothing is done and
-	   * the UE state in the eNB is wrong.
-	   */
-          for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
-            ra = &mac->common_channels[CC_idP].ra[ii];
-            if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
-              mac_rrc_data_ind(enb_mod_idP,
-                               CC_idP,
-                               frameP, subframeP,
-                               old_rnti,
-                               DCCH,
-                               (uint8_t *) payload_ptr,
-                               rx_lengths[i],
-                               0);
-              // prepare transmission of Msg4(RRCConnectionReconfiguration)
-              ra->state = MSGCRNTI;
-              LOG_I(MAC,
-                    "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n",
-                    enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
-
-              UE_id = old_UE_id;
-              current_rnti = old_rnti;
-              ra->rnti = old_rnti;
-              ra->crnti_rrc_mui = rrc_eNB_mui-1;
-              ra->crnti_harq_pid = -1;
-              //clear timer
-              UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
-              UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
-              UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
-              if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
-                UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
-                mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
-                                       subframeP, old_rnti);
+
+          if (mac_eNB_get_rrc_status(enb_mod_idP,old_rnti) ==  RRC_HO_EXECUTION) {
+                LOG_I(MAC,
+                      "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) Handover case\n",
+                      enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
+
+                UE_id = old_UE_id;
+                current_rnti = old_rnti;
+                //clear timer
+                UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
+                UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
+                UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
+                if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
+                  UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
+                  mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
+                                         subframeP, old_rnti);
+                }
+                UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
+                UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
+                UE_list->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1;
+                cancel_ra_proc(enb_mod_idP, CC_idP, frameP,current_rnti);
+          }
+          else {
+	    /* TODO: if the UE did random access (followed by a MAC uplink with
+	     * CRNTI) because none of its scheduling request was granted, then
+	     * according to 36.321 5.4.4 the UE's MAC will notify RRC to release
+	     * PUCCH/SRS. According to 36.331 5.3.13 the UE will then apply
+	     * default configuration for CQI reporting and scheduling requests,
+	     * which basically means that the CQI requests won't work anymore and
+	     * that the UE won't do any scheduling request anymore as long as the
+	     * eNB doesn't reconfigure the UE.
+	     * We have to take care of this. As the code is, nothing is done and
+	     * the UE state in the eNB is wrong.
+	     */
+            for (ii = 0; ii < NB_RA_PROC_MAX; ii++) {
+              ra = &mac->common_channels[CC_idP].ra[ii];
+              if ((ra->rnti == current_rnti) && (ra->state != IDLE)) {
+                mac_rrc_data_ind(enb_mod_idP,
+                                 CC_idP,
+                                 frameP, subframeP,
+                                 old_rnti,
+                                 DCCH,
+                                 (uint8_t *) payload_ptr,
+                                 rx_lengths[i],
+                                 0);
+                // prepare transmission of Msg4(RRCConnectionReconfiguration)
+                ra->state = MSGCRNTI;
+                LOG_I(MAC,
+                      "[eNB %d] Frame %d, Subframe %d CC_id %d : (rnti %x UE_id %d) RRCConnectionReconfiguration(Msg4)\n",
+                      enb_mod_idP, frameP, subframeP, CC_idP, old_rnti, old_UE_id);
+
+                UE_id = old_UE_id;
+                current_rnti = old_rnti;
+                ra->rnti = old_rnti;
+                ra->crnti_rrc_mui = rrc_eNB_mui-1;
+                ra->crnti_harq_pid = -1;
+                //clear timer
+                UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0;
+                UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer = 0;
+                UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0;
+                if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
+                  UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 0;
+                  mac_eNB_rrc_ul_in_sync(enb_mod_idP, CC_idP, frameP,
+                                         subframeP, old_rnti);
+                }
+                UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
+                UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
+                break;
               }
-              UE_list->UE_template[CC_idP][UE_id].ul_SR = 1;
-              UE_list->UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 1;
-              break;
             }
           }
         } else {
diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
index 5e07d9e936243594e6aaedf9ac8bc17b6944d9d7..c0bee6fe579d8e6b21984bc4542e1cab8797b8bf 100644
--- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c
@@ -52,6 +52,8 @@
 #include "RRCConnectionSetup.h"
 #include "SRB-ToAddModList.h"
 #include "DRB-ToAddModList.h"
+#include "HandoverPreparationInformation.h"
+#include "HandoverCommand.h"
 #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
 #include "MCCH-Message.h"
 //#define MRB1 1
@@ -2386,6 +2388,7 @@ do_RRCConnectionReconfiguration(
   MAC_MainConfig_t                   *mac_MainConfig,
   MeasGapConfig_t                    *measGapConfig,
   MobilityControlInfo_t              *mobilityInfo,
+  SecurityConfigHO_t                 *securityConfigHO,
   struct MeasConfig__speedStatePars  *speedStatePars,
   RSRP_Range_t                       *rsrp,
   C_RNTI_t                           *cba_rnti,
@@ -2485,8 +2488,16 @@ do_RRCConnectionReconfiguration(
     rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.mobilityControlInfo  = NULL;
   }
 
+  if (securityConfigHO != NULL) {
+    rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO     = CALLOC(1,
+        sizeof(*rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO));
+    memcpy((void*)rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO, (void*)securityConfigHO,
+           sizeof(SecurityConfigHO_t));
+  } else {
+    rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO     = NULL;
+  }
+
   rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.dedicatedInfoNASList = dedicatedInfoNASList;
-  rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.securityConfigHO     = NULL;
 
   //TTN for D2D
   //allocate dedicated resource pools for SL communication (sl_CommConfig_r12)
@@ -2545,7 +2556,7 @@ do_RRCConnectionReconfiguration(
 #if defined(ENABLE_ITTI)
 # if !defined(DISABLE_XER_SPRINT)
   {
-    char        message_string[30000];
+    char        message_string[40000];
     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) {
@@ -3368,6 +3379,88 @@ uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t
   return encoded;
 }
 
+int do_HandoverPreparation(char *ho_buf, int ho_size, UE_EUTRA_Capability_t *ue_eutra_cap, int rrc_size)
+{
+  asn_enc_rval_t enc_rval;
+  HandoverPreparationInformation_t ho;
+  HandoverPreparationInformation_r8_IEs_t *ho_info;
+  UE_CapabilityRAT_Container_t *ue_cap_rat_container;
+
+  char rrc_buf[rrc_size];
+
+  memset(rrc_buf, 0, rrc_size);
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_UE_EUTRA_Capability,
+                                   NULL,
+                                   ue_eutra_cap,
+                                   rrc_buf,
+                                   rrc_size);
+
+  /* TODO: free the OCTET_STRING */
+
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+
+  memset(&ho, 0, sizeof(ho));
+
+  ho.criticalExtensions.present = HandoverPreparationInformation__criticalExtensions_PR_c1;
+  ho.criticalExtensions.choice.c1.present = HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8;
+
+  ho_info = &ho.criticalExtensions.choice.c1.choice.handoverPreparationInformation_r8;
+  {
+      ue_cap_rat_container = (UE_CapabilityRAT_Container_t *)calloc(1,sizeof(UE_CapabilityRAT_Container_t));
+      ue_cap_rat_container->rat_Type = RAT_Type_eutra;
+
+      AssertFatal (OCTET_STRING_fromBuf(
+                   &ue_cap_rat_container->ueCapabilityRAT_Container,
+                   rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
+
+      ASN_SEQUENCE_ADD(&ho_info->ue_RadioAccessCapabilityInfo.list, ue_cap_rat_container);
+  }
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_HandoverPreparationInformation,
+                                   NULL,
+                                   &ho,
+                                   ho_buf,
+                                   ho_size);
+
+  /* TODO: free the OCTET_STRING */
+
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  return((enc_rval.encoded+7)/8);
+}
+
+int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size)
+{
+  asn_enc_rval_t enc_rval;
+  HandoverCommand_t ho;
+
+  memset(&ho, 0, sizeof(ho));
+
+  ho.criticalExtensions.present = HandoverCommand__criticalExtensions_PR_c1;
+  ho.criticalExtensions.choice.c1.present = HandoverCommand__criticalExtensions__c1_PR_handoverCommand_r8;
+
+  AssertFatal (OCTET_STRING_fromBuf(
+               &ho.criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage,
+               rrc_buf, rrc_size) != -1, "fatal: OCTET_STRING_fromBuf failed\n");
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_HandoverCommand,
+                                   NULL,
+                                   &ho,
+                                   ho_buf,
+                                   ho_size);
+
+  /* TODO: free the OCTET_STRING */
+
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  return((enc_rval.encoded+7)/8);
+}
+
 OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer_fname)
 {
   static OAI_UECapability_t UECapability; /* TODO declared static to allow returning this has an address should be allocated in a cleaner way. */
diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h
index a4da38c0196a23efc250e90ac9f4d3fa3d1d83bc..6027a5bc34b73627cef02fd773193c5600172cbe 100644
--- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h
@@ -192,6 +192,7 @@ do_RRCConnectionReconfiguration(
     MAC_MainConfig_t                   *mac_MainConfig,
     MeasGapConfig_t                    *measGapConfig,
     MobilityControlInfo_t              *mobilityInfo,
+    SecurityConfigHO_t                 *securityConfigHO,
     struct MeasConfig__speedStatePars  *speedStatePars,
     RSRP_Range_t                       *rsrp,
     C_RNTI_t                           *cba_rnti,
@@ -282,6 +283,10 @@ uint8_t do_Paging(uint8_t Mod_id, uint8_t *buffer, ue_paging_identity_t ue_pagin
 
 uint8_t do_ULInformationTransfer(uint8_t **buffer, uint32_t pdu_length, uint8_t *pdu_buffer);
 
+int do_HandoverPreparation(char *ho_buf, int ho_size, UE_EUTRA_Capability_t *ue_eutra_cap, int rrc_size);
+
+int do_HandoverCommand(char *ho_buf, int ho_size, char *rrc_buf, int rrc_size);
+
 OAI_UECapability_t *fill_ue_capability(char *UE_EUTRA_Capability_xer);
 
 uint8_t
diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h
index e21cb9255a6a0cc7cb275b3c21230383ae987820..d94f6583053db15851f38d222938c36ae93303c1 100644
--- a/openair2/RRC/LTE/rrc_defs.h
+++ b/openair2/RRC/LTE/rrc_defs.h
@@ -344,10 +344,13 @@ typedef enum UE_STATE_e {
 
 typedef enum HO_STATE_e {
   HO_IDLE=0,
-  HO_MEASURMENT,
+  HO_MEASUREMENT,
   HO_PREPARE,
   HO_CMD, // initiated by the src eNB
-  HO_COMPLETE // initiated by the target eNB
+  HO_COMPLETE, // initiated by the target eNB
+  HO_REQUEST,
+  HO_ACK,
+  HO_CONFIGURED
 } HO_STATE_t;
 
 typedef enum SL_TRIGGER_e {
@@ -433,6 +436,7 @@ typedef enum e_rab_satus_e {
   E_RAB_STATUS_NEW,
   E_RAB_STATUS_DONE, // from the eNB perspective
   E_RAB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
+  E_RAB_STATUS_REESTABLISHED, // after HO
   E_RAB_STATUS_FAILED,
   E_RAB_STATUS_TORELEASE  // to release DRB between eNB and UE
 } e_rab_status_t;
@@ -446,14 +450,13 @@ typedef struct e_rab_param_s {
 } __attribute__ ((__packed__)) e_rab_param_t;
 #endif
 
-
-
 /* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */
 typedef struct HANDOVER_INFO_s {
   uint8_t ho_prepare;
   uint8_t ho_complete;
-  uint8_t modid_s; //module_idP of serving cell
-  uint8_t modid_t; //module_idP of target cell
+  HO_STATE_t state; //current state of handover
+  uint32_t modid_s; //module_idP of serving cell
+  uint32_t modid_t; //module_idP of target cell
   uint8_t ueid_s; //UE index in serving cell
   uint8_t ueid_t; //UE index in target cell
   AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */
@@ -511,6 +514,14 @@ typedef struct HANDOVER_INFO_UE_s {
   uint8_t measFlag;
 } HANDOVER_INFO_UE;
 
+typedef struct rrc_gummei_s {
+  uint16_t mcc;
+  uint16_t mnc;
+  uint8_t  mnc_len;
+  uint8_t  mme_code;
+  uint16_t mme_group_id;
+} rrc_gummei_t;
+
 typedef struct eNB_RRC_UE_s {
   uint8_t                            primaryCC_id;
 #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
@@ -537,8 +548,10 @@ typedef struct eNB_RRC_UE_s {
   MeasConfig_t*                      measConfig;
   HANDOVER_INFO*                     handover_info;
   MeasResults_t*                     measResults;
+  MobilityControlInfo_t*             mobilityInfo;
 
   UE_EUTRA_Capability_t*             UE_Capability;
+  int                                UE_Capability_size;
   ImsiMobileIdentity_t               imsi;
 
 #if defined(ENABLE_SECURITY)
@@ -570,8 +583,15 @@ typedef struct eNB_RRC_UE_s {
   /* Information from S1AP initial_context_setup_req */
   uint32_t                           eNB_ue_s1ap_id :24;
 
+  uint32_t                           mme_ue_s1ap_id;
+  rrc_gummei_t                       ue_gummei;
+
   security_capabilities_t            security_capabilities;
 
+  int                                next_hop_chain_count;
+
+  uint8_t                            next_security_key[SECURITY_KEY_LENGTH];
+
   /* Total number of e_rab already setup in the list */
   uint8_t                           setup_e_rabs;
   /* Number of e_rab to be setup in the list */
@@ -582,8 +602,12 @@ typedef struct eNB_RRC_UE_s {
   e_rab_param_t                      modify_e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
   /* list of e_rab to be setup by RRC layers */
   e_rab_param_t                      e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB];
+  /* UE aggregate maximum bitrate */
+  ambr_t ue_ambr;
   //release e_rabs
   uint8_t                            nb_release_of_e_rabs;
+  /* list of e_rab to be released by RRC layers */
+  uint8_t                            e_rabs_tobereleased[NB_RB_MAX];
   e_rab_failed_t                     e_rabs_release_failed[S1AP_MAX_E_RAB];
   // LG: For GTPV1 TUNNELS
   uint32_t                           enb_gtp_teid[S1AP_MAX_E_RAB];
@@ -639,6 +663,8 @@ typedef struct {
   int                               p_eNB;
   uint32_t                          dl_CarrierFreq;
   uint32_t                          ul_CarrierFreq;
+  uint32_t                          eutra_band;
+  uint32_t                          N_RB_DL;
   uint32_t                          pbch_repetition;
   BCCH_BCH_Message_t                mib;
   BCCH_DL_SCH_Message_t             siblock1;
diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c
index e62596aed610a927cb5a31e7583bae215ee238f2..37ca828e86275a40d3737b768fb3c0a3966a5ffb 100644
--- a/openair2/RRC/LTE/rrc_eNB.c
+++ b/openair2/RRC/LTE/rrc_eNB.c
@@ -53,6 +53,7 @@
 #include "UL-DCCH-Message.h"
 #include "DL-DCCH-Message.h"
 #include "TDD-Config.h"
+#include "HandoverPreparationInformation.h"
 #include "HandoverCommand.h"
 #include "rlc.h"
 #include "rrc_eNB_UE_context.h"
@@ -118,6 +119,8 @@ extern uint16_t                     two_tier_hexagonal_cellIds[7];
 
 mui_t                               rrc_eNB_mui = 0;
 
+extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
+
 void
 openair_rrc_on(
   const protocol_ctxt_t* const ctxt_pP
@@ -165,6 +168,8 @@ init_SI(
   RC.rrc[ctxt_pP->module_id]->carrier[CC_id].Ncp             = configuration->prefix_type[CC_id];
   RC.rrc[ctxt_pP->module_id]->carrier[CC_id].dl_CarrierFreq  = configuration->downlink_frequency[CC_id];
   RC.rrc[ctxt_pP->module_id]->carrier[CC_id].ul_CarrierFreq  = configuration->downlink_frequency[CC_id]+ configuration->uplink_frequency_offset[CC_id];
+  RC.rrc[ctxt_pP->module_id]->carrier[CC_id].eutra_band      = configuration->eutra_band[CC_id];
+  RC.rrc[ctxt_pP->module_id]->carrier[CC_id].N_RB_DL         = configuration->N_RB_DL[CC_id];
 #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
   RC.rrc[ctxt_pP->module_id]->carrier[CC_id].pbch_repetition = configuration->pbch_repetition[CC_id];
 #endif
@@ -1602,7 +1607,7 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
 
   ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1);
 
-  if (RC.rrc[ctxt_pP->module_id]->HO_flag == 1 /*HO_MEASURMENT */ ) {
+  if (RC.rrc[ctxt_pP->module_id]->HO_flag == 1 /*HO_MEASUREMENT */ ) {
     LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, A5, and A6 event reporting\n",
           ctxt_pP->module_id, ctxt_pP->frame);
     ReportConfig_A2->reportConfigId = 3;
@@ -1828,6 +1833,7 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete(
                                          (MAC_MainConfig_t*)ue_context_pP->ue_context.mac_MainConfig,
                                          (MeasGapConfig_t*)NULL,
                                          (MobilityControlInfo_t*)NULL,
+                                         (SecurityConfigHO_t *)NULL,
                                          (struct MeasConfig__speedStatePars*)Sparams, // Sparams,
                                          (RSRP_Range_t*)rsrp, // rsrp,
                                          (C_RNTI_t*)cba_RNTI,  // cba_RNTI
@@ -2283,7 +2289,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* co
 					  (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
                                          (struct SPS_Config*)NULL,    // *sps_Config,
 					  NULL, NULL, NULL, NULL,NULL,
-					  NULL, NULL,  NULL, NULL, NULL, NULL, 
+					  NULL, NULL,  NULL, NULL, NULL, NULL, NULL,
 					  (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
 					  (SL_CommConfig_r12_t*)NULL,
 					  (SL_DiscConfig_r12_t*)NULL
@@ -2546,7 +2552,7 @@ rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t* cons
 					  (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
                                          (struct SPS_Config*)NULL,    // *sps_Config,
 					  NULL, NULL, NULL, NULL,NULL,
-					  NULL, NULL,  NULL, NULL, NULL, NULL, 
+					  NULL, NULL,  NULL, NULL, NULL, NULL, NULL,
 					  (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
 					  (SL_CommConfig_r12_t*)NULL,
 					  (SL_DiscConfig_r12_t*)NULL
@@ -2665,6 +2671,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_release(  const protocol_
                                     NULL,
                                     NULL,
                                     NULL,
+                                    NULL,
                                     (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
                                     (SL_CommConfig_r12_t*)NULL,
                                     (SL_DiscConfig_r12_t*)NULL
@@ -2768,8 +2775,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
   RSRP_Range_t                       *rsrp                             = NULL;
   struct MeasConfig__speedStatePars  *Sparams                          = NULL;
   QuantityConfig_t                   *quantityConfig                   = NULL;
-  CellsToAddMod_t                    *CellToAdd                        = NULL;
-  CellsToAddModList_t                *CellsToAddModList                = NULL;
+
+  //CellsToAddMod_t                    *CellToAdd                        = NULL;
+  //CellsToAddModList_t                *CellsToAddModList                = NULL;
   struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL;
   DedicatedInfoNAS_t                 *dedicatedInfoNas                 = NULL;
   /* for no gcc warnings */
@@ -3111,8 +3119,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
 
   MeasObj->measObjectId = 1;
   MeasObj->measObject.present = MeasObjectToAddMod__measObject_PR_measObjectEUTRA;
-  MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 3350; //band 7, 2.68GHz
-  //MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = 36090; //band 33, 1.909GHz
+  MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = (ARFCN_ValueEUTRA_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq, RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL);
   MeasObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth = AllowedMeasBandwidth_mbw25;
   MeasObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1 = 1;
   MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf = CALLOC(1, sizeof(uint8_t));
@@ -3121,20 +3128,20 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
   MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6;
   MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL;   // Default is 15 or 0dB
 
-  MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList =
-    (CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList));
+  //MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList =
+    //(CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList));
 
-  CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList;
+  //CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList;
 
   // Add adjacent cell lists (6 per eNB)
-  for (i = 0; i < 6; i++) {
-    CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd));
-    CellToAdd->cellIndex = i + 1;
-    CellToAdd->physCellId = get_adjacent_cell_id(ctxt_pP->module_id, i);
-    CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0;
+  //for (i = 0; i < 6; i++) {
+    //CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd));
+    //CellToAdd->cellIndex = 1;//i + 1;
+    //CellToAdd->physCellId = 1;//get_adjacent_cell_id(ctxt_pP->module_id, i);
+    //CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0;
 
-    ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd);
-  }
+    //ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd);
+  //}
 
   ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj);
   //  rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list;
@@ -3187,8 +3194,8 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
 
   ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1);
   
-  if (ho_state == 1 /*HO_MEASURMENT */ ) {
-    LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, A5, and A6 event reporting\n",
+//  if (ho_state == 1 /*HO_MEASUREMENT */ ) {
+    LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, and A5 event reporting\n",
           ctxt_pP->module_id, ctxt_pP->frame);
     ReportConfig_A2->reportConfigId = 3;
     ReportConfig_A2->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
@@ -3217,7 +3224,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
     ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present =
       ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3;
 
-    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = 1;   //10;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = 0;   //10;
     ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
     eventA3.reportOnLeave = 1;
 
@@ -3228,7 +3235,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
     ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
     ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
 
-    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis = 0.5; // FIXME ...hysteresis is of type long!
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis = 0; // FIXME ...hysteresis is of type long!
     ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger =
       TimeToTrigger_ms40;
     ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A3);
@@ -3304,6 +3311,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
     *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = FilterCoefficient_fc4;
     *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = FilterCoefficient_fc4;
 
+#if 0
     LOG_I(RRC,
           "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n",
           ctxt_pP->module_id, ctxt_pP->frame);
@@ -3325,8 +3333,9 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
            (void*)ue_context_pP->ue_context.physicalConfigDedicated, sizeof(PhysicalConfigDedicated_t));
     ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.sps_Config = NULL;
     //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.sps_Config,(void *)rrc_inst->sps_Config[ue_mod_idP],sizeof(SPS_Config_t));
+#endif
 
-  }
+//  }
 
 #if defined(ENABLE_ITTI)
   /* Initialize NAS list */
@@ -3374,17 +3383,18 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t* cons
                                          (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
                                          (struct SPS_Config*)NULL,    // *sps_Config,
                                          (struct PhysicalConfigDedicated*)*physicalConfigDedicated,
-#ifdef EXMIMO_IOT
-                                         NULL, NULL, NULL,NULL,
-#else
+//#ifdef EXMIMO_IOT
+//                                         NULL, NULL, NULL,NULL,
+//#else
                                          (MeasObjectToAddModList_t*)MeasObj_list,
                                          (ReportConfigToAddModList_t*)ReportConfig_list,
                                          (QuantityConfig_t*)quantityConfig,
                                          (MeasIdToAddModList_t*)MeasId_list,
-#endif
+//#endif
                                          (MAC_MainConfig_t*)mac_MainConfig,
                                          (MeasGapConfig_t*)NULL,
                                          (MobilityControlInfo_t*)NULL,
+                                         (SecurityConfigHO_t*)NULL,
                                          (struct MeasConfig__speedStatePars*)Sparams,
                                          (RSRP_Range_t*)rsrp,
                                          (C_RNTI_t*)cba_RNTI,
@@ -3970,6 +3980,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
                                          (MAC_MainConfig_t*)mac_MainConfig,
                                          (MeasGapConfig_t*)NULL,
                                          (MobilityControlInfo_t*)NULL,
+                                         (SecurityConfigHO_t*)NULL,
                                          (struct MeasConfig__speedStatePars*)Sparams,
                                          (RSRP_Range_t*)rsrp,
                                          (C_RNTI_t*)cba_RNTI,
@@ -4068,6 +4079,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_SCell(
                                          (MAC_MainConfig_t*)NULL,
                                          (MeasGapConfig_t*)NULL,
                                          (MobilityControlInfo_t*)NULL,
+                                         (SecurityConfigHO_t*)NULL,
                                          (struct MeasConfig__speedStatePars*)NULL,
                                          (RSRP_Range_t*)NULL,
                                          (C_RNTI_t*)NULL,
@@ -4117,6 +4129,9 @@ rrc_eNB_process_MeasurementReport(
   int i=0;
   int neighboring_cells=-1;
   
+  int ncell_index = 0;
+  long ncell_max = -150;
+
   T(T_ENB_RRC_MEASUREMENT_REPORT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
@@ -4127,11 +4142,38 @@ rrc_eNB_process_MeasurementReport(
      if (ue_context_pP->ue_context.measResults == NULL) {
        ue_context_pP->ue_context.measResults = CALLOC(1, sizeof(MeasResults_t));
      }
-     ue_context_pP->ue_context.measResults->measId=measResults2->measId; 
+     ue_context_pP->ue_context.measResults->measId=measResults2->measId;
+
+     switch (measResults2->measId) {
+       case 1:
+         LOG_D(RRC,"Periodic report at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+       case 2:
+         LOG_D(RRC,"A1 event report (Serving becomes better than absolute threshold) at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+       case 3:
+         LOG_D(RRC,"A2 event report (Serving becomes worse than absolute threshold) at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+       case 4:
+         LOG_D(RRC,"A3 event report (Neighbour becomes amount of offset better than PCell) at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+       case 5:
+         LOG_D(RRC,"A4 event report (Neighbour becomes better than absolute threshold) at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+       case 6:
+         LOG_D(RRC,"A5 event report (PCell becomes worse than absolute threshold1 AND Neighbour becomes better than another absolute threshold2) at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+       default:
+         LOG_D(RRC,"Other event report frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+         break;
+     }
+
      ue_context_pP->ue_context.measResults->measResultPCell.rsrpResult=measResults2->measResultPCell.rsrpResult;
      ue_context_pP->ue_context.measResults->measResultPCell.rsrqResult=measResults2->measResultPCell.rsrqResult;
      LOG_D(RRC, "[eNB %d]Frame %d: UE %x (Measurement Id %d): RSRP of Source %ld\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, (int)measResults2->measId, ue_context_pP->ue_context.measResults->measResultPCell.rsrpResult-140);
      LOG_D(RRC, "[eNB %d]Frame %d: UE %x (Measurement Id %d): RSRQ of Source %ld\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, (int)measResults2->measId, ue_context_pP->ue_context.measResults->measResultPCell.rsrqResult/2 - 20);
+     //LOG_D(RRC, "[eNB %d]Frame %d: UE %x (Measurement Id2 %d): RSRP of Source %ld\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, (int)measResults2->measId, measResults2->measResultPCell.rsrpResult-140);
+     //LOG_D(RRC, "[eNB %d]Frame %d: UE %x (Measurement Id2 %d): RSRQ of Source %ld\n", ctxt_pP->module_id, ctxt_pP->frame, ctxt_pP->rnti, (int)measResults2->measId, measResults2->measResultPCell.rsrqResult/2 - 20);
    }
    if (measResults2->measResultNeighCells == NULL)
      return;
@@ -4140,58 +4182,145 @@ rrc_eNB_process_MeasurementReport(
      neighboring_cells = measResults2->measResultNeighCells->choice.measResultListEUTRA.list.count;
      
      if (ue_context_pP->ue_context.measResults->measResultNeighCells == NULL) {
-       
-       ue_context_pP->ue_context.measResults->measResultNeighCells = CALLOC(1, sizeof(*measResults2->measResultNeighCells)*neighboring_cells);
+       ue_context_pP->ue_context.measResults->measResultNeighCells = CALLOC(1, sizeof(*ue_context_pP->ue_context.measResults->measResultNeighCells));
      }
-     ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count = neighboring_cells;
+
      for (i=0; i < neighboring_cells; i++){
-       memcpy (ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i],
-	       measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i],
-	       sizeof(MeasResultListEUTRA_t));
        
+       if (i>=ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count) {
+         //printf("NeighCells number: %d \n", ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.count);
+         ASN_SEQUENCE_ADD(&ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list,measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]);
+       }
+
+       ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->physCellId =
+         measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->physCellId;
+
+       ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrpResult =
+         measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrpResult;
+
+       ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrqResult =
+         measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrqResult;
+
        LOG_D(RRC, "Physical Cell Id %d\n",
 	     (int)ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->physCellId);
-       LOG_D(RRC, "RSRP of Target %d\n",
-	     (int)*(ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrpResult));
-       LOG_D(RRC, "RSRQ of Target %d\n",
-	     (int)*(ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrqResult));
+       LOG_D(RRC, "RSRP of Target %ld\n",
+	     (*ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrpResult)-140);
+       LOG_D(RRC, "RSRQ of Target %ld\n",
+	     (*ue_context_pP->ue_context.measResults->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrqResult)/2 - 20);
+
+       if ( *measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrpResult >= ncell_max ) {
+         ncell_max = *measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->measResult.rsrpResult;
+         ncell_index = i;
+       }
+       //LOG_D(RRC, "Physical Cell Id2 %d\n",
+            //(int)measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->physCellId);
+       //LOG_D(RRC, "RSRP of Target2 %ld\n",
+            //(*(measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->
+                                                 //measResult.rsrpResult))-140);
+       //LOG_D(RRC, "RSRQ of Target2 %ld\n",
+            //(*(measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[i]->
+                                                 //measResult.rsrqResult))/2 - 20);
      }
    }
 
-// #if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
-
+  /* Decide whether to trigger HO or not */
+  if (!(measResults2->measId == 4))
+    return;
   
-// #else
-  // LOG_I(RRC, "RSRP of Source %d\n", measResults2->measResultServCell.rsrpResult);
-  // LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult);
-// #endif
+  LOG_D(RRC, "A3 event is triggered...\n");
 
-  // if (ue_context_pP->ue_context.handover_info->ho_prepare != 0xF0) {
-  //   rrc_eNB_generate_HandoverPreparationInformation(ctxt_pP,
-  //       ue_context_pP,
-  //       measResults2->measResultNeighCells->choice.
-  //       measResultListEUTRA.list.array[0]->physCellId);
-  // } else {
-  //   LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame,
-  //         ctxt_pP->rnti);
-  // }
-
-  //Look for IP address of the target eNB
-  //Send Handover Request -> target eNB
-  //Wait for Handover Acknowledgement <- target eNB
-  //Send Handover Command
-
-  //x2delay();
-  //    handover_request_x2(ue_mod_idP,enb_mod_idP,measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId);
-
-  //    uint8_t buffer[100];
-  //    int size=rrc_eNB_generate_Handover_Command_TeNB(0,0,buffer);
-  //
-  //      send_check_message((char*)buffer,size);
-  //send_handover_command();
+  /* if the UE is not in handover mode, start handover procedure */
+  if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) {
+    MessageDef      *msg;
+
+    LOG_I(RRC, "Send HO preparation message at frame %d and subframe %d \n", ctxt_pP->frame, ctxt_pP->subframe);
+
+    /* HO info struct may not be needed anymore */
+    ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info)));
+
+    ue_context_pP->ue_context.Status = RRC_HO_EXECUTION;
+
+    ue_context_pP->ue_context.handover_info->state = HO_REQUEST;
+
+    /* HO Preparation message */
+
+    msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ);
+
+    rrc_eNB_generate_HandoverPreparationInformation(
+           ue_context_pP,
+           X2AP_HANDOVER_REQ(msg).rrc_buffer,
+           &X2AP_HANDOVER_REQ(msg).rrc_buffer_size);
+
+
+    X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
+    X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = 0;
+    X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
+                                               measResultListEUTRA.list.array[ncell_index]->physCellId;
+
+    X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc;
+    X2AP_HANDOVER_REQ(msg).ue_gummei.mnc = ue_context_pP->ue_context.ue_gummei.mnc;
+    X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len = ue_context_pP->ue_context.ue_gummei.mnc_len;
+    X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code = ue_context_pP->ue_context.ue_gummei.mme_code;
+    X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id = ue_context_pP->ue_context.ue_gummei.mme_group_id;
+
+    // Don't know how to get this ID?
+    X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id;
+
+    X2AP_HANDOVER_REQ(msg).security_capabilities = ue_context_pP->ue_context.security_capabilities;
+
+    memcpy (X2AP_HANDOVER_REQ(msg).kenb,
+	    ue_context_pP->ue_context.kenb,
+	    32);
+    X2AP_HANDOVER_REQ(msg).kenb_ncc = ue_context_pP->ue_context.kenb_ncc;
+
+    //X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr;
+
+    X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ue_context_pP->ue_context.setup_e_rabs;
+
+    for (int i=0;i<ue_context_pP->ue_context.setup_e_rabs;i++) {
+	X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = ue_context_pP->ue_context.e_rab[i].param.e_rab_id;
+	X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr = ue_context_pP->ue_context.e_rab[i].param.sgw_addr;
+	X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid = ue_context_pP->ue_context.e_rab[i].param.gtp_teid;
+        X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = ue_context_pP->ue_context.e_rab[i].param.qos.qci;
+        X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level;
+        X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_capability;
+        X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.pre_emp_vulnerability;
+    }
+
+    /* TODO: don't do that, X2AP should find the target by itself */
+    //X2AP_HANDOVER_REQ(msg).target_mod_id = 0;
+
+    LOG_I(RRC,
+          "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n",
+          ctxt_pP->module_id, ctxt_pP->frame);
+
+    itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
+  } else {
+    LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame,
+          ctxt_pP->rnti);
+  }
+}
+
+//-----------------------------------------------------------------------------
+void
+rrc_eNB_generate_HandoverPreparationInformation(
+  //const protocol_ctxt_t* const ctxt_pP,
+  rrc_eNB_ue_context_t* const ue_context_pP,
+  uint8_t*                     buffer,
+  int                          *_size
+)
+{
+  memset(buffer, 0, RRC_BUF_SIZE);
+
+  char *ho_buf = (char*) buffer;
+  int ho_size;
 
+  ho_size = do_HandoverPreparation(ho_buf, 1024, ue_context_pP->ue_context.UE_Capability, ue_context_pP->ue_context.UE_Capability_size);
+
+  *_size = ho_size;
 }
 
+#if 0
 //-----------------------------------------------------------------------------
 void
 rrc_eNB_generate_HandoverPreparationInformation(
@@ -4296,7 +4425,161 @@ rrc_eNB_generate_HandoverPreparationInformation(
     LOG_E(RRC, "\nError in obtaining Module ID of target eNB for handover \n");
   }
 }
+#endif
+
+void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m)
+{
+  struct rrc_eNB_ue_context_s*        ue_context_target_p = NULL;
+  /* TODO: get proper UE rnti */
+  int rnti = taus() & 0xffff;
+  int i;
+  //global_rnti = rnti;
+  //HandoverPreparationInformation_t *ho = NULL;
+  //HandoverPreparationInformation_r8_IEs_t *ho_info;
+  //asn_dec_rval_t                      dec_rval;
+
+  ue_context_target_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
+  if (ue_context_target_p != NULL) {
+    LOG_E(RRC, "\nError in obtaining free UE id in target eNB for handover \n");
+    return;
+  }
+
+  ue_context_target_p = rrc_eNB_allocate_new_UE_context(RC.rrc[mod_id]);
+  if (ue_context_target_p == NULL) {
+    LOG_E(RRC, "Cannot create new UE context\n");
+    return;
+  }
+
+  ue_context_target_p->ue_id_rnti = rnti;
+  ue_context_target_p->ue_context.rnti = rnti;
+
+  RB_INSERT(rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head, ue_context_target_p);
+  LOG_D(RRC, "eNB %d: Created new UE context uid %u\n", mod_id, ue_context_target_p->local_uid);
+
+  ue_context_target_p->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info)));
+  //ue_context_target_p->ue_context.handover_info->source_x2id = m->source_x2id;
+  ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION;
+  ue_context_target_p->ue_context.handover_info->state = HO_ACK;
+
+  /* TODO: remove this hack */
+  //ue_context_target_p->ue_context.handover_info->modid_t = mod_id;
+  ue_context_target_p->ue_context.handover_info->modid_t = m->target_mod_id;
+  //ue_context_target_p->ue_context.handover_info->modid_s = 1-mod_id;
+  //ue_context_target_p->ue_context.handover_info->ueid_s  = m->source_rnti;
+
+  memset (ue_context_target_p->ue_context.nh, 0, 32);
+  ue_context_target_p->ue_context.nh_ncc = -1;
+  memcpy (ue_context_target_p->ue_context.kenb, m->kenb, 32);
+  ue_context_target_p->ue_context.kenb_ncc = m->kenb_ncc;
+
+  ue_context_target_p->ue_context.security_capabilities.encryption_algorithms = m->security_capabilities.encryption_algorithms;
+  ue_context_target_p->ue_context.security_capabilities.integrity_algorithms = m->security_capabilities.integrity_algorithms;
+
+  /*
+  dec_rval = uper_decode(NULL,
+                         &asn_DEF_HandoverPreparationInformation,
+                         (void **)&ho,
+                         m->rrc_buffer,
+                         m->rrc_buffer_size, 0, 0);
+
+  if (dec_rval.code != RC_OK ||
+      ho->criticalExtensions.present != HandoverPreparationInformation__criticalExtensions_PR_c1 ||
+      ho->criticalExtensions.choice.c1.present != HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8) {
+    LOG_E(RRC, "could not decode Handover Preparation\n");
+    abort();
+  }
+
+  ho_info = &ho->criticalExtensions.choice.c1.choice.handoverPreparationInformation_r8;
+
+  if (ue_context_target_p->ue_context.UE_Capability) {
+    LOG_I(RRC, "freeing old UE capabilities for UE %x\n", rnti);
+    ASN_STRUCT_FREE(asn_DEF_UE_EUTRA_Capability,
+                    ue_context_target_p->ue_context.UE_Capability);
+    ue_context_target_p->ue_context.UE_Capability = 0;
+  }
+
+  dec_rval = uper_decode(NULL,
+                         &asn_DEF_UE_EUTRA_Capability,
+                         (void **)&ue_context_target_p->ue_context.UE_Capability,
+                         ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.buf,
+                         ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size, 0, 0);
+
+  ue_context_target_p->ue_context.UE_Capability_size = ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size;
+
+  if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
+     xer_fprint(stdout, &asn_DEF_UE_EUTRA_Capability, ue_context_target_p->ue_context.UE_Capability);
+  }
+
+  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
+      LOG_E(RRC, "Failed to decode UE capabilities (%zu bytes)\n", dec_rval.consumed);
+      ASN_STRUCT_FREE(asn_DEF_UE_EUTRA_Capability,
+                      ue_context_target_p->ue_context.UE_Capability);
+      ue_context_target_p->ue_context.UE_Capability = 0;
+  }
+  */
+
+  ue_context_target_p->ue_context.nb_of_e_rabs = m->nb_e_rabs_tobesetup;
+  ue_context_target_p->ue_context.setup_e_rabs = m->nb_e_rabs_tobesetup;
+
+  ue_context_target_p->ue_context.mme_ue_s1ap_id = m->mme_ue_s1ap_id;
+
+  ue_context_target_p->ue_context.ue_gummei.mcc = m->ue_gummei.mcc;
+  ue_context_target_p->ue_context.ue_gummei.mnc = m->ue_gummei.mnc;
+  ue_context_target_p->ue_context.ue_gummei.mnc_len = m->ue_gummei.mnc_len;
+  ue_context_target_p->ue_context.ue_gummei.mme_code = m->ue_gummei.mme_code;
+  ue_context_target_p->ue_context.ue_gummei.mme_group_id = m->ue_gummei.mme_group_id;
+
+
+  LOG_I(RRC, "eNB %d: Update the E-RABS %u\n", mod_id, ue_context_target_p->ue_context.nb_of_e_rabs);
+
+  for (i = 0; i < ue_context_target_p->ue_context.nb_of_e_rabs; i++) {
+	  ue_context_target_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW;
+	  ue_context_target_p->ue_context.e_rab[i].param.e_rab_id = m->e_rabs_tobesetup[i].e_rab_id;
+	  ue_context_target_p->ue_context.e_rab[i].param.sgw_addr = m->e_rabs_tobesetup[i].eNB_addr;
+	  ue_context_target_p->ue_context.e_rab[i].param.gtp_teid= m->e_rabs_tobesetup[i].gtp_teid;
+
+	  LOG_I(RRC, "eNB %d: Update the UE context after HO, e_rab_id %u gtp_teid %u\n", mod_id,
+			ue_context_target_p->ue_context.e_rab[i].param.e_rab_id,
+			ue_context_target_p->ue_context.e_rab[i].param.gtp_teid);
+
+  }
+
+}
+
+void rrc_eNB_process_handoverCommand(
+        int                         mod_id,
+        struct rrc_eNB_ue_context_s *ue_context,
+        x2ap_handover_req_ack_t     *m)
+{
+  asn_dec_rval_t dec_rval;
+  HandoverCommand_t *ho = NULL;
+
+  dec_rval = uper_decode(
+               NULL,
+               &asn_DEF_HandoverCommand,
+               (void**)&ho,
+               m->rrc_buffer,
+               m->rrc_buffer_size,
+               0,
+               0);
+
+  if (dec_rval.code != RC_OK ||
+      ho->criticalExtensions.present != HandoverCommand__criticalExtensions_PR_c1 ||
+      ho->criticalExtensions.choice.c1.present != HandoverCommand__criticalExtensions__c1_PR_handoverCommand_r8) {
+    LOG_E(RRC, "could not decode Handover Command\n");
+    abort();
+  }
+
+  unsigned char *buf = ho->criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage.buf;
+  int size = ho->criticalExtensions.choice.c1.choice.handoverCommand_r8.handoverCommandMessage.size;
+
+  if (size > RRC_BUF_SIZE) { printf("%s:%d: fatal\n", __FILE__, __LINE__); abort(); }
+
+  memcpy(ue_context->ue_context.handover_info->buf, buf, size);
+  ue_context->ue_context.handover_info->size = size;
+}
 
+#if 0
 //-----------------------------------------------------------------------------
 void
 rrc_eNB_process_handoverPreparationInformation(
@@ -4318,8 +4601,85 @@ rrc_eNB_process_handoverPreparationInformation(
     NULL,
     0);
 }
+#endif
+
+void
+check_handovers(
+  protocol_ctxt_t* const ctxt_pP
+)
+//-----------------------------------------------------------------------------
+{
+  int                                 result;
+  struct rrc_eNB_ue_context_s*        ue_context_p;
+  RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
+    ctxt_pP->rnti  = ue_context_p->ue_id_rnti;
+
+    if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info != NULL) {
+      /* in the source, UE in HO_PREPARE mode */
+      if (ue_context_p->ue_context.handover_info->state == HO_PREPARE) {
+        LOG_D(RRC,
+              "[eNB %d] Frame %d: Incoming handover detected for new UE_id %x) \n",
+              ctxt_pP->module_id,
+              ctxt_pP->frame,
+              ctxt_pP->rnti);
+
+        // source eNB generates rrcconnectionreconfiguration to prepare the HO
+        LOG_I(RRC,
+                "[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",
+                ctxt_pP->module_id, ctxt_pP->frame, ue_context_p->ue_context.rnti);
+
+        result = pdcp_data_req(ctxt_pP,
+                               SRB_FLAG_YES,
+                               DCCH,
+                               rrc_eNB_mui++,
+                               SDU_CONFIRM_NO,
+                               ue_context_p->ue_context.handover_info->size,
+                               ue_context_p->ue_context.handover_info->buf,
+                               PDCP_TRANSMISSION_MODE_CONTROL
+                               #if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                               ,NULL, NULL
+                               #endif
+                               );
+
+        AssertFatal(result == TRUE, "PDCP data request failed!\n");
+
+        ue_context_p->ue_context.handover_info->state = HO_COMPLETE;
+	LOG_I(RRC, "RRC Sends RRCConnectionReconfiguration to UE %d  at frame %d and subframe %d \n", ue_context_p->ue_context.rnti, ctxt_pP->frame,ctxt_pP->subframe);
+      }
+
+      /* in the target, UE in HO_ACK mode */
+      if (ue_context_p->ue_context.handover_info->state == HO_ACK) {
+        MessageDef *msg;
+        // Configure target
+        ue_context_p->ue_context.handover_info->state = HO_CONFIGURED;
+
+        msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ_ACK);
+
+        rrc_eNB_generate_HO_RRCConnectionReconfiguration(ctxt_pP, ue_context_p, X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer,
+                &X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size);
+
+        rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP);
+
+        /* TODO: remove this hack */
+        //X2AP_HANDOVER_REQ_ACK(msg).target_mod_id = 1 - ctxt_pP->module_id;
+        X2AP_HANDOVER_REQ_ACK(msg).target_mod_id = ue_context_p->ue_context.handover_info->modid_t;
+        //X2AP_HANDOVER_REQ_ACK(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id;
+
+        /* Call admission control not implemented yet */
+        X2AP_HANDOVER_REQ_ACK(msg).nb_e_rabs_tobesetup = ue_context_p->ue_context.setup_e_rabs;
+
+        for (int i=0;i<ue_context_p->ue_context.setup_e_rabs;i++) {
+          X2AP_HANDOVER_REQ_ACK(msg).e_rabs_tobesetup[i].e_rab_id = ue_context_p->ue_context.e_rab[i].param.e_rab_id;
+        }
 
+        itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
+	LOG_I(RRC, "RRC Sends X2 HO ACK to the source eNB at frame %d and subframe %d \n", ctxt_pP->frame,ctxt_pP->subframe);
+      }
+    }
+  }
+}
 
+#if 0
 //-----------------------------------------------------------------------------
 void
 check_handovers(
@@ -4380,72 +4740,1201 @@ check_handovers(
     }
   }
 }
+#endif
 
-// 5.3.5.4 RRCConnectionReconfiguration including the mobilityControlInfo to prepare the UE handover
-//-----------------------------------------------------------------------------
 void
-rrc_eNB_generate_RRCConnectionReconfiguration_handover(
-  const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_t*           const ue_context_pP,
-  uint8_t*                const nas_pdu,
-  const uint32_t                nas_length
-)
+rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP,
+						 rrc_eNB_ue_context_t*  const ue_context_pP,
+                                                 uint8_t*               buffer,
+                                                 int                    *_size
+						 //const uint8_t        ho_state
+						 )
 //-----------------------------------------------------------------------------
 {
-  T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
-    T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
-
-
-  uint8_t                             buffer[RRC_BUF_SIZE];
+  uint16_t                            size;
   int                                 i;
   uint8_t                             rv[2];
-  uint16_t                            Idx;
+
   // configure SRB1/SRB2, PhysicalConfigDedicated, MAC_MainConfig for UE
   eNB_RRC_INST*                       rrc_inst = RC.rrc[ctxt_pP->module_id];
   struct PhysicalConfigDedicated**    physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated;
+  // phy config dedicated
+  PhysicalConfigDedicated_t          *physicalConfigDedicated2;
+  // srb 1: for HO
+  struct SRB_ToAddMod                *SRB1_config                      = NULL;
+  struct SRB_ToAddMod__rlc_Config    *SRB1_rlc_config                  = NULL;
+  struct SRB_ToAddMod__logicalChannelConfig *SRB1_lchan_config         = NULL;
+  struct LogicalChannelConfig__ul_SpecificParameters
+      *SRB1_ul_SpecificParameters       = NULL;
 
-  struct SRB_ToAddMod                *SRB2_config;
-  struct SRB_ToAddMod__rlc_Config    *SRB2_rlc_config;
-  struct SRB_ToAddMod__logicalChannelConfig *SRB2_lchan_config;
-  struct LogicalChannelConfig__ul_SpecificParameters *SRB2_ul_SpecificParameters;
-  LogicalChannelConfig_t             *SRB1_logicalChannelConfig = NULL;
-  SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;    // not used in this context: may be removed
-  SRB_ToAddModList_t                 *SRB_configList2;
+  struct SRB_ToAddMod                *SRB2_config                      = NULL;
+  struct SRB_ToAddMod__rlc_Config    *SRB2_rlc_config                  = NULL;
+  struct SRB_ToAddMod__logicalChannelConfig *SRB2_lchan_config         = NULL;
+  struct LogicalChannelConfig__ul_SpecificParameters
+      *SRB2_ul_SpecificParameters       = NULL;
+  SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;
 
-  struct DRB_ToAddMod                *DRB_config;
-  struct RLC_Config                  *DRB_rlc_config;
-  struct PDCP_Config                 *DRB_pdcp_config;
-  struct PDCP_Config__rlc_UM         *PDCP_rlc_UM;
-  struct LogicalChannelConfig        *DRB_lchan_config;
-  struct LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters;
-  DRB_ToAddModList_t                 *DRB_configList2;
+  SRB_ToAddModList_t                 **SRB_configList2                 = NULL;
 
-  MAC_MainConfig_t                   *mac_MainConfig;
-  MeasObjectToAddModList_t           *MeasObj_list;
-  MeasObjectToAddMod_t               *MeasObj;
-  ReportConfigToAddModList_t         *ReportConfig_list;
+  struct DRB_ToAddMod                *DRB_config                       = NULL;
+  struct RLC_Config                  *DRB_rlc_config                   = NULL;
+  struct PDCP_Config                 *DRB_pdcp_config                  = NULL;
+  struct PDCP_Config__rlc_AM         *PDCP_rlc_AM                      = NULL;
+  struct PDCP_Config__rlc_UM         *PDCP_rlc_UM                      = NULL;
+  struct LogicalChannelConfig        *DRB_lchan_config                 = NULL;
+  struct LogicalChannelConfig__ul_SpecificParameters
+      *DRB_ul_SpecificParameters        = NULL;
+  DRB_ToAddModList_t**                DRB_configList = &ue_context_pP->ue_context.DRB_configList;
+  DRB_ToAddModList_t**                DRB_configList2 = NULL;
+   MAC_MainConfig_t                   *mac_MainConfig                   = NULL;
+  MeasObjectToAddModList_t           *MeasObj_list                     = NULL;
+  MeasObjectToAddMod_t               *MeasObj                          = NULL;
+  ReportConfigToAddModList_t         *ReportConfig_list                = NULL;
   ReportConfigToAddMod_t             *ReportConfig_per, *ReportConfig_A1,
                                      *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5;
-  MeasIdToAddModList_t               *MeasId_list;
+  MeasIdToAddModList_t               *MeasId_list                      = NULL;
   MeasIdToAddMod_t                   *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5;
-  QuantityConfig_t                   *quantityConfig;
-  MobilityControlInfo_t              *mobilityInfo;
-  // HandoverCommand_t handoverCommand;
-  //uint8_t                             sourceModId =
-  //  get_adjacent_cell_mod_id(ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->sourcePhysCellId);
 #if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
-  long                               *sr_ProhibitTimer_r9;
+  long                               *sr_ProhibitTimer_r9              = NULL;
+  //     uint8_t sCellIndexToAdd = rrc_find_free_SCell_index(enb_mod_idP, ue_mod_idP, 1);
+  //uint8_t                            sCellIndexToAdd = 0;
 #endif
 
   long                               *logicalchannelgroup, *logicalchannelgroup_drb;
   long                               *maxHARQ_Tx, *periodicBSR_Timer;
 
-  // RSRP_Range_t *rsrp;
-  struct MeasConfig__speedStatePars  *Sparams;
-  CellsToAddMod_t                    *CellToAdd;
-  CellsToAddModList_t                *CellsToAddModList;
-  // srb 1: for HO
-  struct SRB_ToAddMod                *SRB1_config;
+  RSRP_Range_t                       *rsrp                             = NULL;
+  struct MeasConfig__speedStatePars  *Sparams                          = NULL;
+  QuantityConfig_t                   *quantityConfig                   = NULL;
+  MobilityControlInfo_t              *mobilityInfo                     = NULL;
+  SecurityConfigHO_t                 *securityConfigHO                 = NULL;
+
+  //CellsToAddMod_t                    *CellToAdd                        = NULL;
+  //CellsToAddModList_t                *CellsToAddModList                = NULL;
+  struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList *dedicatedInfoNASList = NULL;
+  DedicatedInfoNAS_t                 *dedicatedInfoNas                 = NULL;
+  /* for no gcc warnings */
+  (void)dedicatedInfoNas;
+
+  C_RNTI_t                           *cba_RNTI                         = NULL;
+
+  uint8_t xid = rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id);   //Transaction_id,
+
+#ifdef CBA
+  //struct PUSCH_CBAConfigDedicated_vlola  *pusch_CBAConfigDedicated_vlola;
+  uint8_t                            *cba_RNTI_buf;
+  cba_RNTI = CALLOC(1, sizeof(C_RNTI_t));
+  cba_RNTI_buf = CALLOC(1, 2 * sizeof(uint8_t));
+  cba_RNTI->buf = cba_RNTI_buf;
+  cba_RNTI->size = 2;
+  cba_RNTI->bits_unused = 0;
+
+  // associate UEs to the CBa groups as a function of their UE id
+  if (rrc_inst->num_active_cba_groups) {
+    cba_RNTI->buf[0] = rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups] & 0xff;
+    cba_RNTI->buf[1] = 0xff;
+    LOG_D(RRC,
+          "[eNB %d] Frame %d: cba_RNTI = %x in group %d is attribued to UE %d\n",
+          enb_mod_idP, frameP,
+          rrc_inst->cba_rnti[ue_mod_idP % rrc_inst->num_active_cba_groups],
+          ue_mod_idP % rrc_inst->num_active_cba_groups, ue_mod_idP);
+  } else {
+    cba_RNTI->buf[0] = 0x0;
+    cba_RNTI->buf[1] = 0x0;
+    LOG_D(RRC, "[eNB %d] Frame %d: no cba_RNTI is configured for UE %d\n", enb_mod_idP, frameP, ue_mod_idP);
+  }
+
+#endif
+
+  T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
+    T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
+
+  rv[0] = (ue_context_pP->ue_context.rnti >> 8) & 255;
+  rv[1] = ue_context_pP->ue_context.rnti & 255;
+
+  LOG_I(RRC, "target UE rnti = %x (decimal: %d)\n", ue_context_pP->ue_context.rnti, ue_context_pP->ue_context.rnti);
+
+  LOG_D(RRC, "[eNB %d] Frame %d : handover preparation: add target eNB SRB1 and PHYConfigDedicated reconfiguration\n",
+        ctxt_pP->module_id, ctxt_pP->frame);
+
+  if (SRB_configList) {
+    free(SRB_configList);
+  }
+  SRB_configList = CALLOC(1, sizeof(*SRB_configList));
+  memset(SRB_configList, 0, sizeof(*SRB_configList));
+  SRB1_config = CALLOC(1, sizeof(*SRB1_config));
+
+  SRB1_config->srb_Identity = 1;
+  SRB1_rlc_config = CALLOC(1, sizeof(*SRB1_rlc_config));
+  SRB1_config->rlc_Config = SRB1_rlc_config;
+
+  SRB1_rlc_config->present = SRB_ToAddMod__rlc_Config_PR_explicitValue;
+  SRB1_rlc_config->choice.explicitValue.present = RLC_Config_PR_am;
+  SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms15;
+  SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollPDU = PollPDU_p8;
+  SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollByte = PollByte_kB1000;
+  SRB1_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.maxRetxThreshold = UL_AM_RLC__maxRetxThreshold_t16;
+  SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_Reordering = T_Reordering_ms35;
+  SRB1_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_StatusProhibit = T_StatusProhibit_ms10;
+
+  SRB1_lchan_config = CALLOC(1, sizeof(*SRB1_lchan_config));
+  SRB1_config->logicalChannelConfig = SRB1_lchan_config;
+
+  SRB1_lchan_config->present = SRB_ToAddMod__logicalChannelConfig_PR_explicitValue;
+  SRB1_ul_SpecificParameters = CALLOC(1, sizeof(*SRB1_ul_SpecificParameters));
+
+  SRB1_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB1_ul_SpecificParameters;
+
+  SRB1_ul_SpecificParameters->priority = 1;
+
+  //assign_enum(&SRB1_ul_SpecificParameters->prioritisedBitRate,LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity);
+  SRB1_ul_SpecificParameters->prioritisedBitRate =
+    LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+
+  //assign_enum(&SRB1_ul_SpecificParameters->bucketSizeDuration,LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50);
+  SRB1_ul_SpecificParameters->bucketSizeDuration =
+    LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+  logicalchannelgroup = CALLOC(1, sizeof(long));
+  *logicalchannelgroup = 0;
+  SRB1_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup;
+
+  ASN_SEQUENCE_ADD(&SRB_configList->list, SRB1_config);
+
+  ue_context_pP->ue_context.SRB_configList = SRB_configList;
+
+  // Configure SRB2
+  /// SRB2
+  SRB_configList2=&ue_context_pP->ue_context.SRB_configList2[xid];
+  if (*SRB_configList2) {
+    free(*SRB_configList2);
+  }
+  *SRB_configList2 = CALLOC(1, sizeof(**SRB_configList2));
+  memset(*SRB_configList2, 0, sizeof(**SRB_configList2));
+  SRB2_config = CALLOC(1, sizeof(*SRB2_config));
+
+  SRB2_config->srb_Identity = 2;
+  SRB2_rlc_config = CALLOC(1, sizeof(*SRB2_rlc_config));
+  SRB2_config->rlc_Config = SRB2_rlc_config;
+
+  SRB2_rlc_config->present = SRB_ToAddMod__rlc_Config_PR_explicitValue;
+  SRB2_rlc_config->choice.explicitValue.present = RLC_Config_PR_am;
+  SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms15;
+  SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollPDU = PollPDU_p8;
+  SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.pollByte = PollByte_kB1000;
+  SRB2_rlc_config->choice.explicitValue.choice.am.ul_AM_RLC.maxRetxThreshold = UL_AM_RLC__maxRetxThreshold_t32;
+  SRB2_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_Reordering = T_Reordering_ms35;
+  SRB2_rlc_config->choice.explicitValue.choice.am.dl_AM_RLC.t_StatusProhibit = T_StatusProhibit_ms10;
+
+  SRB2_lchan_config = CALLOC(1, sizeof(*SRB2_lchan_config));
+  SRB2_config->logicalChannelConfig = SRB2_lchan_config;
+
+  SRB2_lchan_config->present = SRB_ToAddMod__logicalChannelConfig_PR_explicitValue;
+
+  SRB2_ul_SpecificParameters = CALLOC(1, sizeof(*SRB2_ul_SpecificParameters));
+
+  SRB2_ul_SpecificParameters->priority = 3; // let some priority for SRB1 and dedicated DRBs
+  SRB2_ul_SpecificParameters->prioritisedBitRate =
+    LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+  SRB2_ul_SpecificParameters->bucketSizeDuration =
+    LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+  // LCG for CCCH and DCCH is 0 as defined in 36331
+  logicalchannelgroup = CALLOC(1, sizeof(long));
+  *logicalchannelgroup = 0;
+
+  SRB2_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup;
+
+  SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters = SRB2_ul_SpecificParameters;
+  // this list has the configuration for SRB1 and SRB2
+  ASN_SEQUENCE_ADD(&SRB_configList->list, SRB2_config);
+  // this list has only the configuration for SRB2
+  ASN_SEQUENCE_ADD(&(*SRB_configList2)->list, SRB2_config);
+
+  // Configure DRB
+  //*DRB_configList = CALLOC(1, sizeof(*DRB_configList));
+  // list for all the configured DRB
+  if (*DRB_configList) {
+    free(*DRB_configList);
+  }
+  *DRB_configList = CALLOC(1, sizeof(**DRB_configList));
+  memset(*DRB_configList, 0, sizeof(**DRB_configList));
+
+  // list for the configured DRB for a this xid
+  DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid];
+  if (*DRB_configList2) {
+    free(*DRB_configList2);
+  }
+  *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2));
+  memset(*DRB_configList2, 0, sizeof(**DRB_configList2));
+
+
+  /// DRB
+  DRB_config = CALLOC(1, sizeof(*DRB_config));
+
+  DRB_config->eps_BearerIdentity = CALLOC(1, sizeof(long));
+  *(DRB_config->eps_BearerIdentity) = 5L; // LW set to first value, allowed value 5..15, value : x+4
+  // DRB_config->drb_Identity = (DRB_Identity_t) 1; //allowed values 1..32
+  // NN: this is the 1st DRB for this ue, so set it to 1
+  DRB_config->drb_Identity = (DRB_Identity_t) 1;  // (ue_mod_idP+1); //allowed values 1..32, value: x
+  DRB_config->logicalChannelIdentity = CALLOC(1, sizeof(long));
+  *(DRB_config->logicalChannelIdentity) = (long)3; // value : x+2
+  DRB_rlc_config = CALLOC(1, sizeof(*DRB_rlc_config));
+  DRB_config->rlc_Config = DRB_rlc_config;
+
+#ifdef RRC_DEFAULT_RAB_IS_AM
+  DRB_rlc_config->present = RLC_Config_PR_am;
+  DRB_rlc_config->choice.am.ul_AM_RLC.t_PollRetransmit = T_PollRetransmit_ms50;
+  DRB_rlc_config->choice.am.ul_AM_RLC.pollPDU = PollPDU_p16;
+  DRB_rlc_config->choice.am.ul_AM_RLC.pollByte = PollByte_kBinfinity;
+  DRB_rlc_config->choice.am.ul_AM_RLC.maxRetxThreshold = UL_AM_RLC__maxRetxThreshold_t8;
+  DRB_rlc_config->choice.am.dl_AM_RLC.t_Reordering = T_Reordering_ms35;
+  DRB_rlc_config->choice.am.dl_AM_RLC.t_StatusProhibit = T_StatusProhibit_ms25;
+#else
+  DRB_rlc_config->present = RLC_Config_PR_um_Bi_Directional;
+  DRB_rlc_config->choice.um_Bi_Directional.ul_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.sn_FieldLength = SN_FieldLength_size10;
+#ifdef CBA
+  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering   = T_Reordering_ms5;//T_Reordering_ms25;
+#else
+  DRB_rlc_config->choice.um_Bi_Directional.dl_UM_RLC.t_Reordering = T_Reordering_ms35;
+#endif
+#endif
+
+  DRB_pdcp_config = CALLOC(1, sizeof(*DRB_pdcp_config));
+  DRB_config->pdcp_Config = DRB_pdcp_config;
+  DRB_pdcp_config->discardTimer = CALLOC(1, sizeof(long));
+  *DRB_pdcp_config->discardTimer = PDCP_Config__discardTimer_infinity;
+  DRB_pdcp_config->rlc_AM = NULL;
+  DRB_pdcp_config->rlc_UM = NULL;
+
+  /* avoid gcc warnings */
+  (void)PDCP_rlc_AM;
+  (void)PDCP_rlc_UM;
+
+#ifdef RRC_DEFAULT_RAB_IS_AM // EXMIMO_IOT
+  PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM));
+  DRB_pdcp_config->rlc_AM = PDCP_rlc_AM;
+  PDCP_rlc_AM->statusReportRequired = FALSE;
+#else
+  PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM));
+  DRB_pdcp_config->rlc_UM = PDCP_rlc_UM;
+  PDCP_rlc_UM->pdcp_SN_Size = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits;
+#endif
+  DRB_pdcp_config->headerCompression.present = PDCP_Config__headerCompression_PR_notUsed;
+
+  DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config));
+  DRB_config->logicalChannelConfig = DRB_lchan_config;
+  DRB_ul_SpecificParameters = CALLOC(1, sizeof(*DRB_ul_SpecificParameters));
+  DRB_lchan_config->ul_SpecificParameters = DRB_ul_SpecificParameters;
+
+  DRB_ul_SpecificParameters->priority = 12;    // lower priority than srb1, srb2 and other dedicated bearer
+  DRB_ul_SpecificParameters->prioritisedBitRate =LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_kBps8 ;
+    //LogicalChannelConfig__ul_SpecificParameters__prioritisedBitRate_infinity;
+  DRB_ul_SpecificParameters->bucketSizeDuration =
+    LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms50;
+
+  // LCG for DTCH can take the value from 1 to 3 as defined in 36331: normally controlled by upper layers (like RRM)
+  logicalchannelgroup_drb = CALLOC(1, sizeof(long));
+  *logicalchannelgroup_drb = 1;
+  DRB_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup_drb;
+
+  ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config);
+  ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config);
+
+  //ue_context_pP->ue_context.DRB_configList2[0] = &(*DRB_configList);
+
+  mac_MainConfig = CALLOC(1, sizeof(*mac_MainConfig));
+  ue_context_pP->ue_context.mac_MainConfig = mac_MainConfig;
+
+  mac_MainConfig->ul_SCH_Config = CALLOC(1, sizeof(*mac_MainConfig->ul_SCH_Config));
+
+  maxHARQ_Tx = CALLOC(1, sizeof(long));
+  *maxHARQ_Tx = MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
+  mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx;
+  periodicBSR_Timer = CALLOC(1, sizeof(long));
+  *periodicBSR_Timer = PeriodicBSR_Timer_r12_sf64;
+  mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer;
+  mac_MainConfig->ul_SCH_Config->retxBSR_Timer = RetxBSR_Timer_r12_sf320;
+  mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE
+
+  mac_MainConfig->timeAlignmentTimerDedicated = TimeAlignmentTimer_infinity;
+
+  mac_MainConfig->drx_Config = NULL;
+
+  mac_MainConfig->phr_Config = CALLOC(1, sizeof(*mac_MainConfig->phr_Config));
+
+  mac_MainConfig->phr_Config->present = MAC_MainConfig__phr_Config_PR_setup;
+  mac_MainConfig->phr_Config->choice.setup.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20; // sf20 = 20 subframes
+
+  mac_MainConfig->phr_Config->choice.setup.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20; // sf20 = 20 subframes
+
+  mac_MainConfig->phr_Config->choice.setup.dl_PathlossChange = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1;  // Value dB1 =1 dB, dB3 = 3 dB
+
+#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+  sr_ProhibitTimer_r9 = CALLOC(1, sizeof(long));
+  *sr_ProhibitTimer_r9 = 0;   // SR tx on PUCCH, Value in number of SR period(s). Value 0 = no timer for SR, Value 2= 2*SR
+  mac_MainConfig->ext1 = CALLOC(1, sizeof(struct MAC_MainConfig__ext1));
+  mac_MainConfig->ext1->sr_ProhibitTimer_r9 = sr_ProhibitTimer_r9;
+  //sps_RA_ConfigList_rlola = NULL;
+#endif
+
+  //change the transmission mode for the primary component carrier
+  //TODO: add codebook subset restriction here
+  //TODO: change TM for secondary CC in SCelltoaddmodlist
+  /// now reconfigure phy config dedicated
+  if (*physicalConfigDedicated) {
+    free(*physicalConfigDedicated);
+  }
+
+  //if (*physicalConfigDedicated) {
+
+  physicalConfigDedicated2 = CALLOC(1, sizeof(*physicalConfigDedicated2));
+  *physicalConfigDedicated = physicalConfigDedicated2;
+
+  physicalConfigDedicated2->pdsch_ConfigDedicated =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->pdsch_ConfigDedicated));
+  physicalConfigDedicated2->pucch_ConfigDedicated =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->pucch_ConfigDedicated));
+  physicalConfigDedicated2->pusch_ConfigDedicated =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->pusch_ConfigDedicated));
+  physicalConfigDedicated2->uplinkPowerControlDedicated =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated));
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH));
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH));
+  physicalConfigDedicated2->cqi_ReportConfig = NULL;  //CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
+  physicalConfigDedicated2->soundingRS_UL_ConfigDedicated = NULL; //CALLOC(1,sizeof(*physicalConfigDedicated2->soundingRS_UL_ConfigDedicated));
+  physicalConfigDedicated2->antennaInfo = CALLOC(1, sizeof(*physicalConfigDedicated2->antennaInfo));
+  physicalConfigDedicated2->schedulingRequestConfig =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->schedulingRequestConfig));
+  // PDSCH
+  //assign_enum(&physicalConfigDedicated2->pdsch_ConfigDedicated->p_a,
+  //          PDSCH_ConfigDedicated__p_a_dB0);
+  physicalConfigDedicated2->pdsch_ConfigDedicated->p_a = PDSCH_ConfigDedicated__p_a_dB0;
+
+  // PUCCH
+  physicalConfigDedicated2->pucch_ConfigDedicated->ackNackRepetition.present =
+    PUCCH_ConfigDedicated__ackNackRepetition_PR_release;
+  physicalConfigDedicated2->pucch_ConfigDedicated->ackNackRepetition.choice.release = 0;
+  physicalConfigDedicated2->pucch_ConfigDedicated->tdd_AckNackFeedbackMode = NULL;    //PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing;
+
+  // Pusch_config_dedicated
+  physicalConfigDedicated2->pusch_ConfigDedicated->betaOffset_ACK_Index = 0;  // 2.00
+  physicalConfigDedicated2->pusch_ConfigDedicated->betaOffset_RI_Index = 0;   // 1.25
+  physicalConfigDedicated2->pusch_ConfigDedicated->betaOffset_CQI_Index = 8;  // 2.25
+
+  // UplinkPowerControlDedicated
+  physicalConfigDedicated2->uplinkPowerControlDedicated->p0_UE_PUSCH = 0; // 0 dB
+  //assign_enum(&physicalConfigDedicated2->uplinkPowerControlDedicated->deltaMCS_Enabled,
+  // UplinkPowerControlDedicated__deltaMCS_Enabled_en1);
+  physicalConfigDedicated2->uplinkPowerControlDedicated->deltaMCS_Enabled =
+    UplinkPowerControlDedicated__deltaMCS_Enabled_en1;
+  physicalConfigDedicated2->uplinkPowerControlDedicated->accumulationEnabled = 1; // should be TRUE in order to have 0dB power offset
+  physicalConfigDedicated2->uplinkPowerControlDedicated->p0_UE_PUCCH = 0; // 0 dB
+  physicalConfigDedicated2->uplinkPowerControlDedicated->pSRS_Offset = 0; // 0 dB
+  physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient =
+    CALLOC(1, sizeof(*physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient));
+  //  assign_enum(physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient,FilterCoefficient_fc4); // fc4 dB
+  *physicalConfigDedicated2->uplinkPowerControlDedicated->filterCoefficient = FilterCoefficient_fc4;  // fc4 dB
+
+  // TPC-PDCCH-Config
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->present = TPC_PDCCH_Config_PR_setup;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_Index.present = TPC_Index_PR_indexOfFormat3;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_Index.choice.indexOfFormat3 = 1;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.buf = CALLOC(1, 2);
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.size = 2;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.buf[0] = 0x12;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.buf[1] = 0x34 + ue_context_pP->local_uid;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUCCH->choice.setup.tpc_RNTI.bits_unused = 0;
+
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->present = TPC_PDCCH_Config_PR_setup;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_Index.present = TPC_Index_PR_indexOfFormat3;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_Index.choice.indexOfFormat3 = 1;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.buf = CALLOC(1, 2);
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.size = 2;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.buf[0] = 0x22;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.buf[1] = 0x34 + ue_context_pP->local_uid;
+  physicalConfigDedicated2->tpc_PDCCH_ConfigPUSCH->choice.setup.tpc_RNTI.bits_unused = 0;
+
+  //AntennaInfoDedicated
+  physicalConfigDedicated2->antennaInfo = CALLOC(1, sizeof(*physicalConfigDedicated2->antennaInfo));
+  physicalConfigDedicated2->antennaInfo->present = PhysicalConfigDedicated__antennaInfo_PR_explicitValue;
+
+  //if ((*physicalConfigDedicated)->antennaInfo) {
+    (*physicalConfigDedicated)->antennaInfo->choice.explicitValue.transmissionMode = rrc_inst->configuration.ue_TransmissionMode[0];
+    LOG_D(RRC,"Setting transmission mode to %ld+1\n",rrc_inst->configuration.ue_TransmissionMode[0]);
+    if (rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm3) {
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction=
+	  CALLOC(1,sizeof(AntennaInfoDedicated__codebookSubsetRestriction_PR));
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->present =
+	  AntennaInfoDedicated__codebookSubsetRestriction_PR_n2TxAntenna_tm3;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm3.buf= MALLOC(1);
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm3.buf[0] = 0xc0;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm3.size=1;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm3.bits_unused=6;
+    }
+    else if (rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm4) {
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction=
+	  CALLOC(1,sizeof(AntennaInfoDedicated__codebookSubsetRestriction_PR));
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->present =
+	  AntennaInfoDedicated__codebookSubsetRestriction_PR_n2TxAntenna_tm4;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm4.buf= MALLOC(1);
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm4.buf[0] = 0xfc;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm4.size=1;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm4.bits_unused=2;
+
+    }
+    else if (rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm5) {
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction=
+	  CALLOC(1,sizeof(AntennaInfoDedicated__codebookSubsetRestriction_PR));
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->present =
+	  AntennaInfoDedicated__codebookSubsetRestriction_PR_n2TxAntenna_tm5;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm5.buf= MALLOC(1);
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm5.buf[0] = 0xf0;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm5.size=1;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm5.bits_unused=4;
+    }
+    else if (rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm6) {
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction=
+	  CALLOC(1,sizeof(AntennaInfoDedicated__codebookSubsetRestriction_PR));
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->present =
+	  AntennaInfoDedicated__codebookSubsetRestriction_PR_n2TxAntenna_tm6;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm6.buf= MALLOC(1);
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm6.buf[0] = 0xf0;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm6.size=1;
+	(*physicalConfigDedicated)->antennaInfo->choice.explicitValue.codebookSubsetRestriction->choice.n2TxAntenna_tm6.bits_unused=4;
+    }
+  physicalConfigDedicated2->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.present =
+    AntennaInfoDedicated__ue_TransmitAntennaSelection_PR_release;
+  physicalConfigDedicated2->antennaInfo->choice.explicitValue.ue_TransmitAntennaSelection.choice.release = 0;
+  //}
+  //else {
+    //LOG_E(RRC,"antenna_info not present in physical_config_dedicated. Not reconfiguring!\n");
+  //}
+  // CQI ReportConfig
+    physicalConfigDedicated2->cqi_ReportConfig = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig));
+
+    physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic = CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic));
+    physicalConfigDedicated2->cqi_ReportConfig->nomPDSCH_RS_EPRE_Offset = 0; // 0 dB
+    //physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic=NULL;
+
+    physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic=CALLOC(1,sizeof(*physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic));
+    physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportPeriodic->present =  CQI_ReportPeriodic_PR_release;
+  //if ((*physicalConfigDedicated)->cqi_ReportConfig) {
+    if ((rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm4) ||
+	  (rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm5) ||
+	  (rrc_inst->configuration.ue_TransmissionMode[0]==AntennaInfoDedicated__transmissionMode_tm6)) {
+	//feedback mode needs to be set as well
+	//TODO: I think this is taken into account in the PHY automatically based on the transmission mode variable
+	printf("setting cqi reporting mode to rm31\n");
+#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+	*((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=CQI_ReportModeAperiodic_rm31;
+#else
+	*((*physicalConfigDedicated)->cqi_ReportConfig->cqi_ReportModeAperiodic)=CQI_ReportConfig__cqi_ReportModeAperiodic_rm31; // HLC CQI, no PMI
+#endif
+    }
+    else {
+#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+        *physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic= CQI_ReportModeAperiodic_rm30;
+#else
+        *physicalConfigDedicated2->cqi_ReportConfig->cqi_ReportModeAperiodic=CQI_ReportConfig__cqi_ReportModeAperiodic_rm30; // HLC CQI, no PMI
+#endif
+    }
+  //}
+  //else {
+    //LOG_E(RRC,"cqi_ReportConfig not present in physical_config_dedicated. Not reconfiguring!\n");
+  //}
+
+  // SchedulingRequestConfig
+  physicalConfigDedicated2->schedulingRequestConfig->present = SchedulingRequestConfig_PR_setup;
+  physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = ue_context_pP->local_uid;
+
+  if (rrc_inst->carrier[0].sib1->tdd_Config==NULL) {  // FDD
+    physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 5 + (ue_context_pP->local_uid %
+        10);   // Isr = 5 (every 10 subframes, offset=2+UE_id mod3)
+  } else {
+    switch (rrc_inst->carrier[0].sib1->tdd_Config->subframeAssignment) {
+    case 1:
+      physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid & 1) + ((
+            ue_context_pP->local_uid & 3) >> 1) * 5;    // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 7 for UE2, 8 for UE3 , 2 for UE4 etc..)
+      break;
+
+    case 3:
+      physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid %
+          3);    // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 3 for UE2, 2 for UE3 , etc..)
+      break;
+
+    case 4:
+      physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7 + (ue_context_pP->local_uid &
+          1);    // Isr = 5 (every 10 subframes, offset=2 for UE0, 3 for UE1, 3 for UE2, 2 for UE3 , etc..)
+      break;
+
+    default:
+      physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 7; // Isr = 5 (every 10 subframes, offset=2 for all UE0 etc..)
+      break;
+    }
+  }
+
+  //  assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax,
+  //SchedulingRequestConfig__setup__dsr_TransMax_n4);
+  //  assign_enum(&physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax = SchedulingRequestConfig__setup__dsr_TransMax_n4;
+  physicalConfigDedicated2->schedulingRequestConfig->choice.setup.dsr_TransMax =
+    SchedulingRequestConfig__setup__dsr_TransMax_n4;
+  //}
+  //else {
+    //LOG_E(RRC,"physical_config_dedicated not present in RRCConnectionReconfiguration. Not reconfiguring!\n");
+  //}
+
+  // Measurement ID list
+  MeasId_list = CALLOC(1, sizeof(*MeasId_list));
+  memset((void *)MeasId_list, 0, sizeof(*MeasId_list));
+
+  MeasId0 = CALLOC(1, sizeof(*MeasId0));
+  MeasId0->measId = 1;
+  MeasId0->measObjectId = 1;
+  MeasId0->reportConfigId = 1;
+  ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId0);
+
+  MeasId1 = CALLOC(1, sizeof(*MeasId1));
+  MeasId1->measId = 2;
+  MeasId1->measObjectId = 1;
+  MeasId1->reportConfigId = 2;
+  ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId1);
+
+  MeasId2 = CALLOC(1, sizeof(*MeasId2));
+  MeasId2->measId = 3;
+  MeasId2->measObjectId = 1;
+  MeasId2->reportConfigId = 3;
+  ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId2);
+
+  MeasId3 = CALLOC(1, sizeof(*MeasId3));
+  MeasId3->measId = 4;
+  MeasId3->measObjectId = 1;
+  MeasId3->reportConfigId = 4;
+  ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId3);
+
+  MeasId4 = CALLOC(1, sizeof(*MeasId4));
+  MeasId4->measId = 5;
+  MeasId4->measObjectId = 1;
+  MeasId4->reportConfigId = 5;
+  ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId4);
+
+  MeasId5 = CALLOC(1, sizeof(*MeasId5));
+  MeasId5->measId = 6;
+  MeasId5->measObjectId = 1;
+  MeasId5->reportConfigId = 6;
+  ASN_SEQUENCE_ADD(&MeasId_list->list, MeasId5);
+
+  //  rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measIdToAddModList = MeasId_list;
+
+  // Add one EUTRA Measurement Object
+  MeasObj_list = CALLOC(1, sizeof(*MeasObj_list));
+  memset((void *)MeasObj_list, 0, sizeof(*MeasObj_list));
+
+  // Configure MeasObject
+
+  MeasObj = CALLOC(1, sizeof(*MeasObj));
+  memset((void *)MeasObj, 0, sizeof(*MeasObj));
+
+  MeasObj->measObjectId = 1;
+  MeasObj->measObject.present = MeasObjectToAddMod__measObject_PR_measObjectEUTRA;
+  MeasObj->measObject.choice.measObjectEUTRA.carrierFreq = (ARFCN_ValueEUTRA_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq, RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL);
+  MeasObj->measObject.choice.measObjectEUTRA.allowedMeasBandwidth = AllowedMeasBandwidth_mbw25;
+  MeasObj->measObject.choice.measObjectEUTRA.presenceAntennaPort1 = 1;
+  MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf = CALLOC(1, sizeof(uint8_t));
+  MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0;
+  MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1;
+  MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6;
+  MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL;   // Default is 15 or 0dB
+
+  //MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList =
+    //(CellsToAddModList_t *) CALLOC(1, sizeof(*CellsToAddModList));
+
+  //CellsToAddModList = MeasObj->measObject.choice.measObjectEUTRA.cellsToAddModList;
+
+  // Add adjacent cell lists (6 per eNB)
+  //for (i = 0; i < 6; i++) {
+    //CellToAdd = (CellsToAddMod_t *) CALLOC(1, sizeof(*CellToAdd));
+    //CellToAdd->cellIndex = 1;//i + 1;
+    //CellToAdd->physCellId = 1;//get_adjacent_cell_id(ctxt_pP->module_id, i);
+    //CellToAdd->cellIndividualOffset = Q_OffsetRange_dB0;
+
+    //ASN_SEQUENCE_ADD(&CellsToAddModList->list, CellToAdd);
+  //}
+
+  ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj);
+  //  rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->measObjectToAddModList = MeasObj_list;
+
+  // Report Configurations for periodical, A1-A5 events
+  ReportConfig_list = CALLOC(1, sizeof(*ReportConfig_list));
+
+  ReportConfig_per = CALLOC(1, sizeof(*ReportConfig_per));
+
+  ReportConfig_A1 = CALLOC(1, sizeof(*ReportConfig_A1));
+
+  ReportConfig_A2 = CALLOC(1, sizeof(*ReportConfig_A2));
+
+  ReportConfig_A3 = CALLOC(1, sizeof(*ReportConfig_A3));
+
+  ReportConfig_A4 = CALLOC(1, sizeof(*ReportConfig_A4));
+
+  ReportConfig_A5 = CALLOC(1, sizeof(*ReportConfig_A5));
+
+  ReportConfig_per->reportConfigId = 1;
+  ReportConfig_per->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.present =
+    ReportConfigEUTRA__triggerType_PR_periodical;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerType.choice.periodical.purpose =
+    ReportConfigEUTRA__triggerType__periodical__purpose_reportStrongestCells;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.triggerQuantity = ReportConfigEUTRA__triggerQuantity_rsrp;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
+  ReportConfig_per->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
+
+  ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_per);
+
+  ReportConfig_A1->reportConfigId = 2;
+  ReportConfig_A1->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.present =
+    ReportConfigEUTRA__triggerType_PR_event;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present =
+    ReportConfigEUTRA__triggerType__event__eventId_PR_eventA1;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1.
+  a1_Threshold.present = ThresholdEUTRA_PR_threshold_RSRP;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA1.
+  a1_Threshold.choice.threshold_RSRP = 10;
+
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.triggerQuantity = ReportConfigEUTRA__triggerQuantity_rsrp;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
+  ReportConfig_A1->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
+
+  ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A1);
+
+//  if (ho_state == 1 /*HO_MEASUREMENT */ ) {
+    LOG_I(RRC, "[eNB %d] frame %d: requesting A2, A3, A4, and A5 event reporting\n",
+          ctxt_pP->module_id, ctxt_pP->frame);
+    ReportConfig_A2->reportConfigId = 3;
+    ReportConfig_A2->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.present =
+      ReportConfigEUTRA__triggerType_PR_event;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present =
+      ReportConfigEUTRA__triggerType__event__eventId_PR_eventA2;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA2.a2_Threshold.present = ThresholdEUTRA_PR_threshold_RSRP;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA2.a2_Threshold.choice.threshold_RSRP = 10;
+
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.triggerQuantity =
+      ReportConfigEUTRA__triggerQuantity_rsrp;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
+    ReportConfig_A2->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
+
+    ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A2);
+
+    ReportConfig_A3->reportConfigId = 4;
+    ReportConfig_A3->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.present =
+      ReportConfigEUTRA__triggerType_PR_event;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present =
+      ReportConfigEUTRA__triggerType__event__eventId_PR_eventA3;
+
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.eventA3.a3_Offset = 0;   //10;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA3.reportOnLeave = 1;
+
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerQuantity =
+      ReportConfigEUTRA__triggerQuantity_rsrp;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
+
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.hysteresis = 0; // FIXME ...hysteresis is of type long!
+    ReportConfig_A3->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.timeToTrigger =
+      TimeToTrigger_ms40;
+    ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A3);
+
+    ReportConfig_A4->reportConfigId = 5;
+    ReportConfig_A4->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.present =
+      ReportConfigEUTRA__triggerType_PR_event;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present =
+      ReportConfigEUTRA__triggerType__event__eventId_PR_eventA4;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA4.a4_Threshold.present = ThresholdEUTRA_PR_threshold_RSRP;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA4.a4_Threshold.choice.threshold_RSRP = 10;
+
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.triggerQuantity =
+      ReportConfigEUTRA__triggerQuantity_rsrp;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
+    ReportConfig_A4->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
+
+    ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A4);
+
+    ReportConfig_A5->reportConfigId = 6;
+    ReportConfig_A5->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigEUTRA;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.present =
+      ReportConfigEUTRA__triggerType_PR_event;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.present =
+      ReportConfigEUTRA__triggerType__event__eventId_PR_eventA5;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA5.a5_Threshold1.present = ThresholdEUTRA_PR_threshold_RSRP;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA5.a5_Threshold2.present = ThresholdEUTRA_PR_threshold_RSRP;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA5.a5_Threshold1.choice.threshold_RSRP = 10;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerType.choice.event.eventId.choice.
+    eventA5.a5_Threshold2.choice.threshold_RSRP = 10;
+
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.triggerQuantity =
+      ReportConfigEUTRA__triggerQuantity_rsrp;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportQuantity = ReportConfigEUTRA__reportQuantity_both;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.maxReportCells = 2;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportInterval = ReportInterval_ms120;
+    ReportConfig_A5->reportConfig.choice.reportConfigEUTRA.reportAmount = ReportConfigEUTRA__reportAmount_infinity;
+
+    ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_A5);
+    //  rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.measConfig->reportConfigToAddModList = ReportConfig_list;
+
+    rsrp = CALLOC(1, sizeof(RSRP_Range_t));
+    *rsrp = 20;
+
+    Sparams = CALLOC(1, sizeof(*Sparams));
+    Sparams->present = MeasConfig__speedStatePars_PR_setup;
+    Sparams->choice.setup.timeToTrigger_SF.sf_High = SpeedStateScaleFactors__sf_Medium_oDot75;
+    Sparams->choice.setup.timeToTrigger_SF.sf_Medium = SpeedStateScaleFactors__sf_High_oDot5;
+    Sparams->choice.setup.mobilityStateParameters.n_CellChangeHigh = 10;
+    Sparams->choice.setup.mobilityStateParameters.n_CellChangeMedium = 5;
+    Sparams->choice.setup.mobilityStateParameters.t_Evaluation = MobilityStateParameters__t_Evaluation_s60;
+    Sparams->choice.setup.mobilityStateParameters.t_HystNormal = MobilityStateParameters__t_HystNormal_s120;
+
+    quantityConfig = CALLOC(1, sizeof(*quantityConfig));
+    memset((void *)quantityConfig, 0, sizeof(*quantityConfig));
+    quantityConfig->quantityConfigEUTRA = CALLOC(1, sizeof(struct QuantityConfigEUTRA));
+    memset((void *)quantityConfig->quantityConfigEUTRA, 0, sizeof(*quantityConfig->quantityConfigEUTRA));
+    quantityConfig->quantityConfigCDMA2000 = NULL;
+    quantityConfig->quantityConfigGERAN = NULL;
+    quantityConfig->quantityConfigUTRA = NULL;
+    quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP =
+      CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP)));
+    quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ =
+      CALLOC(1, sizeof(*(quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ)));
+    *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRP = FilterCoefficient_fc4;
+    *quantityConfig->quantityConfigEUTRA->filterCoefficientRSRQ = FilterCoefficient_fc4;
+
+    /* mobilityinfo  */
+    mobilityInfo = ue_context_pP->ue_context.mobilityInfo;
+    if (mobilityInfo) {
+      free(mobilityInfo);
+    }
+    mobilityInfo = CALLOC(1, sizeof(*mobilityInfo));
+    memset((void *)mobilityInfo, 0, sizeof(*mobilityInfo));
+    mobilityInfo->targetPhysCellId = RC.rrc[ctxt_pP->module_id]->carrier[0].physCellId;
+
+    //(PhysCellId_t) two_tier_hexagonal_cellIds[ue_context_pP->ue_context.handover_info->modid_t];
+    LOG_D(RRC, "[eNB %d] Frame %d: handover preparation: targetPhysCellId: %ld mod_id: %d ue: %x \n",
+          ctxt_pP->module_id,
+          ctxt_pP->frame,
+          mobilityInfo->targetPhysCellId,
+          ctxt_pP->module_id, // get_adjacent_cell_mod_id(mobilityInfo->targetPhysCellId),
+          ue_context_pP->ue_context.rnti);
+
+    mobilityInfo->additionalSpectrumEmission = CALLOC(1, sizeof(*mobilityInfo->additionalSpectrumEmission));
+    *mobilityInfo->additionalSpectrumEmission = 1;  //Check this value!
+
+    mobilityInfo->t304 = MobilityControlInfo__t304_ms200;    // need to configure an appropriate value here
+
+    // New UE Identity (C-RNTI) to identify an UE uniquely in a cell
+    mobilityInfo->newUE_Identity.size = 2;
+    mobilityInfo->newUE_Identity.bits_unused = 0;
+    mobilityInfo->newUE_Identity.buf = rv;
+    mobilityInfo->newUE_Identity.buf[0] = rv[0];
+    mobilityInfo->newUE_Identity.buf[1] = rv[1];
+
+    //memset((void *)&mobilityInfo->radioResourceConfigCommon,(void *)&rrc_inst->sib2->radioResourceConfigCommon,sizeof(RadioResourceConfigCommon_t));
+    //memset((void *)&mobilityInfo->radioResourceConfigCommon,0,sizeof(RadioResourceConfigCommon_t));
+
+    // Configuring radioResourceConfigCommon
+    mobilityInfo->radioResourceConfigCommon.rach_ConfigCommon =
+      CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.rach_ConfigCommon));
+    memcpy((void *)mobilityInfo->radioResourceConfigCommon.rach_ConfigCommon,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.rach_ConfigCommon, sizeof(RACH_ConfigCommon_t));
+    mobilityInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo =
+      CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo));
+    memcpy((void *)mobilityInfo->radioResourceConfigCommon.prach_Config.prach_ConfigInfo,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.prach_Config.prach_ConfigInfo,
+           sizeof(PRACH_ConfigInfo_t));
+
+    mobilityInfo->radioResourceConfigCommon.prach_Config.rootSequenceIndex =
+      rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.prach_Config.rootSequenceIndex;
+    mobilityInfo->radioResourceConfigCommon.pdsch_ConfigCommon =
+      CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.pdsch_ConfigCommon));
+    memcpy((void *)mobilityInfo->radioResourceConfigCommon.pdsch_ConfigCommon,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.pdsch_ConfigCommon, sizeof(PDSCH_ConfigCommon_t));
+    memcpy((void *)&mobilityInfo->radioResourceConfigCommon.pusch_ConfigCommon,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.pusch_ConfigCommon, sizeof(PUSCH_ConfigCommon_t));
+    mobilityInfo->radioResourceConfigCommon.phich_Config = NULL;
+    mobilityInfo->radioResourceConfigCommon.pucch_ConfigCommon =
+      CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.pucch_ConfigCommon));
+    memcpy((void *)mobilityInfo->radioResourceConfigCommon.pucch_ConfigCommon,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.pucch_ConfigCommon, sizeof(PUCCH_ConfigCommon_t));
+    mobilityInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon =
+      CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon));
+    memcpy((void *)mobilityInfo->radioResourceConfigCommon.soundingRS_UL_ConfigCommon,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.soundingRS_UL_ConfigCommon,
+           sizeof(SoundingRS_UL_ConfigCommon_t));
+    mobilityInfo->radioResourceConfigCommon.uplinkPowerControlCommon =
+      CALLOC(1, sizeof(*mobilityInfo->radioResourceConfigCommon.uplinkPowerControlCommon));
+    memcpy((void *)mobilityInfo->radioResourceConfigCommon.uplinkPowerControlCommon,
+           (void *)&rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.uplinkPowerControlCommon,
+           sizeof(UplinkPowerControlCommon_t));
+    mobilityInfo->radioResourceConfigCommon.antennaInfoCommon = NULL;
+    mobilityInfo->radioResourceConfigCommon.p_Max = NULL;   // CALLOC(1,sizeof(*mobilityInfo->radioResourceConfigCommon.p_Max));
+    //memcpy((void *)mobilityInfo->radioResourceConfigCommon.p_Max,(void *)rrc_inst->sib1->p_Max,sizeof(P_Max_t));
+    mobilityInfo->radioResourceConfigCommon.tdd_Config = NULL;  //CALLOC(1,sizeof(TDD_Config_t));
+    //memcpy((void *)mobilityInfo->radioResourceConfigCommon.tdd_Config,(void *)rrc_inst->sib1->tdd_Config,sizeof(TDD_Config_t));
+    mobilityInfo->radioResourceConfigCommon.ul_CyclicPrefixLength =
+      rrc_inst->carrier[0] /* CROUX TBC */.sib2->radioResourceConfigCommon.ul_CyclicPrefixLength;
+    //End of configuration of radioResourceConfigCommon
+
+    mobilityInfo->carrierFreq = CALLOC(1, sizeof(*mobilityInfo->carrierFreq));  //CALLOC(1,sizeof(CarrierFreqEUTRA_t)); 36090
+    mobilityInfo->carrierFreq->dl_CarrierFreq = (ARFCN_ValueEUTRA_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq, RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL);
+    mobilityInfo->carrierFreq->ul_CarrierFreq = NULL;
+
+    mobilityInfo->carrierBandwidth = CALLOC(1, sizeof(
+        *mobilityInfo->carrierBandwidth));    //CALLOC(1,sizeof(struct CarrierBandwidthEUTRA));  AllowedMeasBandwidth_mbw25
+    mobilityInfo->carrierBandwidth->dl_Bandwidth = CarrierBandwidthEUTRA__dl_Bandwidth_n25;
+    mobilityInfo->carrierBandwidth->ul_Bandwidth = NULL;
+    mobilityInfo->rach_ConfigDedicated = NULL;
+
+    ue_context_pP->ue_context.mobilityInfo = mobilityInfo;
+#if 0
+    LOG_I(RRC,
+          "[eNB %d] Frame %d: potential handover preparation: store the information in an intermediate structure in case of failure\n",
+          ctxt_pP->module_id, ctxt_pP->frame);
+    // store the information in an intermediate structure for Hanodver management
+    //rrc_inst->handover_info.as_config.sourceRadioResourceConfig.srb_ToAddModList = CALLOC(1,sizeof());
+    ue_context_pP->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_pP->ue_context.handover_info)));
+    //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.srb_ToAddModList,(void *)SRB_list,sizeof(SRB_ToAddModList_t));
+    ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.srb_ToAddModList = *SRB_configList2;
+    //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.drb_ToAddModList,(void *)DRB_list,sizeof(DRB_ToAddModList_t));
+    ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToAddModList = *DRB_configList;
+    ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.drb_ToReleaseList = NULL;
+    ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig =
+      CALLOC(1, sizeof(*ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig));
+    memcpy((void*)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.mac_MainConfig,
+           (void *)mac_MainConfig, sizeof(MAC_MainConfig_t));
+    ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated =
+      CALLOC(1, sizeof(PhysicalConfigDedicated_t));
+    memcpy((void*)ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.physicalConfigDedicated,
+           (void*)ue_context_pP->ue_context.physicalConfigDedicated, sizeof(PhysicalConfigDedicated_t));
+    ue_context_pP->ue_context.handover_info->as_config.sourceRadioResourceConfig.sps_Config = NULL;
+    //memcpy((void *)rrc_inst->handover_info[ue_mod_idP]->as_config.sourceRadioResourceConfig.sps_Config,(void *)rrc_inst->sps_Config[ue_mod_idP],sizeof(SPS_Config_t));
+#endif
+
+//  }
+
+  securityConfigHO = CALLOC(1, sizeof(*securityConfigHO));
+  memset((void *)securityConfigHO, 0, sizeof(*securityConfigHO));
+
+  securityConfigHO->handoverType.present = SecurityConfigHO__handoverType_PR_intraLTE;
+  securityConfigHO->handoverType.choice.intraLTE.securityAlgorithmConfig = NULL; /* TODO: to be checked */
+  securityConfigHO->handoverType.choice.intraLTE.keyChangeIndicator = 0;
+  securityConfigHO->handoverType.choice.intraLTE.nextHopChainingCount = 0;
+
+
+#if defined(ENABLE_ITTI)
+  /* Initialize NAS list */
+  dedicatedInfoNASList = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList));
+
+  /* Add all NAS PDUs to the list */
+  for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) {
+    if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) {
+      dedicatedInfoNas = CALLOC(1, sizeof(DedicatedInfoNAS_t));
+      memset(dedicatedInfoNas, 0, sizeof(OCTET_STRING_t));
+      OCTET_STRING_fromBuf(dedicatedInfoNas,
+			   (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer,
+                           ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length);
+      ASN_SEQUENCE_ADD(&dedicatedInfoNASList->list, dedicatedInfoNas);
+    }
+
+    /* TODO parameters yet to process ... */
+    {
+      //      ue_context_pP->ue_context.e_rab[i].param.qos;
+      //      ue_context_pP->ue_context.e_rab[i].param.sgw_addr;
+      //      ue_context_pP->ue_context.e_rab[i].param.gtp_teid;
+    }
+
+    /* TODO should test if e RAB are Ok before! */
+    ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE;
+    LOG_D(RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n",
+	  i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_STATUS_DONE");
+  }
+
+  /* If list is empty free the list and reset the address */
+  if (dedicatedInfoNASList->list.count == 0) {
+    free(dedicatedInfoNASList);
+    dedicatedInfoNASList = NULL;
+  }
+
+#endif
+
+  memset(buffer, 0, RRC_BUF_SIZE);
+
+  char rrc_buf[1000 /* arbitrary, should be big enough, has to be less than size of return buf by a few bits/bytes */];
+  int rrc_size;
+
+  rrc_size = do_RRCConnectionReconfiguration(ctxt_pP,
+                                         (unsigned char *)rrc_buf,
+                                         xid,   //Transaction_id,
+                                         NULL, // SRB_configList
+                                         NULL,
+                                         NULL,  // DRB2_list,
+                                         (struct SPS_Config*)NULL,    // *sps_Config,
+                                         (struct PhysicalConfigDedicated*)*physicalConfigDedicated,
+//#ifdef EXMIMO_IOT
+//                                         NULL, NULL, NULL,NULL,
+//#else
+                                         (MeasObjectToAddModList_t*)MeasObj_list,
+                                         (ReportConfigToAddModList_t*)ReportConfig_list,
+                                         (QuantityConfig_t*)quantityConfig,
+                                         (MeasIdToAddModList_t*)MeasId_list,
+//#endif
+                                         (MAC_MainConfig_t*)mac_MainConfig,
+                                         (MeasGapConfig_t*)NULL,
+                                         (MobilityControlInfo_t*)mobilityInfo,
+                                         (SecurityConfigHO_t*)securityConfigHO,
+                                         (struct MeasConfig__speedStatePars*)Sparams,
+                                         (RSRP_Range_t*)rsrp,
+                                         (C_RNTI_t*)cba_RNTI,
+                                         (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)dedicatedInfoNASList,
+                                         (SL_CommConfig_r12_t*)NULL,
+                                         (SL_DiscConfig_r12_t*)NULL
+#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+                                         , (SCellToAddMod_r10_t*)NULL
+#endif
+                                        );
+
+  if (rrc_size <= 0) { printf("%s:%d: fatal\n", __FILE__, __LINE__); abort(); }
+
+  char *ho_buf = (char*)buffer;
+  int ho_size;
+  ho_size = do_HandoverCommand(
+           ho_buf, 1024 /* TODO: this is the value found in struct x2ap_handover_req_ack_s for array rrc_buffer */,
+           rrc_buf,
+           rrc_size);
+
+  *_size = size = ho_size;
+
+  LOG_DUMPMSG(RRC,DEBUG_RRC,(char *)buffer,size,
+              "[MSG] RRC Connection Reconfiguration handover\n");
+
+#if defined(ENABLE_ITTI)
+
+  /* Free all NAS PDUs */
+  for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) {
+    if (ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer != NULL) {
+      /* Free the NAS PDU buffer and invalidate it */
+      free(ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer);
+      ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer = NULL;
+    }
+  }
+
+#endif
+
+  LOG_I(RRC,
+        "[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate RRCConnectionReconfiguration handover (bytes %d, UE id %x)\n",
+        ctxt_pP->module_id, ctxt_pP->frame, size, ue_context_pP->ue_context.rnti);
+
+  LOG_D(RRC,
+        "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration handover to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n",
+        ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH);
+
+  MSC_LOG_TX_MESSAGE(
+    MSC_RRC_ENB,
+    MSC_RRC_UE,
+    buffer,
+    size,
+    MSC_AS_TIME_FMT" rrcConnectionReconfiguration handover UE %x MUI %d size %u",
+    MSC_AS_TIME_ARGS(ctxt_pP),
+    ue_context_pP->ue_context.rnti,
+    rrc_eNB_mui,
+    size);
+}
+
+void
+rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protocol_ctxt_t* const ctxt_pP)
+{
+  uint16_t                            Idx;
+
+  Idx = DCCH;
+#if 1
+
+    // Activate the radio bearers
+    // SRB1
+    ue_context_p->ue_context.Srb1.Active = 1;
+    ue_context_p->ue_context.Srb1.Srb_info.Srb_id = Idx;
+    memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[0], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
+    memcpy(&ue_context_p->ue_context.Srb1.Srb_info.Lchan_desc[1], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
+
+    // SRB2
+    ue_context_p->ue_context.Srb2.Active = 1;
+    ue_context_p->ue_context.Srb2.Srb_info.Srb_id = Idx;
+    memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[0], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
+    memcpy(&ue_context_p->ue_context.Srb2.Srb_info.Lchan_desc[1], &DCCH_LCHAN_DESC, LCHAN_DESC_SIZE);
+#endif
+
+    LOG_I(RRC, "[eNB %d] CALLING RLC CONFIG SRB1 (rbid %d) for UE %x\n",
+	  ctxt_pP->module_id, Idx, ue_context_p->ue_context.rnti);
+
+    // Configure PDCP/RLC for the target
+
+    rrc_pdcp_config_asn1_req(ctxt_pP,
+			     ue_context_p->ue_context.SRB_configList,
+			     (DRB_ToAddModList_t *) NULL,
+			     (DRB_ToReleaseList_t *) NULL,
+			     0xff,
+			     NULL,
+			     NULL,
+			     NULL
+#if defined(Rel10) || defined(Rel14)
+			     , (PMCH_InfoList_r9_t *) NULL
+#endif
+			     , NULL);
+
+    rrc_rlc_config_asn1_req(ctxt_pP,
+			    ue_context_p->ue_context.SRB_configList,
+			    (DRB_ToAddModList_t *) NULL,
+			    (DRB_ToReleaseList_t *) NULL
+#if defined(Rel10) || defined(Rel14)
+			    , (PMCH_InfoList_r9_t *) NULL
+                            , 0, 0
+#endif
+			    );
+  // Add a new user (called during the HO procedure)
+  LOG_I(RRC, "rrc_eNB_target_add_ue_handover module_id %d rnti %d\n", ctxt_pP->module_id, ctxt_pP->rnti);
+
+    // Configure MAC for the target
+  rrc_mac_config_req_eNB(
+                         ctxt_pP->module_id,
+                         ue_context_p->ue_context.primaryCC_id,
+                         0,0,0,0,0,
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+0,
+#endif
+                         ue_context_p->ue_context.rnti,
+                         (BCCH_BCH_Message_t *) NULL,
+                         (RadioResourceConfigCommonSIB_t*) NULL,
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                         (RadioResourceConfigCommonSIB_t*) NULL,
+#endif
+                         ue_context_p->ue_context.physicalConfigDedicated,
+#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
+                         (SCellToAddMod_r10_t *)NULL,
+                         //(struct PhysicalConfigDedicatedSCell_r10 *)NULL,
+#endif
+                         (MeasObjectToAddMod_t **) NULL,
+                         ue_context_p->ue_context.mac_MainConfig,
+                         1,
+                         NULL,//SRB1_logicalChannelConfig,
+                         ue_context_p->ue_context.measGapConfig,
+                         (TDD_Config_t*) NULL,
+                         (MobilityControlInfo_t*) ue_context_p->ue_context.mobilityInfo,
+                         (SchedulingInfoList_t*) NULL,
+                         0,
+                         NULL,
+                         NULL,
+                         (MBSFN_SubframeConfigList_t *) NULL
+#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+                         , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
+#endif
+#if (RRC_VERSION >= MAKE_VERSION(13, 0, 0))
+                         ,
+                         (SystemInformationBlockType1_v1310_IEs_t *)NULL
+#endif
+                         );
+
+#if 0
+  }
+#endif
+}
+
+#if 0
+// 5.3.5.4 RRCConnectionReconfiguration including the mobilityControlInfo to prepare the UE handover
+//-----------------------------------------------------------------------------
+void
+rrc_eNB_generate_RRCConnectionReconfiguration_handover(
+  const protocol_ctxt_t* const ctxt_pP,
+  rrc_eNB_ue_context_t*           const ue_context_pP,
+  uint8_t*                const nas_pdu,
+  const uint32_t                nas_length
+)
+//-----------------------------------------------------------------------------
+{
+  T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
+    T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
+
+
+  uint8_t                             buffer[RRC_BUF_SIZE];
+  int                                 i;
+  uint8_t                             rv[2];
+  uint16_t                            Idx;
+  // configure SRB1/SRB2, PhysicalConfigDedicated, MAC_MainConfig for UE
+  eNB_RRC_INST*                       rrc_inst = RC.rrc[ctxt_pP->module_id];
+  struct PhysicalConfigDedicated**    physicalConfigDedicated = &ue_context_pP->ue_context.physicalConfigDedicated;
+
+  struct SRB_ToAddMod                *SRB2_config;
+  struct SRB_ToAddMod__rlc_Config    *SRB2_rlc_config;
+  struct SRB_ToAddMod__logicalChannelConfig *SRB2_lchan_config;
+  struct LogicalChannelConfig__ul_SpecificParameters *SRB2_ul_SpecificParameters;
+  LogicalChannelConfig_t             *SRB1_logicalChannelConfig = NULL;
+  SRB_ToAddModList_t*                 SRB_configList = ue_context_pP->ue_context.SRB_configList;    // not used in this context: may be removed
+  SRB_ToAddModList_t                 *SRB_configList2;
+
+  struct DRB_ToAddMod                *DRB_config;
+  struct RLC_Config                  *DRB_rlc_config;
+  struct PDCP_Config                 *DRB_pdcp_config;
+  struct PDCP_Config__rlc_UM         *PDCP_rlc_UM;
+  struct LogicalChannelConfig        *DRB_lchan_config;
+  struct LogicalChannelConfig__ul_SpecificParameters *DRB_ul_SpecificParameters;
+  DRB_ToAddModList_t                 *DRB_configList2;
+
+  MAC_MainConfig_t                   *mac_MainConfig;
+  MeasObjectToAddModList_t           *MeasObj_list;
+  MeasObjectToAddMod_t               *MeasObj;
+  ReportConfigToAddModList_t         *ReportConfig_list;
+  ReportConfigToAddMod_t             *ReportConfig_per, *ReportConfig_A1,
+                                     *ReportConfig_A2, *ReportConfig_A3, *ReportConfig_A4, *ReportConfig_A5;
+  MeasIdToAddModList_t               *MeasId_list;
+  MeasIdToAddMod_t                   *MeasId0, *MeasId1, *MeasId2, *MeasId3, *MeasId4, *MeasId5;
+  QuantityConfig_t                   *quantityConfig;
+  MobilityControlInfo_t              *mobilityInfo;
+  // HandoverCommand_t handoverCommand;
+  //uint8_t                             sourceModId =
+  //  get_adjacent_cell_mod_id(ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->sourcePhysCellId);
+#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
+  long                               *sr_ProhibitTimer_r9;
+#endif
+
+  long                               *logicalchannelgroup, *logicalchannelgroup_drb;
+  long                               *maxHARQ_Tx, *periodicBSR_Timer;
+
+  // RSRP_Range_t *rsrp;
+  struct MeasConfig__speedStatePars  *Sparams;
+  CellsToAddMod_t                    *CellToAdd;
+  CellsToAddModList_t                *CellsToAddModList;
+  // srb 1: for HO
+  struct SRB_ToAddMod                *SRB1_config;
   struct SRB_ToAddMod__rlc_Config    *SRB1_rlc_config;
   struct SRB_ToAddMod__logicalChannelConfig *SRB1_lchan_config;
   struct LogicalChannelConfig__ul_SpecificParameters *SRB1_ul_SpecificParameters;
@@ -5286,6 +6775,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
 			 ue_context_pP->ue_context.measGapConfig,
 			 (TDD_Config_t *) NULL,
 			 (MobilityControlInfo_t *) mobilityInfo,
+                         (SecurityConfigHO_t *)NULL,
 			 (SchedulingInfoList_t *) NULL, 0, NULL, NULL, (MBSFN_SubframeConfigList_t *) NULL
 #if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
 			 , 0, (MBSFN_AreaInfoList_r9_t *) NULL, (PMCH_InfoList_r9_t *) NULL
@@ -5326,6 +6816,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
 
 #endif
 }
+#endif
 
 /*
   void ue_rrc_process_rrcConnectionReconfiguration(uint8_t enb_mod_idP,frame_t frameP,
@@ -6635,7 +8126,23 @@ rrc_eNB_decode_dcch(
   	      dedicated_DRB = 2;
   	      RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0;
   	    }
-  	  } else {
+	  }
+          else if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION){
+            int16_t UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti);
+            if(UE_id == -1){
+              LOG_E(RRC,
+                    PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReconfigurationComplete without rnti %x, fault\n",
+                    PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ctxt_pP->rnti);
+              break;
+            }
+            dedicated_DRB = 3;
+            RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0;
+            ue_context_p->ue_context.Status = RRC_RECONFIGURED;
+            LOG_I(RRC,
+                  PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_HO_EXECUTION (xid %ld)\n",
+                  PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier);
+          }
+          else {
   	    dedicated_DRB = 0;
   	    ue_context_p->ue_context.Status = RRC_RECONFIGURED;
   	    LOG_I(RRC,
@@ -6728,7 +8235,17 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
                  ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED;
                }
              }
-         }
+  }else if(dedicated_DRB == 3){//x2 path switch
+             for (uint8_t e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
+               if (ue_context_p->ue_context.e_rab[e_rab].status == E_RAB_STATUS_DONE) {
+                 ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_ESTABLISHED;
+               } else {
+                 ue_context_p->ue_context.e_rab[e_rab].status = E_RAB_STATUS_FAILED;
+               }
+             }
+        LOG_I(RRC,"issue rrc_eNB_send_PATH_SWITCH_REQ \n");
+        rrc_eNB_send_PATH_SWITCH_REQ(ctxt_pP,ue_context_p);
+  }
 #endif   
 #else  // establish a dedicated bearer 
       if (dedicated_DRB == 0 ) {
@@ -6994,6 +8511,11 @@ if (ue_context_p->ue_context.nb_of_modify_e_rabs > 0) {
                              ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.
                              choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.
                              array[0]->ueCapabilityRAT_Container.size, 0, 0);
+
+      ue_context_p->ue_context.UE_Capability_size = ul_dcch_msg->message.choice.c1.choice.ueCapabilityInformation.criticalExtensions.
+                             choice.c1.choice.ueCapabilityInformation_r8.ue_CapabilityRAT_ContainerList.list.
+                             array[0]->ueCapabilityRAT_Container.size;
+
       if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
          xer_fprint(stdout, &asn_DEF_UE_EUTRA_Capability, ue_context_p->ue_context.UE_Capability);
       }
@@ -7349,6 +8871,30 @@ rrc_enb_task(
 
 #   endif
 
+    case S1AP_PATH_SWITCH_REQ_ACK:
+      LOG_I(RRC, "[eNB %d] received path switch ack %s\n", instance, msg_name_p);
+      rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK(msg_p, msg_name_p, instance);
+      break;
+
+    case X2AP_HANDOVER_REQ:
+      LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s at frame %d subframe %d\n", instance, msg_name_p,
+            ctxt.frame, ctxt.subframe);
+      rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p));
+      break;
+
+    case X2AP_HANDOVER_REQ_ACK: {
+      struct rrc_eNB_ue_context_s*        ue_context_p = NULL;
+      ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], ctxt.rnti);
+
+      LOG_I(RRC, "[eNB %d] source eNB receives the X2 HO ACK %s at frame %d subframe %d \n", instance, msg_name_p,
+            ctxt.frame,ctxt.subframe);
+      DevAssert(ue_context_p != NULL);
+      if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort();
+      rrc_eNB_process_handoverCommand(instance, ue_context_p, &X2AP_HANDOVER_REQ_ACK(msg_p));
+      ue_context_p->ue_context.handover_info->state = HO_PREPARE;
+      break;
+     }
+
       /* Messages from eNB app */
     case RRC_CONFIGURATION_REQ:
       LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p,&RRC_CONFIGURATION_REQ(msg_p));
@@ -7570,7 +9116,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(
                    (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
                    (struct SPS_Config*)NULL,    // *sps_Config,
                    NULL, NULL, NULL, NULL,NULL,
-                   NULL, NULL,  NULL, NULL, NULL, NULL,
+                   NULL, NULL,  NULL, NULL, NULL, NULL, NULL,
                    (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL,
                    (SL_CommConfig_r12_t*)&sl_CommConfig,
                    (SL_DiscConfig_r12_t*)NULL
@@ -7593,7 +9139,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_Sidelink(
                    (DRB_ToReleaseList_t*)NULL,  // DRB2_list,
                    (struct SPS_Config*)NULL,    // *sps_Config,
                    NULL, NULL, NULL, NULL,NULL,
-                   NULL, NULL,  NULL, NULL, NULL, NULL,
+                   NULL, NULL,  NULL, NULL, NULL, NULL, NULL,
                    (struct RRCConnectionReconfiguration_r8_IEs__dedicatedInfoNASList*)NULL,
                    (SL_CommConfig_r12_t*)NULL,
                    (SL_DiscConfig_r12_t*)&sl_DiscConfig
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c
index 7d242286023985c1002562d25feb32040285603e..a26c0aad8da9229f39bc0f1a5268ac2a3123d930 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.c
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c
@@ -36,6 +36,7 @@
 # include "rrc_eNB_S1AP.h"
 # include "enb_config.h"
 # include "common/ran_context.h"
+# include "gtpv1u.h"
 
 # if defined(ENABLE_ITTI)
 #   include "asn1_conversions.h"
@@ -63,6 +64,11 @@
 
 extern RAN_CONTEXT_t RC;
 
+extern int
+gtpv1u_delete_s1u_tunnel(
+  const instance_t instanceP,
+  const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
+
 /* Value to indicate an invalid UE initial id */
 static const uint16_t UE_INITIAL_ID_INVALID = 0;
 
@@ -793,6 +799,12 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ(
         S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code     = BIT_STRING_to_uint8 (&r_mme->mmec);
         S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id = BIT_STRING_to_uint16 (&r_mme->mmegi);
 
+        ue_context_pP->ue_context.ue_gummei.mcc = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc;
+        ue_context_pP->ue_context.ue_gummei.mnc = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc;
+        ue_context_pP->ue_context.ue_gummei.mnc_len = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len;
+        ue_context_pP->ue_context.ue_gummei.mme_code = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code;
+        ue_context_pP->ue_context.ue_gummei.mme_group_id = S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_group_id;
+
         MSC_LOG_TX_MESSAGE(
           MSC_S1AP_ENB,
           MSC_S1AP_MME,
@@ -976,6 +988,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
 
     PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
     ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).eNB_ue_s1ap_id;
+    ue_context_p->ue_context.mme_ue_s1ap_id = S1AP_INITIAL_CONTEXT_SETUP_REQ (msg_p).mme_ue_s1ap_id;
 
     /* Save e RAB information for later */
     {
@@ -1976,5 +1989,231 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance
   return (0);
 }
 
+/*NN: careful about the typcast of xid (long -> uint8_t*/
+int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
+				  rrc_eNB_ue_context_t*          const ue_context_pP){
+
+  MessageDef      *msg_p         = NULL;
+  int e_rab = 0;
+  int e_rabs_done = 0;
+
+  rrc_ue_s1ap_ids_t*  rrc_ue_s1ap_ids_p = NULL;
+  hashtable_rc_t      h_rc;
+
+  gtpv1u_enb_create_tunnel_req_t  create_tunnel_req;
+  gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
+
+  uint8_t inde_list[ue_context_pP->ue_context.nb_of_e_rabs];
+  memset(inde_list, 0, ue_context_pP->ue_context.nb_of_e_rabs*sizeof(uint8_t));
+
+  msg_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ);
+
+  ue_context_pP->ue_context.ue_initial_id = get_next_ue_initial_id (ctxt_pP->module_id);
+  S1AP_PATH_SWITCH_REQ (msg_p).ue_initial_id = ue_context_pP->ue_context.ue_initial_id;
+
+  rrc_ue_s1ap_ids_p = malloc(sizeof(*rrc_ue_s1ap_ids_p));
+  rrc_ue_s1ap_ids_p->ue_initial_id  = ue_context_pP->ue_context.ue_initial_id;
+  rrc_ue_s1ap_ids_p->eNB_ue_s1ap_id = UE_INITIAL_ID_INVALID;
+  rrc_ue_s1ap_ids_p->ue_rnti        = ctxt_pP->rnti;
+
+  h_rc = hashtable_insert(RC.rrc[ctxt_pP->module_id]->initial_id2_s1ap_ids,
+		               (hash_key_t)ue_context_pP->ue_context.ue_initial_id,
+                               rrc_ue_s1ap_ids_p);
+  if (h_rc != HASH_TABLE_OK) {
+    LOG_E(S1AP, "[eNB %d] Error while hashtable_insert in initial_id2_s1ap_ids ue_initial_id %u\n",
+	  ctxt_pP->module_id, ue_context_pP->ue_context.ue_initial_id);
+  }
+
+  S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id = ue_context_pP->ue_context.eNB_ue_s1ap_id;
+
+  S1AP_PATH_SWITCH_REQ (msg_p).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id;
+
+  S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc;
+  S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mnc = ue_context_pP->ue_context.ue_gummei.mnc;
+  S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mnc_len = ue_context_pP->ue_context.ue_gummei.mnc_len;
+  S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mme_code = ue_context_pP->ue_context.ue_gummei.mme_code;
+  S1AP_PATH_SWITCH_REQ (msg_p).ue_gummei.mme_group_id = ue_context_pP->ue_context.ue_gummei.mme_group_id;
+
+  S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.encryption_algorithms=ue_context_pP->ue_context.security_capabilities.encryption_algorithms;
+  S1AP_PATH_SWITCH_REQ (msg_p).security_capabilities.integrity_algorithms=ue_context_pP->ue_context.security_capabilities.integrity_algorithms;
+
+  LOG_I (RRC,"Path switch request: nb nb_of_e_rabs %u status %u\n",
+          ue_context_pP->ue_context.nb_of_e_rabs,
+          ue_context_pP->ue_context.e_rab[e_rab].status);
+
+  memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
+  // the context for UE to be handovered is obtained through ho_req message
+  for (e_rab = 0; e_rab <  ue_context_pP->ue_context.nb_of_e_rabs ; e_rab++) {
+
+    if (ue_context_pP->ue_context.e_rab[e_rab].status == E_RAB_STATUS_ESTABLISHED) {
+
+      create_tunnel_req.eps_bearer_id[e_rabs_done]       = ue_context_pP->ue_context.e_rab[e_rab].param.e_rab_id;
+      create_tunnel_req.sgw_S1u_teid[e_rabs_done]        = ue_context_pP->ue_context.e_rab[e_rab].param.gtp_teid;
+      memcpy(&create_tunnel_req.sgw_addr[e_rabs_done],
+             &ue_context_pP->ue_context.e_rab[e_rab].param.sgw_addr,
+             sizeof(transport_layer_addr_t));
+
+      inde_list[e_rabs_done] = e_rab;
+      e_rabs_done++;
+    }
+  }
+
+  S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs = e_rabs_done;
+
+  create_tunnel_req.rnti           = ue_context_pP->ue_context.rnti;
+  create_tunnel_req.num_tunnels    = e_rabs_done;
+
+  gtpv1u_create_s1u_tunnel(
+      ctxt_pP->instance,
+      &create_tunnel_req,
+      &create_tunnel_resp);
+
+  rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP(
+        ctxt_pP,
+        &create_tunnel_resp,
+        &inde_list[0]);
+
+  for (e_rab = 0; e_rab < e_rabs_done; e_rab++) {
+
+      S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id = create_tunnel_resp.eps_bearer_id[e_rab];
+      S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].gtp_teid = create_tunnel_resp.enb_S1u_teid[e_rab];
+      S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr = create_tunnel_resp.enb_addr;
+
+      LOG_I (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d): nb_of_e_rabs %d,  e_rab_id %d, teid: %u, addr: %d.%d.%d.%d \n ",
+	     e_rabs_done,  e_rab, ue_context_pP->ue_context.e_rab[inde_list[e_rab]].status,
+	     ue_context_pP->ue_context.nb_of_e_rabs,
+	     S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id,
+	     S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].gtp_teid,
+	     S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[0],
+	     S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[1],
+	     S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[2],
+	     S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[3]);
+  }
+
+    // NN: add conditions for e_rabs_failed
+    if (e_rabs_done > 0) {
+
+      LOG_I(RRC,"S1AP_PATH_SWITCH_REQ: sending the message: nb_of_erabstobeswitched %d, total e_rabs %d, index %d\n",
+	    ue_context_pP->ue_context.nb_of_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab);
+
+      MSC_LOG_TX_MESSAGE(
+			 MSC_RRC_ENB,
+			 MSC_S1AP_ENB,
+			 (const char *)&S1AP_PATH_SWITCH_REQ (msg_p),
+			 sizeof(s1ap_path_switch_req_t),
+			 MSC_AS_TIME_FMT" PATH_SWITCH_REQ UE %X eNB_ue_s1ap_id %u e_rabs:%u succ",
+			 MSC_AS_TIME_ARGS(ctxt_pP),
+			 ue_context_pP->ue_id_rnti,
+			 S1AP_PATH_SWITCH_REQ (msg_p).eNB_ue_s1ap_id,
+			 e_rabs_done);
+
+
+	itti_send_msg_to_task (TASK_S1AP, ctxt_pP->instance, msg_p);
+     }
+
+  return 0;
+}
+
+int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance)
+{
+  uint16_t                        ue_initial_id;
+  uint32_t                        eNB_ue_s1ap_id;
+  //gtpv1u_enb_create_tunnel_req_t  create_tunnel_req;
+  //gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
+
+  gtpv1u_enb_delete_tunnel_req_t  delete_tunnel_req;
+
+  struct rrc_eNB_ue_context_s* ue_context_p = NULL;
+  protocol_ctxt_t              ctxt;
+  int i;
+
+  ue_initial_id  = S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_initial_id;
+  eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
+  ue_context_p   = rrc_eNB_get_ue_context_from_s1ap_ids(instance, ue_initial_id, eNB_ue_s1ap_id);
+  LOG_I(RRC, "[eNB %d] Received %s: ue_initial_id %d, eNB_ue_s1ap_id %d, nb_of_e_rabs %d\n",
+        instance, msg_name, ue_initial_id, eNB_ue_s1ap_id, S1AP_E_RAB_SETUP_REQ (msg_p).nb_e_rabs_tosetup);
+
+  if (ue_context_p == NULL) {
+    /* Can not associate this message to an UE index, send a failure to S1AP and discard it! */
+    //MessageDef *msg_fail_p = NULL;
+
+    LOG_W(RRC, "[eNB %d] In S1AP_PATH_SWITCH_REQ_ACK: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, eNB_ue_s1ap_id);
+
+    //msg_fail_p = itti_alloc_new_message (TASK_RRC_ENB, S1AP_PATH_SWITCH_REQ_ACK_FAIL);
+    //S1AP_PATH_SWITCH_REQ_ACK  (msg_fail_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
+
+    // TODO add failure cause when defined!
+
+    //itti_send_msg_to_task (TASK_S1AP, instance, msg_fail_p);
+    return (-1);
+  } else {
+
+    PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, ENB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
+    ue_context_p->ue_context.eNB_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).eNB_ue_s1ap_id;
+    ue_context_p->ue_context.mme_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).mme_ue_s1ap_id;
+
+    /* Save e RAB information for later */
+    {
+      for (i = 0;
+	   i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg
+	   i++) {
+	// assume that we are releasing all the DRBs
+	ue_context_p->ue_context.e_rab[i].status =  E_RAB_STATUS_TORELEASE;
+      }
+
+      //memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
+      uint8_t nb_e_rabs_tobeswitched = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobeswitched;
+
+      // keep the previous bearer
+      // the index for the rec
+      for (i = 0;
+	   i < 1;//nb_e_rabs_tobeswitched; // go over total number of e_rabs received through x2_ho_req msg
+	   i++) {
+        LOG_I(RRC,"Bearer re-established with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
+	/* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */
+	ue_context_p->ue_context.e_rab[i].status =  E_RAB_STATUS_REESTABLISHED;
+	//ue_context_p->ue_context.e_rab[i].param.e_rab_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].e_rab_id;
+	//ue_context_p->ue_context.e_rab[i].param.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].sgw_addr;
+	//ue_context_p->ue_context.e_rab[i].param.gtp_teid = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].gtp_teid;
+	/* Tunnel must have been already created in X2_HO_REQ procedure */
+      }
+
+      ue_context_p->ue_context.setup_e_rabs=i;
+      ue_context_p->ue_context.nb_of_e_rabs=i;
+    }
+
+    ue_context_p->ue_context.ue_ambr=S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_ambr;
+
+
+    ue_context_p->ue_context.nb_release_of_e_rabs = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobereleased;
+    memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
+    for (i = 0;
+	 i < ue_context_p->ue_context.nb_release_of_e_rabs;
+	 i++) {
+      LOG_I(RRC,"Bearer released with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
+      ue_context_p->ue_context.e_rabs_tobereleased[i]=S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
+      delete_tunnel_req.eps_bearer_id[i]       = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id;
+
+    }
+    if (ue_context_p->ue_context.nb_release_of_e_rabs>0){
+      delete_tunnel_req.rnti= ue_context_p->ue_context.rnti;
+      delete_tunnel_req.num_erab= ue_context_p->ue_context.nb_release_of_e_rabs;
+      /* this could also be done through ITTI message */
+      gtpv1u_delete_s1u_tunnel(instance,
+			       &delete_tunnel_req);
+      /* TBD: release the DRB not admitted */
+      //rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(&ctxt, ue_context_p, 0);
+    }
+
+    /* Security key */
+    ue_context_p->ue_context.next_hop_chain_count=S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_hop_chain_count;
+    memcpy ( ue_context_p->ue_context.next_security_key,
+	     S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
+	     SECURITY_KEY_LENGTH);
+
+    return (0);
+  }
+}
+
 # endif /* defined(ENABLE_ITTI) */
 #endif /* defined(ENABLE_USE_MME) */
diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.h b/openair2/RRC/LTE/rrc_eNB_S1AP.h
index a924caf254c664159089e1bcf27579bbbb687b67..42f1635a4d9c937b19fcdb498bd361763e2c0d08 100644
--- a/openair2/RRC/LTE/rrc_eNB_S1AP.h
+++ b/openair2/RRC/LTE/rrc_eNB_S1AP.h
@@ -269,6 +269,10 @@ int rrc_eNB_process_S1AP_E_RAB_RELEASE_COMMAND(MessageDef *msg_p, const char *ms
  */
 int rrc_eNB_send_S1AP_E_RAB_RELEASE_RESPONSE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t*  const ue_context_pP, uint8_t xid );
 
+int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t* const ctxt_pP,
+				  rrc_eNB_ue_context_t*          const ue_context_pP);
+int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
+
 #   endif
 # endif /* defined(ENABLE_USE_MME) */
 #endif /* RRC_ENB_S1AP_H_ */
diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h
index e16391aef10d483778f661628ffbd11710bdf7a6..f814a065185824879a2ef2fd3a4fd45b3af33389 100644
--- a/openair2/RRC/LTE/rrc_proto.h
+++ b/openair2/RRC/LTE/rrc_proto.h
@@ -309,6 +309,15 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(
 							     const uint8_t ho_state,
 							     agent_reconf_rrc * trig_param
 							     );
+void
+rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t* const ctxt_pP,
+                                                 rrc_eNB_ue_context_t*  const ue_context_pP,
+                                                 uint8_t*               buffer,
+                                                 int                    *_size
+                                                 //const uint8_t        ho_state
+                                                 );
+void
+rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protocol_ctxt_t* const ctxt_pP);
 
 int freq_to_arfcn10(int band, unsigned long freq);
 
@@ -345,6 +354,8 @@ void *rrc_enb_task(void *args_p);
 void *rrc_ue_task(void *args_p);
 #endif
 
+void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m);
+
 /**\brief Generate/decode the handover RRCConnectionReconfiguration at eNB
    \param module_idP Instance ID for eNB/CH
    \param frame Frame index
@@ -573,9 +584,11 @@ rrc_eNB_process_MeasurementReport(
 
 void
 rrc_eNB_generate_HandoverPreparationInformation(
-  const protocol_ctxt_t* const ctxt_pP,
+  //const protocol_ctxt_t* const ctxt_pP,
   rrc_eNB_ue_context_t*          const ue_context_pP,
-  PhysCellId_t targetPhyId
+  uint8_t*                     buffer,
+  int                          *_size
+  //PhysCellId_t targetPhyId
 );
 
 void
diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c
index d12dfa881979b9a3841471ed236b64ff4475c621..58083b20a5b6ee420e805d09ffddcca716a93a2c 100644
--- a/openair2/X2AP/x2ap_eNB.c
+++ b/openair2/X2AP/x2ap_eNB.c
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB.c
+ * \brief x2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -64,6 +71,13 @@ void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
                            uint32_t             enb_port_for_X2C,
                            int                  multi_sd);
 
+static
+void x2ap_eNB_handle_handover_req(instance_t instance,
+                                  x2ap_handover_req_t *x2ap_handover_req);
+
+static
+void x2ap_eNB_handle_handover_req_ack(instance_t instance,
+                                      x2ap_handover_req_ack_t *x2ap_handover_req_ack);
 
 static
 void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
@@ -405,6 +419,62 @@ void x2ap_eNB_handle_sctp_init_msg_multi_cnf(
   }
 }
 
+static
+void x2ap_eNB_handle_handover_req(instance_t instance,
+                                  x2ap_handover_req_t *x2ap_handover_req)
+{
+  /* TODO: remove this hack (the goal is to find the correct
+   * eNodeB structure for the target) - we need a proper way for RRC
+   * and X2AP to identify eNodeBs
+   * RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
+   * the configuration file)
+   * as far as I understand.. CROUX
+   */
+  x2ap_eNB_instance_t *instance_p;
+  x2ap_eNB_data_t     *target;
+
+  int target_enb_id = x2ap_handover_req->target_physCellId;
+
+  instance_p = x2ap_eNB_pci_get_instance(target_enb_id);
+  DevAssert(instance_p != NULL);
+
+  //instance_p = x2ap_eNB_get_instance(instance);
+  //DevAssert(instance_p != NULL);
+
+  target = x2ap_is_eNB_id_in_list(instance_p->eNB_id);
+  DevAssert(target != NULL);
+
+  /* store rnti at index 0 */
+  //x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti;
+  x2ap_eNB_generate_x2_handover_request(target, x2ap_handover_req);
+}
+
+static
+void x2ap_eNB_handle_handover_req_ack(instance_t instance,
+                                      x2ap_handover_req_ack_t *x2ap_handover_req_ack)
+{
+  /* TODO: remove this hack (the goal is to find the correct
+   * eNodeB structure for the other end) - we need a proper way for RRC
+   * and X2AP to identify eNodeBs
+   * RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
+   * the configuration file)
+   * as far as I understand.. CROUX
+   */
+  x2ap_eNB_instance_t *instance_p;
+  x2ap_eNB_data_t     *target;
+  int target_enb_id = x2ap_handover_req_ack->target_mod_id;
+
+  instance_p = x2ap_eNB_get_instance(instance);
+  DevAssert(instance_p != NULL);
+
+  target = x2ap_is_eNB_id_in_list(target_enb_id);
+  DevAssert(target != NULL);
+
+  x2ap_eNB_generate_x2_handover_request_ack(target, x2ap_handover_req_ack);
+  //x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id,
+          //x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
+}
+
 void *x2ap_task(void *arg)
 {
   MessageDef *received_msg = NULL;
@@ -429,6 +499,16 @@ void *x2ap_task(void *arg)
                                    &X2AP_REGISTER_ENB_REQ(received_msg));
       break;
 
+    case X2AP_HANDOVER_REQ:
+      x2ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                   &X2AP_HANDOVER_REQ(received_msg));
+      break;
+
+    case X2AP_HANDOVER_REQ_ACK:
+      x2ap_eNB_handle_handover_req_ack(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                       &X2AP_HANDOVER_REQ_ACK(received_msg));
+      break;
+
     case SCTP_INIT_MSG_MULTI_CNF:
       x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
                                               &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
diff --git a/openair2/X2AP/x2ap_eNB.h b/openair2/X2AP/x2ap_eNB.h
index 1a19416122d0918fa20896b6f580c858758db90e..5433a890883c94d750594fd4a99e848ef449c343 100644
--- a/openair2/X2AP/x2ap_eNB.h
+++ b/openair2/X2AP/x2ap_eNB.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB.h
+ * \brief x2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <stdio.h>
 #include <stdint.h>
 
diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c
index f156d96d175beab05523d01625cd34324bc1e1a5..553cf8e559c1d38b3969e33a2e21384c6401a326 100644
--- a/openair2/X2AP/x2ap_eNB_decoder.c
+++ b/openair2/X2AP/x2ap_eNB_decoder.c
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_decoder.c
+ * \brief x2ap decoder procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <stdio.h>
 
 #include "assertions.h"
@@ -33,7 +40,12 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
   switch(pdu->choice.initiatingMessage.procedureCode) {
 
     case X2AP_ProcedureCode_id_x2Setup:
-      asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
+      X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
+      break;
+
+    case X2AP_ProcedureCode_id_handoverPreparation:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
       X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
       break;
 
@@ -54,7 +66,12 @@ static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
 
   switch(pdu->choice.successfulOutcome.procedureCode) {
     case X2AP_ProcedureCode_id_x2Setup:
-      asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
+      X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
+      break;
+
+    case X2AP_ProcedureCode_id_handoverPreparation:
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
       X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
       break;
 
@@ -73,7 +90,7 @@ static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu)
 
   switch(pdu->choice.unsuccessfulOutcome.procedureCode) {
     case X2AP_ProcedureCode_id_x2Setup:
-      asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
+      //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
       X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n");
       break;
 
@@ -99,8 +116,9 @@ int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint3
                         length,
                         0,
                         0);
-
-  xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
+  }
 
   if (dec_ret.code != RC_OK) {
     X2AP_ERROR("Failed to decode pdu\n");
diff --git a/openair2/X2AP/x2ap_eNB_decoder.h b/openair2/X2AP/x2ap_eNB_decoder.h
index 9ce9ea3d40ef039a9c36c45163bdeb2969b0b9fb..7919c785554aef8eeaa5c156225c9cdac5d155b4 100644
--- a/openair2/X2AP/x2ap_eNB_decoder.h
+++ b/openair2/X2AP/x2ap_eNB_decoder.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_decoder.h
+ * \brief x2ap decoder procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #ifndef X2AP_ENB_DECODER_H_
 #define X2AP_ENB_DECODER_H_
 
diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h
index 3014290206913e516b046bfc5dbab94fa64397b1..a5558c42a5307d7f55c64be8eca6cf788e37b3c8 100644
--- a/openair2/X2AP/x2ap_eNB_defs.h
+++ b/openair2/X2AP/x2ap_eNB_defs.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_defs.h
+ * \brief x2ap struct definitions for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <stdint.h>
 
 #include "queue.h"
@@ -156,6 +163,7 @@ typedef struct x2ap_eNB_instance_s {
   uint32_t                downlink_frequency[MAX_NUM_CCs];
   int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
   uint32_t                Nid_cell[MAX_NUM_CCs];
+  uint32_t                Nid_target_cell[MAX_NUM_CCs];
   int16_t                 N_RB_DL[MAX_NUM_CCs];
   lte_frame_type_t        frame_type[MAX_NUM_CCs];
   uint32_t                fdd_earfcn_DL[MAX_NUM_CCs];
diff --git a/openair2/X2AP/x2ap_eNB_encoder.c b/openair2/X2AP/x2ap_eNB_encoder.c
index 1eb617a7f1ddec817a88648fe25ddbef2ac9ad7c..8b1c030d35d0b14d588475cf317d450f2fa3e686 100644
--- a/openair2/X2AP/x2ap_eNB_encoder.c
+++ b/openair2/X2AP/x2ap_eNB_encoder.c
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_encoder.c
+ * \brief x2ap encoder procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
diff --git a/openair2/X2AP/x2ap_eNB_encoder.h b/openair2/X2AP/x2ap_eNB_encoder.h
index 04c77583b4f27c05fcc723100784bf418bf26c3a..f451a3fb2626e6119b7a0158d4f4394a8f0cb9d1 100644
--- a/openair2/X2AP/x2ap_eNB_encoder.h
+++ b/openair2/X2AP/x2ap_eNB_encoder.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_encoder.h
+ * \brief x2ap encoder procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #ifndef X2AP_ENB_ENCODER_H_
 #define X2AP_ENB_ENCODER_H_
 
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c
index 9c5a281506730409d8cf9b7048e4d68b90e826a7..76d6053b59a1fb3a242a8730e3dface21a4eecda 100644
--- a/openair2/X2AP/x2ap_eNB_generate_messages.c
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.c
@@ -19,12 +19,22 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_generate_messages.c
+ * \brief x2ap procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include "intertask_interface.h"
 
+#include "X2AP_LastVisitedCell-Item.h"
+
 #include "x2ap_common.h"
 #include "x2ap_eNB.h"
 #include "x2ap_eNB_generate_messages.h"
 #include "x2ap_eNB_encoder.h"
+#include "x2ap_eNB_decoder.h"
 
 #include "x2ap_eNB_itti_messaging.h"
 
@@ -403,3 +413,314 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
 
   return 0;
 }
+
+int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                           x2ap_handover_req_t *x2ap_handover_req)
+{
+
+  X2AP_X2AP_PDU_t                     pdu;
+  X2AP_HandoverRequest_t              *out;
+  X2AP_HandoverRequest_IEs_t          *ie;
+  X2AP_E_RABs_ToBeSetup_ItemIEs_t     *e_RABS_ToBeSetup_ItemIEs;
+  X2AP_E_RABs_ToBeSetup_Item_t        *e_RABs_ToBeSetup_Item;
+  X2AP_LastVisitedCell_Item_t         *lastVisitedCell_Item;
+
+  x2ap_eNB_instance_t                 *instance_p;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  /* get the eNB instance */
+  instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
+
+  DevAssert(instance_p != NULL);
+
+
+  /* Prepare the X2AP handover message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_handoverPreparation;
+  pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_HandoverRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.HandoverRequest;
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = x2ap_handover_req->old_eNB_ue_x2ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Cause;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_HandoverRequest_IEs__value_PR_Cause;
+  ie->value.choice.Cause.present = X2AP_Cause_PR_radioNetwork;
+  ie->value.choice.Cause.choice.radioNetwork = X2AP_CauseRadioNetwork_handover_desirable_for_radio_reasons;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_TargetCell_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_HandoverRequest_IEs__value_PR_ECGI;
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                       &ie->value.choice.ECGI.pLMN_Identity);
+  MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_GUMMEI_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_HandoverRequest_IEs__value_PR_GUMMEI;
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                       &ie->value.choice.GUMMEI.gU_Group_ID.pLMN_Identity);
+  //@TODO: consider to update these values
+  INT16_TO_OCTET_STRING(x2ap_handover_req->ue_gummei.mme_group_id, &ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID);
+  MME_CODE_TO_OCTET_STRING(x2ap_handover_req->ue_gummei.mme_code, &ie->value.choice.GUMMEI.mME_Code);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_UE_ContextInformation;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_ContextInformation;
+  //@TODO: consider to update this value
+  ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID = x2ap_handover_req->mme_ue_s1ap_id;
+
+  KENB_STAR_TO_BIT_STRING(x2ap_handover_req->kenb,&ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
+
+  if (x2ap_handover_req->kenb_ncc >=0) { // Check this condition
+    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = x2ap_handover_req->kenb_ncc;
+  }
+  else {
+    ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
+  }
+
+  ENCRALG_TO_BIT_STRING(x2ap_handover_req->security_capabilities.encryption_algorithms,
+              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+
+  INTPROTALG_TO_BIT_STRING(x2ap_handover_req->security_capabilities.integrity_algorithms,
+              &ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+
+  //@TODO: update with proper UEAMPR
+  UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
+  UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&ie->value.choice.UE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
+  {
+    for (int i=0;i<x2ap_handover_req->nb_e_rabs_tobesetup;i++) {
+      e_RABS_ToBeSetup_ItemIEs = (X2AP_E_RABs_ToBeSetup_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_ToBeSetup_ItemIEs_t));
+      e_RABS_ToBeSetup_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_ToBeSetup_Item;
+      e_RABS_ToBeSetup_ItemIEs->criticality = X2AP_Criticality_ignore;
+      e_RABS_ToBeSetup_ItemIEs->value.present = X2AP_E_RABs_ToBeSetup_ItemIEs__value_PR_E_RABs_ToBeSetup_Item;
+      e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
+      {
+        e_RABs_ToBeSetup_Item->e_RAB_ID = x2ap_handover_req->e_rabs_tobesetup[i].e_rab_id;
+        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI = x2ap_handover_req->e_rab_param[i].qos.qci;
+        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.priority_level;
+        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability;
+        e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = x2ap_handover_req->e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability;
+        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size = (uint8_t)(x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length/8);
+        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused = x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.length%8;
+        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf =
+                        calloc(1,e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+
+        memcpy (e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
+                        x2ap_handover_req->e_rabs_tobesetup[i].eNB_addr.buffer,
+                        e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+
+        INT32_TO_OCTET_STRING(x2ap_handover_req->e_rabs_tobesetup[i].gtp_teid,&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID);
+      }
+      ASN_SEQUENCE_ADD(&ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list, e_RABS_ToBeSetup_ItemIEs);
+    }
+  }
+
+  OCTET_STRING_fromBuf(&ie->value.choice.UE_ContextInformation.rRC_Context, (char*) x2ap_handover_req->rrc_buffer, x2ap_handover_req->rrc_buffer_size);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequest_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_UE_HistoryInformation;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_HistoryInformation;
+  //@TODO: consider to update this value
+  {
+   lastVisitedCell_Item = (X2AP_LastVisitedCell_Item_t *)calloc(1, sizeof(X2AP_LastVisitedCell_Item_t));
+   lastVisitedCell_Item->present = X2AP_LastVisitedCell_Item_PR_e_UTRAN_Cell;
+   MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                       &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
+   MACRO_ENB_ID_TO_CELL_IDENTITY(0, 0, &lastVisitedCell_Item->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
+   lastVisitedCell_Item->choice.e_UTRAN_Cell.cellType.cell_Size = X2AP_Cell_Size_small;
+   lastVisitedCell_Item->choice.e_UTRAN_Cell.time_UE_StayedInCell = 2;
+   ASN_SEQUENCE_ADD(&ie->value.choice.UE_HistoryInformation.list, lastVisitedCell_Item);
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode X2 handover request\n");
+    abort();
+    return -1;
+  }
+
+  MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Handover/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
+
+  return ret;
+}
+
+int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                               x2ap_handover_req_ack_t *x2ap_handover_req_ack)
+{
+
+  X2AP_X2AP_PDU_t                        pdu;
+  X2AP_HandoverRequestAcknowledge_t      *out;
+  X2AP_HandoverRequestAcknowledge_IEs_t  *ie;
+  X2AP_E_RABs_Admitted_ItemIEs_t         *e_RABS_Admitted_ItemIEs;
+  X2AP_E_RABs_Admitted_Item_t            *e_RABs_Admitted_Item;
+
+  x2ap_eNB_instance_t                 *instance_p;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  /* get the eNB instance */
+  instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
+
+  DevAssert(instance_p != NULL);
+
+  /* Prepare the X2AP handover message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_handoverPreparation;
+  pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_HandoverRequestAcknowledge;
+  out = &pdu.choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = 0;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = 0;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_List;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_E_RABs_Admitted_List;
+
+  {
+      for (int i=0;i<x2ap_handover_req_ack->nb_e_rabs_tobesetup;i++) {
+        e_RABS_Admitted_ItemIEs = (X2AP_E_RABs_Admitted_ItemIEs_t *)calloc(1,sizeof(X2AP_E_RABs_Admitted_ItemIEs_t));
+        e_RABS_Admitted_ItemIEs->id = X2AP_ProtocolIE_ID_id_E_RABs_Admitted_Item;
+        e_RABS_Admitted_ItemIEs->criticality = X2AP_Criticality_ignore;
+        e_RABS_Admitted_ItemIEs->value.present = X2AP_E_RABs_Admitted_ItemIEs__value_PR_E_RABs_Admitted_Item;
+        e_RABs_Admitted_Item = &e_RABS_Admitted_ItemIEs->value.choice.E_RABs_Admitted_Item;
+        {
+          e_RABs_Admitted_Item->e_RAB_ID = x2ap_handover_req_ack->e_rabs_tobesetup[i].e_rab_id;
+        }
+        ASN_SEQUENCE_ADD(&ie->value.choice.E_RABs_Admitted_List.list, e_RABS_Admitted_ItemIEs);
+      }
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_TargeteNBtoSource_eNBTransparentContainer;
+
+  OCTET_STRING_fromBuf(&ie->value.choice.TargeteNBtoSource_eNBTransparentContainer, (char*) x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode X2 handover response\n");
+    abort();
+    return -1;
+  }
+
+  MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Handover/successfulOutcome assoc_id %u", x2ap_eNB_data_p->assoc_id);
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
+
+  return ret;
+}
+
+int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p)
+{
+
+  X2AP_X2AP_PDU_t                pdu;
+  X2AP_UEContextRelease_t        *out;
+  X2AP_UEContextRelease_IEs_t    *ie;
+
+  x2ap_eNB_instance_t               *instance_p;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  /* get the eNB instance */
+  instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
+
+  DevAssert(instance_p != NULL);
+
+  /* Prepare the X2AP ue context relase message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_uEContextRelease;
+  pdu.choice.initiatingMessage.criticality = X2AP_Criticality_ignore;
+  pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_UEContextRelease;
+  out = &pdu.choice.initiatingMessage.value.choice.UEContextRelease;
+
+  /* mandatory */
+  ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = 0;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
+  ie->value.choice.UE_X2AP_ID = 0;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode X2 UE Context Release\n");
+    abort();
+    return -1;
+  }
+
+  MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2UEContextRelease/initiatingMessage assoc_id %u", x2ap_eNB_data_p->assoc_id);
+
+  x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_eNB_data_p->assoc_id, buffer, len, 1);
+
+  return ret;
+}
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h
index a72b37e743da4ff24bdd8cd827ec0ffaeec47713..9028d8cd054e9d78388e7cf17967d6b00bdbee7f 100644
--- a/openair2/X2AP/x2ap_eNB_generate_messages.h
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_generate_messages.h
+ * \brief x2ap procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #ifndef X2AP_ENB_GENERATE_MESSAGES_H_
 #define X2AP_ENB_GENERATE_MESSAGES_H_
 
@@ -26,9 +33,9 @@
 #include "x2ap_common.h"
 
 int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
-				       x2ap_eNB_data_t *x2ap_enb_data_p);
+				       x2ap_eNB_data_t *x2ap_eNB_data_p);
 
-int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_enb_data_p);
+int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p);
 
 int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
                                        uint32_t assoc_id,
@@ -40,5 +47,12 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
                         X2AP_Cause_PR cause_type,
                         long cause_value);
 
+int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                           x2ap_handover_req_t *x2ap_handover_req);
+
+int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
+                                               x2ap_handover_req_ack_t *x2ap_handover_req_ack);
+
+int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p);
 #endif /*  X2AP_ENB_GENERATE_MESSAGES_H_ */
 
diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c
index a16a3da5a8ac9d3b5fd998875fed3e61cd8cc5fc..1301f71ca515dcc2d58268f24d28f530f2709c61 100644
--- a/openair2/X2AP/x2ap_eNB_handler.c
+++ b/openair2/X2AP/x2ap_eNB_handler.c
@@ -18,6 +18,14 @@
  * For more information about the OpenAirInterface (OAI) Software Alliance:
  *      contact@openairinterface.org
  */
+
+/*! \file x2ap_eNB_handler.c
+ * \brief x2ap handler procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <stdint.h>
 
 #include "intertask_interface.h"
@@ -52,9 +60,20 @@ int x2ap_eNB_handle_x2_setup_failure (instance_t instance,
                                       uint32_t stream,
                                       X2AP_X2AP_PDU_t *pdu);
 
+static
+int x2ap_eNB_handle_handover_preparation (instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu);
+static
+int x2ap_eNB_handle_handover_response (instance_t instance,
+                                      uint32_t assoc_id,
+                                      uint32_t stream,
+                                      X2AP_X2AP_PDU_t *pdu);
+
 /* Handlers matrix. Only eNB related procedure present here */
 x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
-  { 0, 0, 0 }, /* handoverPreparation */
+  { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
   { 0, 0, 0 }, /* handoverCancel */
   { 0, 0, 0 }, /* loadIndication */
   { 0, 0, 0 }, /* errorIndication */
@@ -143,41 +162,105 @@ int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stre
                                 const uint8_t *const data, const uint32_t data_length)
 {
   X2AP_X2AP_PDU_t pdu;
-  int ret;
+  int ret = 0;
 
   DevAssert(data != NULL);
 
   memset(&pdu, 0, sizeof(pdu));
 
+  //printf("Data length received: %d\n", data_length);
+
   if (x2ap_eNB_decode_pdu(&pdu, data, data_length) < 0) {
     X2AP_ERROR("Failed to decode PDU\n");
     return -1;
   }
 
-  /* Checking procedure Code and direction of message */
-  if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
-        x2ap_message_decoded_callback))
-      || (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
-    X2AP_ERROR("[SCTP %d] Either procedureCode %ld or direction %d exceed expected\n",
-               assoc_id, pdu.choice.initiatingMessage.procedureCode, pdu.present);
-    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
-    return -1;
-  }
+  switch (pdu.present) {
 
-  /* No handler present.
-   * This can mean not implemented or no procedure for eNB (wrong direction).
-   */
-  if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
-    X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
-                assoc_id, pdu.choice.initiatingMessage.procedureCode,
-               x2ap_direction2String(pdu.present - 1));
-    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
-    return -1;
-  }
+  case X2AP_X2AP_PDU_PR_initiatingMessage:
+    /* Checking procedure Code and direction of message */
+    if (pdu.choice.initiatingMessage.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
+          x2ap_message_decoded_callback))) {
+        //|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
+      X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
+                 assoc_id, pdu.choice.initiatingMessage.procedureCode);
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+      return -1;
+    }
+
+    /* No handler present.
+     * This can mean not implemented or no procedure for eNB (wrong direction).
+     */
+    if (x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1] == NULL) {
+      X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
+                  assoc_id, pdu.choice.initiatingMessage.procedureCode,
+                 x2ap_direction2String(pdu.present - 1));
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+      return -1;
+    }
+    /* Calling the right handler */
+    ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+    break;
+
+  case X2AP_X2AP_PDU_PR_successfulOutcome:
+    /* Checking procedure Code and direction of message */
+    if (pdu.choice.successfulOutcome.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
+          x2ap_message_decoded_callback))) {
+        //|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
+      X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
+                 assoc_id, pdu.choice.successfulOutcome.procedureCode);
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+      return -1;
+    }
 
-  /* Calling the right handler */
-  ret = (*x2ap_messages_callback[pdu.choice.initiatingMessage.procedureCode][pdu.present - 1])
+    /* No handler present.
+     * This can mean not implemented or no procedure for eNB (wrong direction).
+     */
+    if (x2ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1] == NULL) {
+      X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
+                  assoc_id, pdu.choice.successfulOutcome.procedureCode,
+                 x2ap_direction2String(pdu.present - 1));
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+      return -1;
+    }
+    /* Calling the right handler */
+    ret = (*x2ap_messages_callback[pdu.choice.successfulOutcome.procedureCode][pdu.present - 1])
         (instance, assoc_id, stream, &pdu);
+    break;
+
+  case X2AP_X2AP_PDU_PR_unsuccessfulOutcome:
+    /* Checking procedure Code and direction of message */
+    if (pdu.choice.unsuccessfulOutcome.procedureCode > sizeof(x2ap_messages_callback) / (3 * sizeof(
+          x2ap_message_decoded_callback))) {
+        //|| (pdu.present > X2AP_X2AP_PDU_PR_unsuccessfulOutcome)) {
+      X2AP_ERROR("[SCTP %d] Either procedureCode %ld exceed expected\n",
+                 assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode);
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+      return -1;
+    }
+
+    /* No handler present.
+     * This can mean not implemented or no procedure for eNB (wrong direction).
+     */
+    if (x2ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1] == NULL) {
+      X2AP_ERROR("[SCTP %d] No handler for procedureCode %ld in %s\n",
+                  assoc_id, pdu.choice.unsuccessfulOutcome.procedureCode,
+                  x2ap_direction2String(pdu.present - 1));
+      ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+      return -1;
+    }
+    /* Calling the right handler */
+    ret = (*x2ap_messages_callback[pdu.choice.unsuccessfulOutcome.procedureCode][pdu.present - 1])
+        (instance, assoc_id, stream, &pdu);
+    break;
+
+  default:
+    X2AP_ERROR("[SCTP %d] Direction %d exceed expected\n",
+               assoc_id, pdu.present);
+    break;
+  }
+
   ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
   return ret;
 }
@@ -191,6 +274,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
 
   X2AP_X2SetupRequest_t              *x2SetupRequest;
   X2AP_X2SetupRequest_IEs_t          *ie;
+  ServedCells__Member                *servedCellMember;
 
   x2ap_eNB_data_t                    *x2ap_eNB_data;
   uint32_t                           eNB_id = 0;
@@ -283,6 +367,17 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
      */
   }
 
+  /* Set proper pci */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest,
+                             X2AP_ProtocolIE_ID_id_ServedCells, true);
+  if (ie->value.choice.ServedCells.list.count > 0) {
+    x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
+    for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
+      servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
+      x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI;
+    }
+  }
+
   return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data);
 }
 
@@ -295,6 +390,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
 
   X2AP_X2SetupResponse_t              *x2SetupResponse;
   X2AP_X2SetupResponse_IEs_t          *ie;
+  ServedCells__Member                 *servedCellMember;
 
   x2ap_eNB_data_t                     *x2ap_eNB_data;
   uint32_t                            eNB_id = 0;
@@ -367,6 +463,17 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
      */
   }
 
+  /* Set proper pci */
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
+                             X2AP_ProtocolIE_ID_id_ServedCells, true);
+  if (ie->value.choice.ServedCells.list.count > 0) {
+    x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
+    for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
+      servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
+      x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI;
+    }
+  }
+
   /* Optionaly set the target eNB name */
 
   /* The association is now ready as source and target eNBs know parameters of each other.
@@ -430,3 +537,165 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
 
   return 0;
 }
+
+static
+int x2ap_eNB_handle_handover_preparation (instance_t instance,
+                                          uint32_t assoc_id,
+                                          uint32_t stream,
+                                          X2AP_X2AP_PDU_t *pdu)
+{
+
+  X2AP_HandoverRequest_t             *x2HandoverRequest;
+  X2AP_HandoverRequest_IEs_t         *ie;
+
+  X2AP_E_RABs_ToBeSetup_ItemIEs_t    *e_RABS_ToBeSetup_ItemIEs;
+  X2AP_E_RABs_ToBeSetup_Item_t       *e_RABs_ToBeSetup_Item;
+
+  x2ap_eNB_data_t                    *x2ap_eNB_data;
+  MessageDef                         *msg;
+
+  DevAssert (pdu != NULL);
+  x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest;
+
+  if (stream == 0) {
+    X2AP_ERROR ("Received new x2 handover request on stream == 0\n");
+    /* TODO: send a x2 failure response */
+    return 0;
+  }
+
+  X2AP_DEBUG ("Received a new X2 handover request\n");
+
+  x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
+  DevAssert(x2ap_eNB_data != NULL);
+
+  msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ);
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
+                             X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
+  //X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
+  //X2AP_HANDOVER_REQ(m).source_x2id = x2HandoverRequest->old_eNB_UE_X2AP_ID;
+  X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = ie->value.choice.UE_X2AP_ID;
+
+  //X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
+                                               //measResultListEUTRA.list.array[ncell_index]->physCellId;
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
+                             X2AP_ProtocolIE_ID_id_GUMMEI_ID, true);
+
+  TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc,
+                  X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len);
+  OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code);
+  OCTET_STRING_TO_INT16(&ie->value.choice.GUMMEI.gU_Group_ID.mME_Group_ID, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_group_id);
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
+                             X2AP_ProtocolIE_ID_id_UE_ContextInformation, true);
+
+  X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID;
+
+  X2AP_HANDOVER_REQ(msg).target_mod_id = x2ap_eNB_data->x2ap_eNB_instance->eNB_id;
+
+  X2AP_HANDOVER_REQ(msg).security_capabilities.encryption_algorithms =
+    BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
+  X2AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms =
+    BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
+
+  //X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr;
+
+  if ((ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf) &&
+          (ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.size == 32)) {
+    memcpy(X2AP_HANDOVER_REQ(msg).kenb, ie->value.choice.UE_ContextInformation.aS_SecurityInformation.key_eNodeB_star.buf, 32);
+    X2AP_HANDOVER_REQ(msg).kenb_ncc = ie->value.choice.UE_ContextInformation.aS_SecurityInformation.nextHopChainingCount;
+  } else {
+    X2AP_WARN ("Size of eNB key star does not match the expected value\n");
+  }
+
+  if (ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count > 0) {
+
+    X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count;
+
+    for (int i=0;i<ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.count;i++) {
+      e_RABS_ToBeSetup_ItemIEs = (X2AP_E_RABs_ToBeSetup_ItemIEs_t *) ie->value.choice.UE_ContextInformation.e_RABs_ToBeSetup_List.list.array[i];
+      e_RABs_ToBeSetup_Item = &e_RABS_ToBeSetup_ItemIEs->value.choice.E_RABs_ToBeSetup_Item;
+
+      X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].e_rab_id = e_RABs_ToBeSetup_Item->e_RAB_ID ;
+
+      memcpy(X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr.buffer,
+                     e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.buf,
+                     e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size);
+
+      X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].eNB_addr.length =
+                      e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.size * 8 - e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.transportLayerAddress.bits_unused;
+
+      OCTET_STRING_TO_INT32(&e_RABs_ToBeSetup_Item->uL_GTPtunnelEndpoint.gTP_TEID,
+                                                X2AP_HANDOVER_REQ(msg).e_rabs_tobesetup[i].gtp_teid);
+
+      X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.qci = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.qCI;
+      X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.priority_level = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel;
+      X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_capability = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability;
+      X2AP_HANDOVER_REQ(msg).e_rab_param[i].qos.allocation_retention_priority.pre_emp_vulnerability = e_RABs_ToBeSetup_Item->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability;
+    }
+
+  }
+  else {
+    X2AP_ERROR ("Can't decode the e_RABs_ToBeSetup_List \n");
+  }
+
+  X2AP_RRC_Context_t *c = &ie->value.choice.UE_ContextInformation.rRC_Context;
+
+  if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
+    { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
+
+  memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
+  X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
+
+  itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
+
+  return 0;
+}
+
+static
+int x2ap_eNB_handle_handover_response (instance_t instance,
+                                       uint32_t assoc_id,
+                                       uint32_t stream,
+                                       X2AP_X2AP_PDU_t *pdu)
+{
+  X2AP_HandoverRequestAcknowledge_t             *x2HandoverRequestAck;
+  X2AP_HandoverRequestAcknowledge_IEs_t         *ie;
+
+  x2ap_eNB_data_t                               *x2ap_eNB_data;
+  MessageDef                                    *msg;
+
+  DevAssert (pdu != NULL);
+  x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
+
+  if (stream == 0) {
+    X2AP_ERROR ("Received new x2 handover response on stream == 0\n");
+    /* TODO: send a x2 failure response */
+    return 0;
+  }
+
+  X2AP_DEBUG ("Received a new X2 handover response\n");
+
+  x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
+  DevAssert(x2ap_eNB_data != NULL);
+
+
+  msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK);
+  /* TODO: fill the message */
+  //extern int x2id_to_source_rnti[1];
+  //X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID;
+  //X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
+                             X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
+
+  X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer;
+
+  if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
+    { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
+
+  memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
+  X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
+
+  itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg);
+  return 0;
+}
diff --git a/openair2/X2AP/x2ap_eNB_handler.h b/openair2/X2AP/x2ap_eNB_handler.h
index 0f93859a84213e273c3a19eac0dd158d1616212e..e4dac14e8e637078880ac10dd25b442a81cce51f 100644
--- a/openair2/X2AP/x2ap_eNB_handler.h
+++ b/openair2/X2AP/x2ap_eNB_handler.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_handler.h
+ * \brief x2ap handler procedures for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #ifndef X2AP_ENB_HANDLERS_H_
 #define X2AP_ENB_HANDLERS_H_
 
diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.c b/openair2/X2AP/x2ap_eNB_itti_messaging.c
index d8e1e19afeeae608e1d44b18784ca1ec0aa293a6..1896e3949c6adf86c9ae91a4f606b1a1b69583f8 100644
--- a/openair2/X2AP/x2ap_eNB_itti_messaging.c
+++ b/openair2/X2AP/x2ap_eNB_itti_messaging.c
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_itti_messaging.c
+ * \brief x2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include "intertask_interface.h"
 
 #include "x2ap_eNB_itti_messaging.h"
diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.h b/openair2/X2AP/x2ap_eNB_itti_messaging.h
index 55bf58b6605260c85c70b4d5887f768c42f3e49f..ee946880ac3c3b69ca51b58ee0c327260ea3ed6d 100644
--- a/openair2/X2AP/x2ap_eNB_itti_messaging.h
+++ b/openair2/X2AP/x2ap_eNB_itti_messaging.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_itti_messaging.h
+ * \brief x2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #ifndef X2AP_ENB_ITTI_MESSAGING_H_
 #define X2AP_ENB_ITTI_MESSAGING_H_
 
diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.c b/openair2/X2AP/x2ap_eNB_management_procedures.c
index c2b128ffd312c4c042dc397b992dd62ff6641bc2..670581406b9e2190ac0233bd9b5b797fc66ef521 100644
--- a/openair2/X2AP/x2ap_eNB_management_procedures.c
+++ b/openair2/X2AP/x2ap_eNB_management_procedures.c
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_management_procedures.c
+ * \brief x2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -162,6 +169,22 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
   return NULL;
 }
 
+x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci)
+{
+  x2ap_eNB_instance_t *temp = NULL;
+
+  STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
+                 x2ap_eNB_entries) {
+    for (int i=0; i<temp->num_cc;i++) {
+      if (temp->Nid_target_cell[i] == pci) {
+        /* Matching occurence */
+        return temp;
+      }
+    }
+  }
+
+  return NULL;
+}
 
 /// utility functions 
 
diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.h b/openair2/X2AP/x2ap_eNB_management_procedures.h
index b66a6d10356536508f5dad4d44a960da61a7f094..80234159515f401f439b47ed0695b9223963cc69 100644
--- a/openair2/X2AP/x2ap_eNB_management_procedures.h
+++ b/openair2/X2AP/x2ap_eNB_management_procedures.h
@@ -19,6 +19,13 @@
  *      contact@openairinterface.org
  */
 
+/*! \file x2ap_eNB_management_procedures.h
+ * \brief x2ap tasks for eNB
+ * \author Konstantinos Alexandris <Konstantinos.Alexandris@eurecom.fr>, Cedric Roux <Cedric.Roux@eurecom.fr>, Navid Nikaein <Navid.Nikaein@eurecom.fr>
+ * \date 2018
+ * \version 1.0
+ */
+
 #ifndef X2AP_ENB_MANAGEMENT_PROCEDURES_H_
 #define X2AP_ENB_MANAGEMENT_PROCEDURES_H
 
@@ -30,6 +37,8 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p);
 
 x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id);
 
+x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci);
+
 uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
 
 void x2ap_eNB_prepare_internal_data(void);
diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c
index 20c104ad1fa33a0ac7d2d43348d3e90e3debb69d..f1302d1b1bdab6fdd0e5f6813af2a237765516ce 100644
--- a/openair3/GTPV1-U/gtpv1u_eNB.c
+++ b/openair3/GTPV1-U/gtpv1u_eNB.c
@@ -150,7 +150,7 @@ gtpv1u_create_s1u_tunnel(
   const gtpv1u_enb_create_tunnel_req_t *  const create_tunnel_req_pP,
         gtpv1u_enb_create_tunnel_resp_t * const create_tunnel_resp_pP);
 
-static int
+int
 gtpv1u_delete_s1u_tunnel(
   const instance_t instanceP,
   const gtpv1u_enb_delete_tunnel_req_t * const req_pP);
@@ -911,7 +911,7 @@ int gtpv1u_update_s1u_tunnel(
 }
 
 //-----------------------------------------------------------------------------
-static int gtpv1u_delete_s1u_tunnel(
+int gtpv1u_delete_s1u_tunnel(
   const instance_t                             instanceP,
   const gtpv1u_enb_delete_tunnel_req_t * const req_pP)
 {
diff --git a/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c b/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c
index eb27189a6133b6785b43c5539e11d09573d57ed8..a654169e1614249e1cdcadbf29af6527fa56dd35 100644
--- a/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c
+++ b/openair3/GTPV1-U/nw-gtpv1u/src/NwGtpv1u.c
@@ -892,6 +892,11 @@ nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
     ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp);
     break;
 
+  case NW_GTP_END_MARKER:
+    GTPU_DEBUG("NW_GTP_END_MARKER\n");
+    ret = NW_GTPV1U_OK;
+    break;
+
   default:
     ret = NW_GTPV1U_FAILURE;
     NW_ASSERT(0);
diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c
index 2a6db4a5ce4361b08b4a9ffbd573ed6a6d13722e..727842fda98e071e163d3ffcd039133127a2f1d1 100644
--- a/openair3/S1AP/s1ap_eNB.c
+++ b/openair3/S1AP/s1ap_eNB.c
@@ -371,6 +371,12 @@ void *s1ap_eNB_task(void *arg)
     }
     break;
 
+    case S1AP_PATH_SWITCH_REQ: {
+      s1ap_eNB_path_switch_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                               &S1AP_PATH_SWITCH_REQ(received_msg));
+    }
+    break;
+
     case S1AP_UE_CONTEXT_RELEASE_COMPLETE: {
       s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg),
                                        &S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg));
diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c
index c12374f7586397c832725dab601e09e027fb48e3..82069241978a42d45d0fe6feaaf15bc60188311b 100644
--- a/openair3/S1AP/s1ap_eNB_decoder.c
+++ b/openair3/S1AP/s1ap_eNB_decoder.c
@@ -166,6 +166,16 @@ static int s1ap_eNB_decode_successful_outcome(S1AP_S1AP_PDU_t *pdu)
       free(res.buffer);
       break;
 
+    case S1AP_ProcedureCode_id_PathSwitchRequest:
+      res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
+      message_id = S1AP_S1_SETUP_LOG;
+      message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
+      message_p->ittiMsg.s1ap_s1_setup_log.size = res.result.encoded;
+      memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, res.buffer, res.result.encoded);
+      itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
+      free(res.buffer);
+      break;
+
     default:
       S1AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
                  (int)pdu->choice.successfulOutcome.procedureCode);
@@ -192,6 +202,15 @@ static int s1ap_eNB_decode_unsuccessful_outcome(S1AP_S1AP_PDU_t *pdu)
       itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
       free(res.buffer);
       break;
+   case S1AP_ProcedureCode_id_PathSwitchRequest:
+      res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
+      message_id = S1AP_S1_SETUP_LOG;
+      message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
+      message_p->ittiMsg.s1ap_s1_setup_log.size = res.result.encoded;
+      memcpy(&message_p->ittiMsg.s1ap_s1_setup_log.text, res.buffer, res.result.encoded);
+      itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
+      free(res.buffer);
+      break;
 
     default:
       S1AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
diff --git a/openair3/S1AP/s1ap_eNB_encoder.c b/openair3/S1AP/s1ap_eNB_encoder.c
index bc0c69792def7fec332f0723ed6e5e9a9d7fb640..bb0ac159e2316a0645cbb0918c686fc2bb6ea4bc 100644
--- a/openair3/S1AP/s1ap_eNB_encoder.c
+++ b/openair3/S1AP/s1ap_eNB_encoder.c
@@ -147,6 +147,16 @@ int s1ap_eNB_encode_initiating(S1AP_S1AP_PDU_t *pdu,
       free(res.buffer);
       break;
 
+    case S1AP_ProcedureCode_id_PathSwitchRequest:
+      res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_S1AP_S1AP_PDU, pdu);
+      message_id = S1AP_UE_CONTEXT_RELEASE_REQ_LOG;
+      message_p = itti_alloc_new_message_sized(TASK_S1AP, message_id, res.result.encoded + sizeof (IttiMsgText));
+      message_p->ittiMsg.s1ap_ue_context_release_req_log.size = res.result.encoded;
+      memcpy(&message_p->ittiMsg.s1ap_ue_context_release_req_log.text, res.buffer, res.result.encoded);
+      itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
+      free(res.buffer);
+      break;
+
     default:
       S1AP_DEBUG("Unknown procedure ID (%d) for initiating message\n",
                  (int)pdu->choice.initiatingMessage.procedureCode);
diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c
index 5c6b208b87336111216ec516b78448b47971aa94..ee1a57a094bf0110b395dd701cec7cfdd22952d1 100644
--- a/openair3/S1AP/s1ap_eNB_handlers.c
+++ b/openair3/S1AP/s1ap_eNB_handlers.c
@@ -93,13 +93,21 @@ static
 int s1ap_eNB_handle_e_rab_release_command(uint32_t               assoc_id,
                                           uint32_t               stream,
                                           S1AP_S1AP_PDU_t       *pdu);
+static
+int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
+                                               uint32_t               stream,
+                                               S1AP_S1AP_PDU_t       *pdu);
+static
+int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t               assoc_id,
+                                                   uint32_t               stream,
+                                                   S1AP_S1AP_PDU_t       *pdu);
 
 /* Handlers matrix. Only eNB related procedure present here */
 s1ap_message_decoded_callback messages_callback[][3] = {
   { 0, 0, 0 }, /* HandoverPreparation */
   { 0, 0, 0 }, /* HandoverResourceAllocation */
   { 0, 0, 0 }, /* HandoverNotification */
-  { 0, 0, 0 }, /* PathSwitchRequest */
+  { 0, s1ap_eNB_handle_s1_path_switch_request_ack, s1ap_eNB_handle_s1_path_switch_request_failure }, /* PathSwitchRequest */
   { 0, 0, 0 }, /* HandoverCancel */
   { s1ap_eNB_handle_e_rab_setup_request, 0, 0 }, /* E_RABSetup */
   { s1ap_eNB_handle_e_rab_modify_request, 0, 0 }, /* E_RABModify */
@@ -742,6 +750,8 @@ int s1ap_eNB_handle_initial_context_request(uint32_t   assoc_id,
 
   S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).eNB_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id;
 
+  S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).mme_ue_s1ap_id = ue_desc_p->mme_ue_s1ap_id;
+
   /* id-uEaggregateMaximumBitrate */
   S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
                              S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, true);
@@ -1400,5 +1410,234 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t               assoc_id,
 
   itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
 
+  return 0;
+}
+
+static
+int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t               assoc_id,
+					       uint32_t               stream,
+					       S1AP_S1AP_PDU_t       *pdu)
+{
+
+  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
+  s1ap_eNB_ue_context_t *ue_desc_p        = NULL;
+  MessageDef            *message_p        = NULL;
+
+  S1AP_PathSwitchRequestAcknowledge_t *pathSwitchRequestAcknowledge;
+  S1AP_PathSwitchRequestAcknowledgeIEs_t *ie;
+  S1AP_E_RABToBeSwitchedULItemIEs_t *s1ap_E_RABToBeSwitchedULItemIEs;
+  S1AP_E_RABToBeSwitchedULItem_t *s1ap_E_RABToBeSwitchedULItem;
+  S1AP_E_RABItemIEs_t  *e_RABItemIEs;
+  S1AP_E_RABItem_t     *e_RABItem;
+
+  DevAssert(pdu != NULL);
+
+  pathSwitchRequestAcknowledge = &pdu->choice.successfulOutcome.value.choice.PathSwitchRequestAcknowledge;
+
+
+  /* Path Switch request == UE-related procedure -> stream !=0 */
+  if (stream == 0) {
+    S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n",
+               assoc_id, stream);
+    return -1;
+  }
+
+  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
+    S1AP_ERROR("[SCTP %d] Received S1 path switch request ack for non existing "
+               "MME context\n", assoc_id);
+    return -1;
+  }
+
+  // send a message to RRC
+  message_p        = itti_alloc_new_message(TASK_S1AP, S1AP_PATH_SWITCH_REQ_ACK);
+
+  /* mandatory */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true);
+
+  S1AP_PATH_SWITCH_REQ_ACK(message_p).eNB_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID;
+
+  if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
+                   ie->value.choice.ENB_UE_S1AP_ID)) == NULL) {
+    S1AP_ERROR("[SCTP %d] Received path switch request ack for non "
+               "existing UE context 0x%06lx\n", assoc_id,
+               ie->value.choice.ENB_UE_S1AP_ID);
+    return -1;
+  }
+
+  S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_initial_id  = ue_desc_p->ue_initial_id;
+
+  /* mandatory */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true);
+
+  S1AP_PATH_SWITCH_REQ_ACK(message_p).mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID;
+
+  if ( ue_desc_p->mme_ue_s1ap_id != ie->value.choice.MME_UE_S1AP_ID){
+    S1AP_WARN("UE context mme_ue_s1ap_id is different form that of the message (%d != %ld)",
+              ue_desc_p->mme_ue_s1ap_id, ie->value.choice.MME_UE_S1AP_ID);
+
+  }
+
+  /* mandatory */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_SecurityContext, true);
+
+  S1AP_PATH_SWITCH_REQ_ACK(message_p).next_hop_chain_count =
+    ie->value.choice.SecurityContext.nextHopChainingCount;
+
+  memcpy(&S1AP_PATH_SWITCH_REQ_ACK(message_p).next_security_key,
+         ie->value.choice.SecurityContext.nextHopParameter.buf,
+	 ie->value.choice.SecurityContext.nextHopParameter.size);
+
+  /* optional */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false);
+
+  if (ie) {
+
+    OCTET_STRING_TO_INT32 (
+			   &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL,
+			   S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul
+			   );
+    OCTET_STRING_TO_INT32 (
+			   &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL,
+			   S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl
+			   );
+  } else {
+    S1AP_WARN("UEAggregateMaximumBitrate not supported\n");
+
+    S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0;
+    S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl = 0;
+  }
+
+  /* optional */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                            S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedULList, false);
+
+  if (ie) {
+
+    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched = ie->value.choice.E_RABToBeSwitchedULList.list.count;
+
+    for (int i = 0; i < ie->value.choice.E_RABToBeSwitchedULList.list.count; i++) {
+      s1ap_E_RABToBeSwitchedULItemIEs = (S1AP_E_RABToBeSwitchedULItemIEs_t *)ie->value.choice.E_RABToBeSwitchedULList.list.array[i];
+      s1ap_E_RABToBeSwitchedULItem = &s1ap_E_RABToBeSwitchedULItemIEs->value.choice.E_RABToBeSwitchedULItem;
+
+      S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].e_rab_id = s1ap_E_RABToBeSwitchedULItem->e_RAB_ID;
+      memcpy(S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.buffer,
+	     s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.buf, s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.size);
+      S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].sgw_addr.length =
+	s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.size * 8 - s1ap_E_RABToBeSwitchedULItem->transportLayerAddress.bits_unused;
+
+      OCTET_STRING_TO_INT32(&s1ap_E_RABToBeSwitchedULItem->gTP_TEID,
+			    S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobeswitched[i].gtp_teid);
+    }
+  }
+  else {
+    S1AP_WARN("E_RABToBeSwitchedULList not supported\n");
+    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobeswitched = 0;
+  }
+
+ /* optional */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, false);
+
+  if (ie) {
+
+    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased = ie->value.choice.E_RABList.list.count;
+
+    for (int i = 0; i < ie->value.choice.E_RABList.list.count; i++) {
+      e_RABItemIEs = (S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i];
+      e_RABItem =  &e_RABItemIEs->value.choice.E_RABItem;
+
+      S1AP_PATH_SWITCH_REQ_ACK (message_p).e_rabs_tobereleased[i].e_rab_id = e_RABItem->e_RAB_ID;
+    }
+  }
+  else {
+    S1AP_WARN("E_RABToBeReleasedList not supported\n");
+    S1AP_PATH_SWITCH_REQ_ACK(message_p).nb_e_rabs_tobereleased = 0;
+  }
+
+  /* optional */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
+  if(!ie) {
+    S1AP_WARN("Critical Diagnostic not supported\n");
+  }
+
+  /* optional */
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestAcknowledgeIEs_t, ie, pathSwitchRequestAcknowledge,
+                             S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID_2, false);
+  if(!ie) {
+    S1AP_WARN("MME_UE_S1AP_ID_2 flag not supported\n");
+  }
+
+  // TODO continue
+
+  itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
+
+  return 0;
+}
+
+static
+int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t               assoc_id,
+						   uint32_t               stream,
+						   S1AP_S1AP_PDU_t       *pdu)
+{
+
+  s1ap_eNB_mme_data_t   *mme_desc_p       = NULL;
+
+  S1AP_PathSwitchRequestFailure_t    *pathSwitchRequestFailure;
+  S1AP_PathSwitchRequestFailureIEs_t *ie;
+
+  DevAssert(pdu != NULL);
+
+  pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure;
+
+  if (stream != 0) {
+    S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n",
+               assoc_id, stream);
+    return -1;
+  }
+
+  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
+    S1AP_ERROR("[SCTP %d] Received S1 path switch request failure for non existing "
+               "MME context\n", assoc_id);
+    return -1;
+  }
+
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestFailureIEs_t, ie, pathSwitchRequestFailure,
+                             S1AP_ProtocolIE_ID_id_Cause, true);
+
+  switch(ie->value.choice.Cause.present) {
+  case S1AP_Cause_PR_NOTHING:
+    S1AP_WARN("Received S1 Error indication cause NOTHING\n");
+    break;
+  case S1AP_Cause_PR_radioNetwork:
+    S1AP_WARN("Radio Network Layer Cause Failure\n");
+    break;
+  case S1AP_Cause_PR_transport:
+    S1AP_WARN("Transport Layer Cause Failure\n");
+    break;
+  case S1AP_Cause_PR_nas:
+    S1AP_WARN("NAS Cause Failure\n");
+    break;
+  case S1AP_Cause_PR_misc:
+    S1AP_WARN("Miscelaneous Cause Failure\n");
+    break;
+  default:
+    S1AP_WARN("Received an unknown S1 Error indication cause\n");
+    break;
+  }
+
+  S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_PathSwitchRequestFailureIEs_t, ie, pathSwitchRequestFailure,
+                             S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
+
+  if(!ie) {
+    S1AP_WARN("Critical Diagnostic not supported\n");
+  }
+  // TODO continue
+
+
   return 0;
 }
diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c
index ebd5bab4fdd8e1b80ec8a61025fafac4501c19ed..be17ce5b6e011a726da96966610cfdee09c68567 100644
--- a/openair3/S1AP/s1ap_eNB_nas_procedures.c
+++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c
@@ -1586,3 +1586,240 @@ int s1ap_eNB_e_rab_release_resp(instance_t instance,
 
   return 0;
 }
+
+int s1ap_eNB_path_switch_req(instance_t instance,
+                             s1ap_path_switch_req_t *path_switch_req_p)
+//------------------------------------------------------------------------------
+{
+  s1ap_eNB_instance_t          *s1ap_eNB_instance_p = NULL;
+  struct s1ap_eNB_ue_context_s *ue_context_p        = NULL;
+  struct s1ap_eNB_mme_data_s   *mme_desc_p = NULL;
+
+  S1AP_S1AP_PDU_t                 pdu;
+  S1AP_PathSwitchRequest_t       *out;
+  S1AP_PathSwitchRequestIEs_t    *ie;
+
+  S1AP_E_RABToBeSwitchedDLItemIEs_t *e_RABToBeSwitchedDLItemIEs;
+  S1AP_E_RABToBeSwitchedDLItem_t    *e_RABToBeSwitchedDLItem;
+
+  uint8_t  *buffer = NULL;
+  uint32_t length;
+  int      ret = 0;//-1;
+
+  /* Retrieve the S1AP eNB instance associated with Mod_id */
+  s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance);
+
+  DevAssert(path_switch_req_p != NULL);
+  DevAssert(s1ap_eNB_instance_p != NULL);
+
+  //if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
+    //                                          path_switch_req_p->eNB_ue_s1ap_id)) == NULL) {
+    /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
+    //S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: 0x%06x\n",
+      //        path_switch_req_p->eNB_ue_s1ap_id);
+    //return -1;
+  //}
+
+  /* Uplink NAS transport can occur either during an s1ap connected state
+   * or during initial attach (for example: NAS authentication).
+   */
+  //if (!(ue_context_p->ue_state == S1AP_UE_CONNECTED ||
+       // ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) {
+    //S1AP_WARN("You are attempting to send NAS data over non-connected "
+        //      "eNB ue s1ap id: %06x, current state: %d\n",
+          //    path_switch_req_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
+    //return -1;
+  //}
+
+  /* Select the MME corresponding to the provided GUMMEI. */
+  mme_desc_p = s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_p, path_switch_req_p->ue_gummei);
+
+  if (mme_desc_p == NULL) {
+    /*
+     * In case eNB has no MME associated, the eNB should inform RRC and discard
+     * this request.
+     */
+
+    S1AP_WARN("No MME is associated to the eNB\n");
+    // TODO: Inform RRC
+    return -1;
+  }
+
+  /* The eNB should allocate a unique eNB UE S1AP ID for this UE. The value
+   * will be used for the duration of the connectivity.
+   */
+  ue_context_p = s1ap_eNB_allocate_new_UE_context();
+  DevAssert(ue_context_p != NULL);
+
+  /* Keep a reference to the selected MME */
+  ue_context_p->mme_ref       = mme_desc_p;
+  ue_context_p->ue_initial_id = path_switch_req_p->ue_initial_id;
+  ue_context_p->eNB_instance  = s1ap_eNB_instance_p;
+
+  do {
+    struct s1ap_eNB_ue_context_s *collision_p;
+
+    /* Peek a random value for the eNB_ue_s1ap_id */
+    ue_context_p->eNB_ue_s1ap_id = (random() + random()) & 0x00ffffff;
+
+    if ((collision_p = RB_INSERT(s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head, ue_context_p))
+        == NULL) {
+      S1AP_DEBUG("Found usable eNB_ue_s1ap_id: 0x%06x %d(10)\n",
+                 ue_context_p->eNB_ue_s1ap_id,
+                 ue_context_p->eNB_ue_s1ap_id);
+      /* Break the loop as the id is not already used by another UE */
+      break;
+    }
+  } while(1);
+
+  ue_context_p->mme_ue_s1ap_id = path_switch_req_p->mme_ue_s1ap_id;
+
+  /* Prepare the S1AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_PathSwitchRequest;
+  pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_PathSwitchRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.PathSwitchRequest;
+
+  /* mandatory */
+  ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID;
+  ie->criticality = S1AP_Criticality_reject;
+  ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_ENB_UE_S1AP_ID;
+  ie->value.choice.ENB_UE_S1AP_ID = ue_context_p->eNB_ue_s1ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  if (path_switch_req_p->nb_of_e_rabs > 0) {
+    ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
+    ie->id = S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedDLList;
+    ie->criticality = S1AP_Criticality_reject;
+    ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_E_RABToBeSwitchedDLList;
+
+    for (int i = 0; i < path_switch_req_p->nb_of_e_rabs; i++) {
+      e_RABToBeSwitchedDLItemIEs = (S1AP_E_RABToBeSwitchedDLItemIEs_t *)calloc(1, sizeof(S1AP_E_RABToBeSwitchedDLItemIEs_t));
+      e_RABToBeSwitchedDLItemIEs->id = S1AP_ProtocolIE_ID_id_E_RABToBeSwitchedDLItem;
+      e_RABToBeSwitchedDLItemIEs->criticality = S1AP_Criticality_reject;
+      e_RABToBeSwitchedDLItemIEs->value.present = S1AP_E_RABToBeSwitchedDLItemIEs__value_PR_E_RABToBeSwitchedDLItem;
+
+      e_RABToBeSwitchedDLItem = &e_RABToBeSwitchedDLItemIEs->value.choice.E_RABToBeSwitchedDLItem;
+      e_RABToBeSwitchedDLItem->e_RAB_ID = path_switch_req_p->e_rabs_tobeswitched[i].e_rab_id;
+      INT32_TO_OCTET_STRING(path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid, &e_RABToBeSwitchedDLItem->gTP_TEID);
+
+      e_RABToBeSwitchedDLItem->transportLayerAddress.size  = path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.length;
+      e_RABToBeSwitchedDLItem->transportLayerAddress.bits_unused = 0;
+
+      e_RABToBeSwitchedDLItem->transportLayerAddress.buf = calloc(1,e_RABToBeSwitchedDLItem->transportLayerAddress.size);
+
+      memcpy (e_RABToBeSwitchedDLItem->transportLayerAddress.buf,
+                path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.buffer,
+                path_switch_req_p->e_rabs_tobeswitched[i].eNB_addr.length);
+
+      S1AP_DEBUG("path_switch_req: e_rab ID %ld, teid %u, enb_addr %d.%d.%d.%d, SIZE %zu\n",
+               e_RABToBeSwitchedDLItem->e_RAB_ID,
+               path_switch_req_p->e_rabs_tobeswitched[i].gtp_teid,
+               e_RABToBeSwitchedDLItem->transportLayerAddress.buf[0],
+               e_RABToBeSwitchedDLItem->transportLayerAddress.buf[1],
+               e_RABToBeSwitchedDLItem->transportLayerAddress.buf[2],
+               e_RABToBeSwitchedDLItem->transportLayerAddress.buf[3],
+               e_RABToBeSwitchedDLItem->transportLayerAddress.size);
+
+      ASN_SEQUENCE_ADD(&ie->value.choice.E_RABToBeSwitchedDLList.list, e_RABToBeSwitchedDLItemIEs);
+    }
+
+    ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+  }
+
+  /* mandatory */
+  ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_SourceMME_UE_S1AP_ID;
+  ie->criticality = S1AP_Criticality_reject;
+  ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_MME_UE_S1AP_ID;
+  ie->value.choice.MME_UE_S1AP_ID = path_switch_req_p->mme_ue_s1ap_id;
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_EUTRAN_CGI;
+  ie->criticality = S1AP_Criticality_ignore;
+  ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_EUTRAN_CGI;
+  MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
+                                0,
+                                &ie->value.choice.EUTRAN_CGI.cell_ID);
+  MCC_MNC_TO_TBCD(s1ap_eNB_instance_p->mcc,
+                  s1ap_eNB_instance_p->mnc,
+                  s1ap_eNB_instance_p->mnc_digit_length,
+                  &ie->value.choice.EUTRAN_CGI.pLMNidentity);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_TAI;
+  ie->criticality = S1AP_Criticality_ignore;
+  ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_TAI;
+  /* Assuming TAI is the TAI from the cell */
+  INT16_TO_OCTET_STRING(s1ap_eNB_instance_p->tac, &ie->value.choice.TAI.tAC);
+  MCC_MNC_TO_PLMNID(s1ap_eNB_instance_p->mcc,
+                    s1ap_eNB_instance_p->mnc,
+                    s1ap_eNB_instance_p->mnc_digit_length,
+                    &ie->value.choice.TAI.pLMNidentity);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (S1AP_PathSwitchRequestIEs_t *)calloc(1, sizeof(S1AP_PathSwitchRequestIEs_t));
+  ie->id = S1AP_ProtocolIE_ID_id_UESecurityCapabilities;
+  ie->criticality = S1AP_Criticality_ignore;
+  ie->value.present = S1AP_PathSwitchRequestIEs__value_PR_UESecurityCapabilities;
+  ENCRALG_TO_BIT_STRING(path_switch_req_p->security_capabilities.encryption_algorithms,
+              &ie->value.choice.UESecurityCapabilities.encryptionAlgorithms);
+  INTPROTALG_TO_BIT_STRING(path_switch_req_p->security_capabilities.integrity_algorithms,
+              &ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (s1ap_eNB_encode_pdu(&pdu, &buffer, &length) < 0) {
+    S1AP_ERROR("Failed to encode Path Switch Req \n");
+    /* Encode procedure has failed... */
+    return -1;
+  }
+
+  /* Update the current S1AP UE state */
+  ue_context_p->ue_state = S1AP_UE_WAITING_CSR;
+
+  /* Assign a stream for this UE :
+   * From 3GPP 36.412 7)Transport layers:
+   *  Within the SCTP association established between one MME and eNB pair:
+   *  - a single pair of stream identifiers shall be reserved for the sole use
+   *      of S1AP elementary procedures that utilize non UE-associated signalling.
+   *  - At least one pair of stream identifiers shall be reserved for the sole use
+   *      of S1AP elementary procedures that utilize UE-associated signallings.
+   *      However a few pairs (i.e. more than one) should be reserved.
+   *  - A single UE-associated signalling shall use one SCTP stream and
+   *      the stream should not be changed during the communication of the
+   *      UE-associated signalling.
+   */
+  mme_desc_p->nextstream = (mme_desc_p->nextstream + 1) % mme_desc_p->out_streams;
+
+  if ((mme_desc_p->nextstream == 0) && (mme_desc_p->out_streams > 1)) {
+    mme_desc_p->nextstream += 1;
+  }
+
+  ue_context_p->tx_stream = mme_desc_p->nextstream;
+
+  MSC_LOG_TX_MESSAGE(
+    MSC_S1AP_ENB,
+    MSC_S1AP_MME,
+    (const char *)buffer,
+    length,
+    MSC_AS_TIME_FMT" E_RAN Setup successfulOutcome eNB_ue_s1ap_id %u mme_ue_s1ap_id %u",
+    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
+    ue_context_p->eNB_ue_s1ap_id,
+    path_switch_req_p->mme_ue_s1ap_id);
+
+  /* UE associated signalling -> use the allocated stream */
+  s1ap_eNB_itti_send_sctp_data_req(s1ap_eNB_instance_p->instance,
+                                   mme_desc_p->assoc_id, buffer,
+                                   length, ue_context_p->tx_stream);
+
+  return ret;
+}
diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.h b/openair3/S1AP/s1ap_eNB_nas_procedures.h
index a7f144c0ca3653ab0a2665f8d1be619a1fe9d1a5..c4257198727a042cfacd7eeafac65e1dfc36a232 100644
--- a/openair3/S1AP/s1ap_eNB_nas_procedures.h
+++ b/openair3/S1AP/s1ap_eNB_nas_procedures.h
@@ -49,4 +49,7 @@ int s1ap_eNB_e_rab_modify_resp(instance_t instance,
 
 int s1ap_eNB_e_rab_release_resp(instance_t instance,
                                 s1ap_e_rab_release_resp_t *e_rab_release_resp_p);
+
+int s1ap_eNB_path_switch_req(instance_t instance,
+                             s1ap_path_switch_req_t *path_switch_req_p);
 #endif /* S1AP_ENB_NAS_PROCEDURES_H_ */
diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c
index 8b7d65cb011194b3846dea521bf0e6bcd0c4bd89..3fba5c202168856d9e6f2989a799c2db56764103 100644
--- a/openair3/S1AP/s1ap_eNB_nnsf.c
+++ b/openair3/S1AP/s1ap_eNB_nnsf.c
@@ -255,3 +255,79 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t       *instance_p,
    */
   return mme_highest_capacity_p;
 }
+
+
+struct s1ap_eNB_mme_data_s *
+s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_t       *instance_p,
+                                            s1ap_gummei_t                   gummei)
+{
+  struct s1ap_eNB_mme_data_s *mme_data_p             = NULL;
+  struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL;
+  uint8_t                     current_capacity       = 0;
+
+  RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) {
+    struct served_gummei_s *gummei_p = NULL;
+
+    if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) {
+      /* The association between MME and eNB is not ready for the moment,
+       * go to the next known MME.
+       */
+      if (mme_data_p->state == S1AP_ENB_OVERLOAD) {
+        /* MME is overloaded. We have to check the RRC establishment
+         * cause and take decision to the select this MME depending on
+         * the overload state.
+         */
+    } else {
+        /* The MME is not overloaded, association is simply not ready. */
+        continue;
+      }
+    }
+
+    if (current_capacity < mme_data_p->relative_mme_capacity) {
+      /* We find a better MME, keep a reference to it */
+      current_capacity = mme_data_p->relative_mme_capacity;
+      mme_highest_capacity_p = mme_data_p;
+    }
+
+    /* Looking for MME gummei matching the one provided by NAS */
+    STAILQ_FOREACH(gummei_p, &mme_data_p->served_gummei, next) {
+      struct served_group_id_s *group_id_p = NULL;
+      struct mme_code_s        *mme_code_p = NULL;
+      struct plmn_identity_s   *served_plmn_p = NULL;
+
+      STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) {
+        if ((served_plmn_p->mcc == gummei.mcc) &&
+            (served_plmn_p->mnc == gummei.mnc)) {
+          break;
+        }
+      }
+      STAILQ_FOREACH(mme_code_p, &gummei_p->mme_codes, next) {
+        if (mme_code_p->mme_code == gummei.mme_code) {
+          break;
+        }
+      }
+      STAILQ_FOREACH(group_id_p, &gummei_p->served_group_ids, next) {
+        if (group_id_p->mme_group_id == gummei.mme_group_id) {
+          break;
+        }
+      }
+
+      /* The MME matches the parameters provided by the NAS layer ->
+      * the MME is knwown and the association is ready.
+      * Return the reference to the MME to use it for this UE.
+      */
+      if ((group_id_p != NULL) &&
+          (mme_code_p != NULL) &&
+          (served_plmn_p != NULL)) {
+        return mme_data_p;
+      }
+    }
+  }
+
+  /* At this point no MME matches the provided GUMMEI. Select the one with the
+   * highest relative capacity.
+   * In case the list of known MME is empty, simply return NULL, that way the RRC
+   * layer should know about it and reject RRC connectivity.
+   */
+  return mme_highest_capacity_p;
+}
diff --git a/openair3/S1AP/s1ap_eNB_nnsf.h b/openair3/S1AP/s1ap_eNB_nnsf.h
index 78405f34d1b17e0995cfa70e91c57b98cf087786..871684f6581385e58c8e58ab23160c159cefc0c0 100644
--- a/openair3/S1AP/s1ap_eNB_nnsf.h
+++ b/openair3/S1AP/s1ap_eNB_nnsf.h
@@ -36,4 +36,8 @@ s1ap_eNB_nnsf_select_mme_by_gummei(s1ap_eNB_instance_t       *instance_p,
                                    rrc_establishment_cause_t  cause,
                                    s1ap_gummei_t                   gummei);
 
+struct s1ap_eNB_mme_data_s*
+s1ap_eNB_nnsf_select_mme_by_gummei_no_cause(s1ap_eNB_instance_t       *instance_p,
+                                   s1ap_gummei_t                   gummei);
+
 #endif /* S1AP_ENB_NNSF_H_ */
diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h
index 00287341b2a19f06af32ae4a136d329b73d694b2..f1f1d2550a146a18b1ae8dbd53dfb5dbcfc4d39f 100644
--- a/openair3/UTILS/conversions.h
+++ b/openair3/UTILS/conversions.h
@@ -131,6 +131,54 @@ do {                                            \
 #define M_TMSI_TO_OCTET_STRING   INT32_TO_OCTET_STRING
 #define MME_GID_TO_OCTET_STRING  INT16_TO_OCTET_STRING
 
+#define ENCRALG_TO_BIT_STRING(encralg, bitstring)    \
+    do {                        \
+    (bitstring)->size=2;                \
+    (bitstring)->bits_unused=0;            \
+    (bitstring)->buf=calloc (1, sizeof (uint8_t));    \
+    (bitstring)->buf[0] = (encralg) >> 8;         \
+    (bitstring)->buf[1] = (encralg);        \
+    }while(0)
+
+#define INTPROTALG_TO_BIT_STRING(intprotalg, bitstring)    \
+do {                                \
+    (bitstring)->size=2;                    \
+    (bitstring)->bits_unused=0;                \
+    (bitstring)->buf=calloc (2, sizeof (uint8_t));        \
+    (bitstring)->buf[0] = (intprotalg) >> 8;         \
+    (bitstring)->buf[1] = (intprotalg);            \
+}while(0)
+
+#define KENB_STAR_TO_BIT_STRING(kenbstar, bitstring)    \
+do {                            \
+    (bitstring)->size=32;                \
+    (bitstring)->bits_unused=0;            \
+    (bitstring)->buf= calloc (32, sizeof (uint8_t));\
+    memcpy((bitstring)->buf, kenbstar, 32*sizeof(uint8_t));            \
+}while(0)
+
+#define UEAGMAXBITRTD_TO_ASN_PRIMITIVES(uegmaxbitrtd, asnprimitives)        \
+do {                                         \
+    (asnprimitives)->size=5;                        \
+    (asnprimitives)->buf=calloc (5, sizeof (uint8_t));            \
+    (asnprimitives)->buf[0] = (uegmaxbitrtd) >> 32;                \
+    (asnprimitives)->buf[1] = (uegmaxbitrtd) >> 24;                \
+    (asnprimitives)->buf[2] = (uegmaxbitrtd) >> 16;                \
+    (asnprimitives)->buf[3] = (uegmaxbitrtd) >> 8;                \
+    (asnprimitives)->buf[4] = (uegmaxbitrtd);                \
+ }while(0)
+
+#define UEAGMAXBITRTU_TO_ASN_PRIMITIVES(uegmaxbitrtu, asnprimitives)        \
+do {                                         \
+    (asnprimitives)->size=5;                        \
+    (asnprimitives)->buf=calloc (5, sizeof (uint8_t));            \
+    (asnprimitives)->buf[0] = (uegmaxbitrtu) >> 32;                \
+    (asnprimitives)->buf[1] = (uegmaxbitrtu) >> 24;                \
+    (asnprimitives)->buf[2] = (uegmaxbitrtu) >> 16;                \
+    (asnprimitives)->buf[3] = (uegmaxbitrtu) >> 8;                \
+    (asnprimitives)->buf[4] = (uegmaxbitrtu);                \
+ }while(0)
+
 #define OCTET_STRING_TO_INT8(aSN, x)    \
 do {                                    \
     DevCheck((aSN)->size == 1, (aSN)->size, 0, 0);           \