diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 8683dfd2e169618dfb245add84ee52cf856f14a3..5bf07dae01f1a792cd3465453139495f9815578a 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -474,12 +474,12 @@ include_directories ("${X2AP_DIR}")
 
 add_library(X2AP_ENB
   ${X2AP_DIR}/x2ap_eNB.c
- # ${X2AP_DIR}/x2ap_eNB_decoder.c
- # ${X2AP_DIR}/x2ap_eNB_encoder.c
+  ${X2AP_DIR}/x2ap_eNB_decoder.c
+  ${X2AP_DIR}/x2ap_eNB_encoder.c
   ${X2AP_DIR}/x2ap_eNB_handler.c
- # ${X2AP_DIR}/x2ap_eNB_itti_messaging.c
+  ${X2AP_DIR}/x2ap_eNB_itti_messaging.c
   ${X2AP_DIR}/x2ap_eNB_management_procedures.c
- # ${X2AP_DIR}/x2ap_eNB_generate_messages.c
+  ${X2AP_DIR}/x2ap_eNB_generate_messages.c
  )
 
 # Hardware dependant options
diff --git a/common/utils/msc/msc.h b/common/utils/msc/msc.h
index 78eb6cdb080665290f80474328110f79a1d61f28..e8a8a4a0e82d7f65f9b9fcd80b54ddc79cff2759 100644
--- a/common/utils/msc/msc.h
+++ b/common/utils/msc/msc.h
@@ -63,6 +63,8 @@ typedef enum {
     MSC_S6A_MME,
     MSC_HSS,
     MAX_MSC_PROTOS,
+    MSC_X2AP_SRC_ENB,
+    MSC_X2AP_TARGET_ENB,
 } msc_proto_t;
 
 
diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h
index 6c4031b981df42869d76abbe210bb88289a27115..c74a826ff84685c88ea9a36b6226ccbf58eee166 100644
--- a/openair2/COMMON/x2ap_messages_types.h
+++ b/openair2/COMMON/x2ap_messages_types.h
@@ -63,17 +63,21 @@ typedef struct x2ap_register_enb_req_s {
   uint8_t  mnc_digit_length;
 
   /*
-   * EARFCN
+   * CC Params
    */
-  uint16_t fdd_uL_EARFCN;
-  uint16_t fdd_dL_EARFCN;
-  uint16_t tdd_EARFCN;
-
-
-  uint16_t fdd_uL_Transmission_Bandwidth;
-  uint16_t fdd_dL_Transmission_Bandwidth;
-  uint16_t tdd_Transmission_Bandwidth;
-
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_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];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
+  /* To be considered for TDD */
+  //uint16_t tdd_EARFCN;
+  //uint16_t tdd_Transmission_Bandwidth;
 
   /* The local eNB IP address to bind */
   net_ip_address_t enb_x2_ip_address;
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index dd995a53a043c2fb4afda8844a84e12054cd5961..2506a0a9dca71261a67156ec4bcec93ec5b648e6 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -65,6 +65,8 @@ extern void set_parallel_conf(char* parallel_conf);
 extern void set_worker_conf(char* worker_conf);
 extern PARALLEL_CONF_t get_thread_parallel_conf(void);
 extern WORKER_CONF_t   get_thread_worker_conf(void);
+extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
+extern uint32_t to_earfcn_UL(int eutra_bandP, uint32_t ul_CarrierFreq, uint32_t bw);
 
 void RCconfig_flexran() {
   uint16_t i;
@@ -2172,7 +2174,7 @@ int RCconfig_S1(MessageDef *msg_p, uint32_t i) {
 }
 
 int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
-  int   j, k, l;
+  int   I, J, j, k, l;
   int   enb_id;
   char *address = NULL;
   char *cidr    = NULL;
@@ -2181,21 +2183,104 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
   paramlist_def_t ENBParamList = {ENB_CONFIG_STRING_ENB_LIST,NULL,0};
   /* get global parameters, defined outside any section in the config file */
   config_get( ENBSParams,sizeof(ENBSParams)/sizeof(paramdef_t),NULL);
-  /*#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
-      if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
-        asn_debug      = 0;
-        asn1_xer_print = 0;
-      } else if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) {
-        asn_debug      = 1;
-        asn1_xer_print = 1;
-      } else if (strcasecmp(*(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr) , ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) {
-        asn_debug      = 1;
-        asn1_xer_print = 2;
-      } else {
-        asn_debug      = 0;
-        asn1_xer_print = 0;
-      }
-    #endif */
+
+  /* define CC params */
+
+  int32_t Nid_cell = 0;
+
+  char *frame_type, *prefix_type, *pbch_repetition, *prach_high_speed,
+    *pusch_hoppingMode, *pusch_enable64QAM, *pusch_groupHoppingEnabled,
+    *pusch_sequenceHoppingEnabled, *phich_duration, *phich_resource,
+    *srs_enable, *srs_ackNackST, *srs_MaxUpPts, *pusch_alpha,
+    *pucch_deltaF_Format1, *pucch_deltaF_Format1b, *pucch_deltaF_Format2,
+    *pucch_deltaF_Format2a, *pucch_deltaF_Format2b,
+    *rach_preamblesGroupAConfig, *rach_messagePowerOffsetGroupB, *pcch_nB;
+  long long int     downlink_frequency;
+  int32_t tdd_config, tdd_config_s, eutra_band, uplink_frequency_offset,
+    Nid_cell_mbsfn, N_RB_DL, nb_antenna_ports, prach_root, prach_config_index,
+    prach_zero_correlation, prach_freq_offset, pucch_delta_shift,
+    pucch_nRB_CQI, pucch_nCS_AN, pucch_n1_AN, pdsch_referenceSignalPower,
+    pdsch_p_b, pusch_n_SB, pusch_hoppingOffset, pusch_groupAssignment,
+    pusch_nDMRS1, srs_BandwidthConfig, srs_SubframeConfig, pusch_p0_Nominal,
+    pucch_p0_Nominal, msg3_delta_Preamble, rach_numberOfRA_Preambles,
+    rach_sizeOfRA_PreamblesGroupA, rach_messageSizeGroupA,
+    rach_powerRampingStep, rach_preambleInitialReceivedTargetPower,
+    rach_preambleTransMax, rach_raResponseWindowSize,
+    rach_macContentionResolutionTimer, rach_maxHARQ_Msg3Tx,
+    pcch_defaultPagingCycle, bcch_modificationPeriodCoeff,
+    ue_TimersAndConstants_t300, ue_TimersAndConstants_t301,
+    ue_TimersAndConstants_t310, ue_TimersAndConstants_t311,
+    ue_TimersAndConstants_n310, ue_TimersAndConstants_n311,
+    ue_TransmissionMode, ue_multiple_max;
+
+  const char*       rxPool_sc_CP_Len;
+  const char*       rxPool_sc_Period;
+  const char*       rxPool_data_CP_Len;
+  libconfig_int     rxPool_ResourceConfig_prb_Num;
+  libconfig_int     rxPool_ResourceConfig_prb_Start;
+  libconfig_int     rxPool_ResourceConfig_prb_End;
+  const char*       rxPool_ResourceConfig_offsetIndicator_present;
+  libconfig_int     rxPool_ResourceConfig_offsetIndicator_choice;
+  const char*       rxPool_ResourceConfig_subframeBitmap_present;
+  char*             rxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
+  libconfig_int     rxPool_ResourceConfig_subframeBitmap_choice_bs_size;
+  libconfig_int     rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+  //SIB19
+  //for discRxPool
+  const char*       discRxPool_cp_Len;
+  const char*       discRxPool_discPeriod;
+  libconfig_int     discRxPool_numRetx;
+  libconfig_int     discRxPool_numRepetition;
+  libconfig_int     discRxPool_ResourceConfig_prb_Num;
+  libconfig_int     discRxPool_ResourceConfig_prb_Start;
+  libconfig_int     discRxPool_ResourceConfig_prb_End;
+  const char*       discRxPool_ResourceConfig_offsetIndicator_present;
+  libconfig_int     discRxPool_ResourceConfig_offsetIndicator_choice;
+  const char*       discRxPool_ResourceConfig_subframeBitmap_present;
+  char*             discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf;
+  libconfig_int     discRxPool_ResourceConfig_subframeBitmap_choice_bs_size;
+  libconfig_int     discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+  //for discRxPoolPS
+  const char*       discRxPoolPS_cp_Len;
+  const char*       discRxPoolPS_discPeriod;
+  libconfig_int     discRxPoolPS_numRetx;
+  libconfig_int     discRxPoolPS_numRepetition;
+  libconfig_int     discRxPoolPS_ResourceConfig_prb_Num;
+  libconfig_int     discRxPoolPS_ResourceConfig_prb_Start;
+  libconfig_int     discRxPoolPS_ResourceConfig_prb_End;
+  const char*       discRxPoolPS_ResourceConfig_offsetIndicator_present;
+  libconfig_int     discRxPoolPS_ResourceConfig_offsetIndicator_choice;
+  const char*       discRxPoolPS_ResourceConfig_subframeBitmap_present;
+  char*             discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_buf;
+  libconfig_int     discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_size;
+  libconfig_int     discRxPoolPS_ResourceConfig_subframeBitmap_choice_bs_bits_unused;
+
+  checkedparam_t config_check_CCparams[] = CCPARAMS_CHECK;
+  paramdef_t CCsParams[] = CCPARAMS_DESC;
+  paramlist_def_t CCsParamList = {ENB_CONFIG_STRING_COMPONENT_CARRIERS, NULL, 0};
+
+  /* map parameter checking array instances to parameter definition array instances */
+  for (I = 0; I < (sizeof(CCsParams) / sizeof(paramdef_t)); I++) {
+    CCsParams[I].chkPptr = &(config_check_CCparams[I]);
+  }
+/*#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
+    if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
+      asn_debug      = 0;
+      asn1_xer_print = 0;
+    } else if (strcasecmp( *(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr), ENB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) {
+      asn_debug      = 1;
+      asn1_xer_print = 1;
+    } else if (strcasecmp(*(ENBSParams[ENB_ASN1_VERBOSITY_IDX].strptr) , ENB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) {
+      asn_debug      = 1;
+      asn1_xer_print = 2;
+    } else {
+      asn_debug      = 0;
+      asn1_xer_print = 0;
+    }
+#endif */
+
   AssertFatal(i < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt,
               "Failed to parse config file %s, %uth attribute %s \n",
               RC.config_file_name, i, ENB_CONFIG_STRING_ACTIVE_ENBS);
@@ -2226,7 +2311,9 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
             paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0};
             paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
             paramdef_t NETParams[]  =  NETPARAMS_DESC;
-            char aprefix[MAX_OPTNAME_SIZE*2 + 8];
+            /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */
+            /* this is most probably a problem with the config module */
+            char aprefix[MAX_OPTNAME_SIZE*80 + 8];
             /* Some default/random parameters */
             X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id;
 
@@ -2249,6 +2336,56 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
                         (X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length == 3),
                         "BAD MNC DIGIT LENGTH %d",
                         X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length);
+
+            /* CC params */
+            sprintf(aprefix, "%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k);
+            config_getlist(&CCsParamList, NULL, 0, aprefix);
+
+            X2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt;
+
+            if (CCsParamList.numelt > 0) {
+
+              //char ccspath[MAX_OPTNAME_SIZE*2 + 16];
+
+              for (J = 0; J < CCsParamList.numelt ; J++) {
+
+                sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J);
+                config_get(CCsParams, sizeof(CCsParams)/sizeof(paramdef_t), aprefix);
+
+                X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = eutra_band;
+	        X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) downlink_frequency;
+	        X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) uplink_frequency_offset;
+	        X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= Nid_cell;
+
+	        if (Nid_cell>503) {
+	          AssertFatal (0,
+	            "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n",
+                         RC.config_file_name, k, Nid_cell);
+	        }
+
+	        X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= N_RB_DL;
+
+	        if ((N_RB_DL!=6) && (N_RB_DL!=15) && (N_RB_DL!=25) && (N_RB_DL!=50) && (N_RB_DL!=75) && (N_RB_DL!=100)) {
+	          AssertFatal (0,
+                    "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n",
+                         RC.config_file_name, k, N_RB_DL);
+	        }
+
+	        if (strcmp(frame_type, "FDD") == 0) {
+                  X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD;
+	        } else  if (strcmp(frame_type, "TDD") == 0) {
+                  X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
+                } else {
+	          AssertFatal (0,
+                    "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n",
+		         RC.config_file_name, k, frame_type);
+	        }
+
+                X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(eutra_band, downlink_frequency, N_RB_DL);
+                X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(eutra_band, downlink_frequency + uplink_frequency_offset, N_RB_DL);
+              }
+            }
+
             sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k);
             config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix);
 
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index 5331f07a6883a7ebbbb0b0bf4f432711a3660e38..0b4f05a56e1883374afc17d50a35d9ee7a69bd4e 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -160,6 +160,58 @@ uint32_t to_earfcn(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw)
 	  (eutra_bandtable[i].N_OFFs_DL / 10));
 }
 
+uint32_t to_earfcn_DL(int eutra_bandP, long long int dl_CarrierFreq, uint32_t bw)
+{
+
+  uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq / 100000;
+  int bw_by_100 = bw / 100;
+
+  int i;
+
+  AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP);
+  for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++);
+
+  AssertFatal(dl_CarrierFreq_by_100k >= eutra_bandtable[i].dl_min,
+              "Band %d, bw %u : DL carrier frequency %lld Hz < %u\n",
+              eutra_bandP, bw, dl_CarrierFreq,
+              eutra_bandtable[i].dl_min);
+  AssertFatal(dl_CarrierFreq_by_100k <=
+              (eutra_bandtable[i].dl_max - bw_by_100),
+              "Band %d, bw %u : DL carrier frequency %lld Hz > %d\n",
+              eutra_bandP, bw, dl_CarrierFreq,
+              eutra_bandtable[i].dl_max - bw_by_100);
+
+
+  return (dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min +
+          (eutra_bandtable[i].N_OFFs_DL / 10));
+}
+
+uint32_t to_earfcn_UL(int eutra_bandP, long long int ul_CarrierFreq, uint32_t bw)
+{
+
+  uint32_t ul_CarrierFreq_by_100k = ul_CarrierFreq / 100000;
+  int bw_by_100 = bw / 100;
+
+  int i;
+
+  AssertFatal(eutra_bandP < 69, "eutra_band %d > 68\n", eutra_bandP);
+  for (i = 0; i < 69 && eutra_bandtable[i].band != eutra_bandP; i++);
+
+  AssertFatal(ul_CarrierFreq_by_100k >= eutra_bandtable[i].ul_min,
+              "Band %d, bw %u : UL carrier frequency %lld Hz < %u\n",
+              eutra_bandP, bw, ul_CarrierFreq,
+              eutra_bandtable[i].ul_min);
+  AssertFatal(ul_CarrierFreq_by_100k <=
+              (eutra_bandtable[i].ul_max - bw_by_100),
+              "Band %d, bw %u : UL carrier frequency %lld Hz > %d\n",
+              eutra_bandP, bw, ul_CarrierFreq,
+              eutra_bandtable[i].ul_max - bw_by_100);
+
+
+  return (ul_CarrierFreq_by_100k - eutra_bandtable[i].ul_min +
+          ((eutra_bandtable[i].N_OFFs_DL + 180000) / 10));
+}
+
 uint32_t from_earfcn(int eutra_bandP, uint32_t dl_earfcn)
 {
 
diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h
index ceda1c8eb96e04a3a7e4509d460a4396be2be85b..a2f903a73725f812b44314e02408ad40ceed145f 100644
--- a/openair2/X2AP/x2ap_common.h
+++ b/openair2/X2AP/x2ap_common.h
@@ -28,12 +28,12 @@
 #include "X2AP_InitiatingMessage.h"
 #include "X2AP_SuccessfulOutcome.h"
 #include "X2AP_UnsuccessfulOutcome.h"
-#include "X2AP_ProtocolIE-Field.h"
 #include "X2AP_ProtocolIE-FieldPair.h"
 #include "X2AP_ProtocolIE-ContainerPair.h"
 #include "X2AP_ProtocolExtensionField.h"
 #include "X2AP_ProtocolExtensionContainer.h"
 #include "X2AP_asn_constant.h"
+#include "intertask_interface.h"
 
 #ifndef X2AP_COMMON_H_
 #define X2AP_COMMON_H_
@@ -87,15 +87,13 @@ extern int asn1_xer_print;
     if (mandatory) DevAssert(ie != NULL); \
   } while(0)
 
-//Forward declaration
-struct x2ap_message_s;
-
 /** \brief Function callback prototype.
  **/
 typedef int (*x2ap_message_decoded_callback)(
+  instance_t instance,
   uint32_t assocId,
   uint32_t stream,
-  struct x2ap_message_s *message);
+  X2AP_X2AP_PDU_t *pdu);
 
 /** \brief Encode a successfull outcome message
  \param buffer pointer to buffer in which data will be encoded
diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c
index a1469509a90563acf4e6dd3546a74056a600cb3a..d12dfa881979b9a3841471ed236b64ff4475c621 100644
--- a/openair2/X2AP/x2ap_eNB.c
+++ b/openair2/X2AP/x2ap_eNB.c
@@ -31,6 +31,7 @@
 #include "x2ap_eNB_defs.h"
 #include "x2ap_eNB_management_procedures.h"
 #include "x2ap_eNB_handler.h"
+#include "x2ap_eNB_generate_messages.h"
 #include "x2ap_common.h"
 
 #include "queue.h"
@@ -42,9 +43,9 @@ struct x2ap_eNB_data_s;
 
 RB_PROTOTYPE(x2ap_enb_map, x2ap_eNB_data_s, entry, x2ap_eNB_compare_assoc_id);
 
-//static
-//void x2ap_eNB_handle_sctp_data_ind(instance_t instance,
-  //                                 sctp_data_ind_t *sctp_data_ind);
+static
+void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind);
+
 static
 void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
 
@@ -63,22 +64,21 @@ 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_sctp_data_ind(instance_t instance,
-				   sctp_data_ind_t *sctp_data_ind) {
+void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
 
   int result;
 
   DevAssert(sctp_data_ind != NULL);
 
-  x2ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream,
+  x2ap_eNB_handle_message(instance, sctp_data_ind->assoc_id, sctp_data_ind->stream,
                           sctp_data_ind->buffer, sctp_data_ind->buffer_length);
 
   result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer);
   AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
 
-}*/
+}
 
 static
 void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
@@ -143,7 +143,7 @@ printf("x2ap_eNB_handle_sctp_association_resp at 4\n");
 dump_trees();
 
   /* Prepare new x2 Setup Request */
-  //x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
+  x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
 }
 
 static
@@ -325,6 +325,19 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
     new_instance->mnc              = x2ap_register_eNB->mnc;
     new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length;
 
+    new_instance->num_cc           = x2ap_register_eNB->num_cc;
+
+    for (int i = 0; i< x2ap_register_eNB->num_cc; i++){
+      new_instance->eutra_band[i]              = x2ap_register_eNB->eutra_band[i];
+      new_instance->downlink_frequency[i]      = x2ap_register_eNB->downlink_frequency[i];
+      new_instance->uplink_frequency_offset[i] = x2ap_register_eNB->uplink_frequency_offset[i];
+      new_instance->Nid_cell[i]                = x2ap_register_eNB->Nid_cell[i];
+      new_instance->N_RB_DL[i]                 = x2ap_register_eNB->N_RB_DL[i];
+      new_instance->frame_type[i]              = x2ap_register_eNB->frame_type[i];
+      new_instance->fdd_earfcn_DL[i]           = x2ap_register_eNB->fdd_earfcn_DL[i];
+      new_instance->fdd_earfcn_UL[i]           = x2ap_register_eNB->fdd_earfcn_UL[i];
+    }
+
     DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS,
              X2AP_MAX_NB_ENB_IP_ADDRESS, x2ap_register_eNB->nb_x2, 0);
     memcpy(new_instance->target_enb_x2_ip_address,
@@ -432,8 +445,8 @@ void *x2ap_task(void *arg)
       break;
 
     case SCTP_DATA_IND:
-      //x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
-	//			    &received_msg->ittiMsg.sctp_data_ind);
+      x2ap_eNB_handle_sctp_data_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg),
+                                           &received_msg->ittiMsg.sctp_data_ind);
       break;
 
     default:
diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..f156d96d175beab05523d01625cd34324bc1e1a5
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_decoder.c
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include <stdio.h>
+
+#include "assertions.h"
+#include "intertask_interface.h"
+#include "x2ap_common.h"
+#include "x2ap_eNB_decoder.h"
+
+static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  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);
+      X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
+      break;
+
+    default:
+      X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
+                  (int)pdu->choice.initiatingMessage.procedureCode);
+      AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n",
+                   (int)pdu->choice.initiatingMessage.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int x2ap_eNB_decode_successful_outcome(X2AP_X2AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  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);
+      X2AP_INFO("x2ap_eNB_decode_successfuloutcome_message!\n");
+      break;
+
+    default:
+      X2AP_ERROR("Unknown procedure ID (%d) for successfull outcome message\n",
+                  (int)pdu->choice.successfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+static int x2ap_eNB_decode_unsuccessful_outcome(X2AP_X2AP_PDU_t *pdu)
+{
+  DevAssert(pdu != NULL);
+
+  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);
+      X2AP_INFO("x2ap_eNB_decode_unsuccessfuloutcome_message!\n");
+      break;
+
+    default:
+       X2AP_ERROR("Unknown procedure ID (%d) for unsuccessfull outcome message\n",
+                  (int)pdu->choice.unsuccessfulOutcome.procedureCode);
+      return -1;
+  }
+
+  return 0;
+}
+
+int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+{
+  asn_dec_rval_t dec_ret;
+
+  DevAssert(buffer != NULL);
+
+  dec_ret = aper_decode(NULL,
+                        &asn_DEF_X2AP_X2AP_PDU,
+                        (void **)&pdu,
+                        buffer,
+                        length,
+                        0,
+                        0);
+
+  xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, pdu);
+
+  if (dec_ret.code != RC_OK) {
+    X2AP_ERROR("Failed to decode pdu\n");
+    return -1;
+  }
+
+  switch(pdu->present) {
+    case X2AP_X2AP_PDU_PR_initiatingMessage:
+      return x2ap_eNB_decode_initiating_message(pdu);
+
+    case X2AP_X2AP_PDU_PR_successfulOutcome:
+      return x2ap_eNB_decode_successful_outcome(pdu);
+
+    case X2AP_X2AP_PDU_PR_unsuccessfulOutcome:
+      return x2ap_eNB_decode_unsuccessful_outcome(pdu);
+
+    default:
+      X2AP_DEBUG("Unknown presence (%d) or not implemented\n", (int)pdu->present);
+      break;
+  }
+
+
+  return -1;
+}
diff --git a/openair2/X2AP/x2ap_eNB_decoder.h b/openair2/X2AP/x2ap_eNB_decoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ce9ea3d40ef039a9c36c45163bdeb2969b0b9fb
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_decoder.h
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef X2AP_ENB_DECODER_H_
+#define X2AP_ENB_DECODER_H_
+
+int x2ap_eNB_decode_pdu(X2AP_X2AP_PDU_t *pdu, const uint8_t *const buffer, uint32_t length)
+__attribute__ ((warn_unused_result));
+
+#endif /* X2AP_ENB_DECODER_H_ */
+
diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h
index 11b4434dc0ae5c1146aff0faa151d18664c8f779..3014290206913e516b046bfc5dbab94fa64397b1 100644
--- a/openair2/X2AP/x2ap_eNB_defs.h
+++ b/openair2/X2AP/x2ap_eNB_defs.h
@@ -151,6 +151,17 @@ typedef struct x2ap_eNB_instance_s {
   uint16_t  mnc;
   uint8_t   mnc_digit_length;
 
+  /* CC params */
+  int16_t                 eutra_band[MAX_NUM_CCs];
+  uint32_t                downlink_frequency[MAX_NUM_CCs];
+  int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
+  uint32_t                Nid_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];
+  uint32_t                fdd_earfcn_UL[MAX_NUM_CCs];
+  int                     num_cc;
+
   net_ip_address_t target_enb_x2_ip_address[X2AP_MAX_NB_ENB_IP_ADDRESS];
   uint8_t          nb_x2;
   net_ip_address_t enb_x2_ip_address;
diff --git a/openair2/X2AP/x2ap_eNB_encoder.c b/openair2/X2AP/x2ap_eNB_encoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..1eb617a7f1ddec817a88648fe25ddbef2ac9ad7c
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_encoder.c
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "assertions.h"
+#include "conversions.h"
+#include "intertask_interface.h"
+#include "x2ap_common.h"
+#include "x2ap_eNB_encoder.h"
+
+int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+{
+  ssize_t    encoded;
+
+  DevAssert(pdu != NULL);
+  DevAssert(buffer != NULL);
+  DevAssert(len != NULL);
+
+  if (asn1_xer_print) {
+    xer_fprint(stdout, &asn_DEF_X2AP_X2AP_PDU, (void *)pdu);
+  }
+
+  encoded = aper_encode_to_new_buffer(&asn_DEF_X2AP_X2AP_PDU, 0, pdu, (void **)buffer);
+
+  if (encoded < 0) {
+    return -1;
+  }
+
+  *len = encoded;
+
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, pdu);
+  return encoded;
+}
diff --git a/openair2/X2AP/x2ap_eNB_encoder.h b/openair2/X2AP/x2ap_eNB_encoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..04c77583b4f27c05fcc723100784bf418bf26c3a
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_encoder.h
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef X2AP_ENB_ENCODER_H_
+#define X2AP_ENB_ENCODER_H_
+
+int x2ap_eNB_encode_pdu(X2AP_X2AP_PDU_t *pdu, uint8_t **buffer, uint32_t *len)
+__attribute__ ((warn_unused_result));
+
+#endif /* X2AP_ENB_ENCODER_H_ */
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c5a281506730409d8cf9b7048e4d68b90e826a7
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.c
@@ -0,0 +1,405 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "intertask_interface.h"
+
+#include "x2ap_common.h"
+#include "x2ap_eNB.h"
+#include "x2ap_eNB_generate_messages.h"
+#include "x2ap_eNB_encoder.h"
+
+#include "x2ap_eNB_itti_messaging.h"
+
+#include "msc.h"
+#include "assertions.h"
+#include "conversions.h"
+
+int x2ap_eNB_generate_x2_setup_request(
+  x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p)
+{
+  X2AP_X2AP_PDU_t                     pdu;
+  X2AP_X2SetupRequest_t              *out;
+  X2AP_X2SetupRequest_IEs_t          *ie;
+  X2AP_PLMN_Identity_t               *plmn;
+  ServedCells__Member                *servedCellMember;
+  X2AP_GU_Group_ID_t                 *gu;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  DevAssert(instance_p != NULL);
+  DevAssert(x2ap_eNB_data_p != NULL);
+
+  x2ap_eNB_data_p->state = X2AP_ENB_STATE_WAITING;
+
+  /* Prepare the X2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_initiatingMessage;
+  pdu.choice.initiatingMessage.procedureCode = X2AP_ProcedureCode_id_x2Setup;
+  pdu.choice.initiatingMessage.criticality = X2AP_Criticality_reject;
+  pdu.choice.initiatingMessage.value.present = X2AP_InitiatingMessage__value_PR_X2SetupRequest;
+  out = &pdu.choice.initiatingMessage.value.choice.X2SetupRequest;
+
+  /* mandatory */
+  ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_GlobalENB_ID;
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                    &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+  ie->value.choice.GlobalENB_ID.eNB_ID.present = X2AP_ENB_ID_PR_macro_eNB_ID;
+  MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+                             &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+  X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+            ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+            ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+            ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_ServedCells;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_ServedCells;
+  {
+    for (int i = 0; i<instance_p->num_cc; i++){
+      servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+      {
+        servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+
+        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                      &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+        MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+                                   &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+        INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+        plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t));
+        {
+          MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+          ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+        }
+
+	if (instance_p->frame_type[i] == FDD) {
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD;
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+          switch (instance_p->N_RB_DL[i]) {
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
+              break;
+            case 15:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
+              break;
+            case 25:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
+              break;
+            case 50:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
+              break;
+            case 75:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
+              break;
+            case 100:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+              break;
+          }
+        }
+        else {
+          AssertFatal(0,"X2Setuprequest not supported for TDD!");
+        }
+      }
+      ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+    }
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_X2SetupRequest_IEs_t *)calloc(1, sizeof(X2AP_X2SetupRequest_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_GUGroupIDList;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_X2SetupRequest_IEs__value_PR_GUGroupIDList;
+  {
+    gu = (X2AP_GU_Group_ID_t *)calloc(1, sizeof(X2AP_GU_Group_ID_t));
+    {
+      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                    &gu->pLMN_Identity);
+      //@TODO: consider to update this value
+      INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+    }
+    ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode X2 setup request\n");
+    return -1;
+  }
+
+  MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/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, 0);
+
+  return ret;
+}
+
+int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p)
+{
+  X2AP_X2AP_PDU_t                     pdu;
+  X2AP_X2SetupResponse_t              *out;
+  X2AP_X2SetupResponse_IEs_t          *ie;
+  X2AP_PLMN_Identity_t                *plmn;
+  ServedCells__Member                 *servedCellMember;
+  X2AP_GU_Group_ID_t                  *gu;
+
+  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 message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_successfulOutcome;
+  pdu.choice.successfulOutcome.procedureCode = X2AP_ProcedureCode_id_x2Setup;
+  pdu.choice.successfulOutcome.criticality = X2AP_Criticality_reject;
+  pdu.choice.successfulOutcome.value.present = X2AP_SuccessfulOutcome__value_PR_X2SetupResponse;
+  out = &pdu.choice.successfulOutcome.value.choice.X2SetupResponse;
+
+  /* mandatory */
+  ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_GlobalENB_ID;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_GlobalENB_ID;
+  MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                    &ie->value.choice.GlobalENB_ID.pLMN_Identity);
+  ie->value.choice.GlobalENB_ID.eNB_ID.present = X2AP_ENB_ID_PR_macro_eNB_ID;
+  MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
+                             &ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID);
+  X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
+            ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[0],
+            ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[1],
+            ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf[2]);
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_ServedCells;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_ServedCells;
+  {
+    for (int i = 0; i<instance_p->num_cc; i++){
+      servedCellMember = (ServedCells__Member *)calloc(1,sizeof(ServedCells__Member));
+      {
+        servedCellMember->servedCellInfo.pCI = instance_p->Nid_cell[i];
+
+        MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                      &servedCellMember->servedCellInfo.cellId.pLMN_Identity);
+        MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,0,
+                                   &servedCellMember->servedCellInfo.cellId.eUTRANcellIdentifier);
+
+        INT16_TO_OCTET_STRING(instance_p->tac, &servedCellMember->servedCellInfo.tAC);
+        plmn = (X2AP_PLMN_Identity_t *)calloc(1,sizeof(X2AP_PLMN_Identity_t));
+        {
+          MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
+          ASN_SEQUENCE_ADD(&servedCellMember->servedCellInfo.broadcastPLMNs.list, plmn);
+        }
+
+	if (instance_p->frame_type[i] == FDD) {
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.present = X2AP_EUTRA_Mode_Info_PR_fDD;
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = instance_p->fdd_earfcn_DL[i];
+          servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = instance_p->fdd_earfcn_UL[i];
+          switch (instance_p->N_RB_DL[i]) {
+            case 6:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw6;
+              break;
+            case 15:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw15;
+              break;
+            case 25:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw25;
+              break;
+            case 50:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw50;
+              break;
+            case 75:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw75;
+              break;
+            case 100:
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
+              servedCellMember->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = X2AP_Transmission_Bandwidth_bw100;
+              break;
+            default:
+              AssertFatal(0,"Failed: Check value for N_RB_DL/N_RB_UL");
+              break;
+          }
+        }
+        else {
+          AssertFatal(0,"X2Setupresponse not supported for TDD!");
+        }
+      }
+      ASN_SEQUENCE_ADD(&ie->value.choice.ServedCells.list, servedCellMember);
+    }
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* mandatory */
+  ie = (X2AP_X2SetupResponse_IEs_t *)calloc(1, sizeof(X2AP_X2SetupResponse_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_GUGroupIDList;
+  ie->criticality = X2AP_Criticality_reject;
+  ie->value.present = X2AP_X2SetupResponse_IEs__value_PR_GUGroupIDList;
+  {
+    gu = (X2AP_GU_Group_ID_t *)calloc(1, sizeof(X2AP_GU_Group_ID_t));
+    {
+      MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
+                    &gu->pLMN_Identity);
+      //@TODO: consider to update this value
+      INT16_TO_OCTET_STRING(0, &gu->mME_Group_ID);
+    }
+    ASN_SEQUENCE_ADD(&ie->value.choice.GUGroupIDList.list, gu);
+  }
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode X2 setup response\n");
+    return -1;
+  }
+
+  x2ap_eNB_data_p->state = X2AP_ENB_STATE_READY;
+
+  MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/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, 0);
+
+  return ret;
+}
+
+int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
+                                       uint32_t assoc_id,
+                                       X2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait)
+{
+  X2AP_X2AP_PDU_t                     pdu;
+  X2AP_X2SetupFailure_t              *out;
+  X2AP_X2SetupFailure_IEs_t          *ie;
+
+  uint8_t  *buffer;
+  uint32_t  len;
+  int       ret = 0;
+
+  /* Prepare the X2AP message to encode */
+  memset(&pdu, 0, sizeof(pdu));
+  pdu.present = X2AP_X2AP_PDU_PR_unsuccessfulOutcome;
+  pdu.choice.unsuccessfulOutcome.procedureCode = X2AP_ProcedureCode_id_x2Setup;
+  pdu.choice.unsuccessfulOutcome.criticality = X2AP_Criticality_reject;
+  pdu.choice.unsuccessfulOutcome.value.present = X2AP_UnsuccessfulOutcome__value_PR_X2SetupFailure;
+  out = &pdu.choice.unsuccessfulOutcome.value.choice.X2SetupFailure;
+
+  /* mandatory */
+  ie = (X2AP_X2SetupFailure_IEs_t *)calloc(1, sizeof(X2AP_X2SetupFailure_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_Cause;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_X2SetupFailure_IEs__value_PR_Cause;
+
+  x2ap_eNB_set_cause (&ie->value.choice.Cause, cause_type, cause_value);
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  /* optional: consider to handle this later */
+  ie = (X2AP_X2SetupFailure_IEs_t *)calloc(1, sizeof(X2AP_X2SetupFailure_IEs_t));
+  ie->id = X2AP_ProtocolIE_ID_id_TimeToWait;
+  ie->criticality = X2AP_Criticality_ignore;
+  ie->value.present = X2AP_X2SetupFailure_IEs__value_PR_TimeToWait;
+
+  if (time_to_wait > -1) {
+    ie->value.choice.TimeToWait = time_to_wait;
+  }
+
+  ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
+
+  if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
+    X2AP_ERROR("Failed to encode X2 setup failure\n");
+    return -1;
+  }
+
+  MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB,
+                      MSC_X2AP_TARGET_ENB, NULL, 0,
+                      "0 X2Setup/unsuccessfulOutcome  assoc_id %u cause %u value %u",
+                      assoc_id, cause_type, cause_value);
+
+  x2ap_eNB_itti_send_sctp_data_req(instance, assoc_id, buffer, len, 0);
+
+  return ret;
+}
+
+int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
+                        X2AP_Cause_PR cause_type,
+                        long cause_value)
+{
+
+  DevAssert (cause_p != NULL);
+  cause_p->present = cause_type;
+
+  switch (cause_type) {
+  case X2AP_Cause_PR_radioNetwork:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case X2AP_Cause_PR_transport:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case X2AP_Cause_PR_protocol:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  case X2AP_Cause_PR_misc:
+    cause_p->choice.misc = cause_value;
+    break;
+
+  default:
+    return -1;
+  }
+
+  return 0;
+}
diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h
new file mode 100644
index 0000000000000000000000000000000000000000..a72b37e743da4ff24bdd8cd827ec0ffaeec47713
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_generate_messages.h
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef X2AP_ENB_GENERATE_MESSAGES_H_
+#define X2AP_ENB_GENERATE_MESSAGES_H_
+
+#include "x2ap_eNB_defs.h"
+#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);
+
+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,
+                                       X2AP_Cause_PR cause_type,
+                                       long cause_value,
+                                       long time_to_wait);
+
+int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
+                        X2AP_Cause_PR cause_type,
+                        long cause_value);
+
+#endif /*  X2AP_ENB_GENERATE_MESSAGES_H_ */
+
diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c
index 180535baa69d932ab85e59ffe40940a4cc362ba6..a16a3da5a8ac9d3b5fd998875fed3e61cd8cc5fc 100644
--- a/openair2/X2AP/x2ap_eNB_handler.c
+++ b/openair2/X2AP/x2ap_eNB_handler.c
@@ -27,12 +27,72 @@
 #include "x2ap_common.h"
 #include "x2ap_eNB_defs.h"
 #include "x2ap_eNB_handler.h"
+#include "x2ap_eNB_decoder.h"
 
 #include "x2ap_eNB_management_procedures.h"
+#include "x2ap_eNB_generate_messages.h"
 
+#include "msc.h"
 #include "assertions.h"
 #include "conversions.h"
 
+static
+int x2ap_eNB_handle_x2_setup_request (instance_t instance,
+                                      uint32_t assoc_id,
+                                      uint32_t stream,
+                                      X2AP_X2AP_PDU_t *pdu);
+static
+int x2ap_eNB_handle_x2_setup_response (instance_t instance,
+                                       uint32_t assoc_id,
+                                       uint32_t stream,
+                                       X2AP_X2AP_PDU_t *pdu);
+static
+int x2ap_eNB_handle_x2_setup_failure (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 */
+  { 0, 0, 0 }, /* handoverCancel */
+  { 0, 0, 0 }, /* loadIndication */
+  { 0, 0, 0 }, /* errorIndication */
+  { 0, 0, 0 }, /* snStatusTransfer */
+  { 0, 0, 0 }, /* uEContextRelease */
+  { x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */
+  { 0, 0, 0 }, /* reset */
+  { 0, 0, 0 }, /* eNBConfigurationUpdate */
+  { 0, 0, 0 }, /* resourceStatusReportingInitiation */
+  { 0, 0, 0 }, /* resourceStatusReporting */
+  { 0, 0, 0 }, /* privateMessage */
+  { 0, 0, 0 }, /* mobilitySettingsChange */
+  { 0, 0, 0 }, /* rLFIndication */
+  { 0, 0, 0 }, /* handoverReport */
+  { 0, 0, 0 }, /* cellActivation */
+  { 0, 0, 0 }, /* x2Release */
+  { 0, 0, 0 }, /* x2APMessageTransfer */
+  { 0, 0, 0 }, /* x2Removal */
+  { 0, 0, 0 }, /* seNBAdditionPreparation */
+  { 0, 0, 0 }, /* seNBReconfigurationCompletion */
+  { 0, 0, 0 }, /* meNBinitiatedSeNBModificationPreparation */
+  { 0, 0, 0 }, /* seNBinitiatedSeNBModification */
+  { 0, 0, 0 }, /* meNBinitiatedSeNBRelease */
+  { 0, 0, 0 }, /* seNBinitiatedSeNBRelease */
+  { 0, 0, 0 }, /* seNBCounterCheck */
+  { 0, 0, 0 }  /* retrieveUEContext */
+};
+
+char *x2ap_direction2String(int x2ap_dir) {
+static char *x2ap_direction_String[] = {
+  "", /* Nothing */
+  "Originating message", /* originating message */
+  "Successfull outcome", /* successfull outcome */
+  "UnSuccessfull outcome", /* successfull outcome */
+};
+return(x2ap_direction_String[x2ap_dir]);
+}
+
 void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown)
 {
   if (sctp_shutdown) {
@@ -77,3 +137,296 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown
     }
   }
 }
+
+
+int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                                const uint8_t *const data, const uint32_t data_length)
+{
+  X2AP_X2AP_PDU_t pdu;
+  int ret;
+
+  DevAssert(data != NULL);
+
+  memset(&pdu, 0, sizeof(pdu));
+
+  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;
+  }
+
+  /* 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);
+  ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_X2AP_X2AP_PDU, &pdu);
+  return ret;
+}
+
+int
+x2ap_eNB_handle_x2_setup_request(instance_t instance,
+                                 uint32_t assoc_id,
+                                 uint32_t stream,
+                                 X2AP_X2AP_PDU_t *pdu)
+{
+
+  X2AP_X2SetupRequest_t              *x2SetupRequest;
+  X2AP_X2SetupRequest_IEs_t          *ie;
+
+  x2ap_eNB_data_t                    *x2ap_eNB_data;
+  uint32_t                           eNB_id = 0;
+
+  DevAssert (pdu != NULL);
+  x2SetupRequest = &pdu->choice.initiatingMessage.value.choice.X2SetupRequest;
+
+  /*
+   * We received a new valid X2 Setup Request on a stream != 0.
+   * * * * This should not happen -> reject eNB x2 setup request.
+   */
+
+  if (stream != 0) {
+    X2AP_ERROR("Received new x2 setup request on stream != 0\n");
+      /*
+       * Send a x2 setup failure with protocol cause unspecified
+       */
+    return x2ap_eNB_generate_x2_setup_failure (instance,
+                                               assoc_id,
+                                               X2AP_Cause_PR_protocol,
+                                               X2AP_CauseProtocol_unspecified,
+                                               -1);
+  }
+
+  X2AP_DEBUG("Received a new X2 setup request\n");
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest,
+                             X2AP_ProtocolIE_ID_id_GlobalENB_ID, true);
+
+  if (ie->value.choice.GlobalENB_ID.eNB_ID.present == X2AP_ENB_ID_PR_home_eNB_ID) {
+    // Home eNB ID = 28 bits
+    uint8_t  *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
+
+    if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
+      //TODO: handle case were size != 28 -> notify ? reject ?
+    }
+
+    eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
+    X2AP_DEBUG("Home eNB id: %07x\n", eNB_id);
+  } else {
+    // Macro eNB = 20 bits
+    uint8_t *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
+
+    if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
+      //TODO: handle case were size != 20 -> notify ? reject ?
+    }
+
+    eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
+    X2AP_DEBUG("macro eNB id: %05x\n", eNB_id);
+  }
+
+  X2AP_DEBUG("Adding eNB to the list of associated eNBs\n");
+
+  if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
+      /*
+       * eNB has not been found in list of associated eNB,
+       * * * * Add it to the tail of list and initialize data
+       */
+    if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
+      /*
+       * ??
+       */
+      return -1;
+    } else {
+      x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
+      x2ap_eNB_data->eNB_id = eNB_id;
+    }
+  } else {
+    x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
+    /*
+     * eNB has been found in list, consider the x2 setup request as a reset connection,
+     * * * * reseting any previous UE state if sctp association is != than the previous one
+     */
+    if (x2ap_eNB_data->assoc_id != assoc_id) {
+      /*
+       * ??: Send an overload cause...
+       */
+      X2AP_ERROR("Rejecting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id);
+
+      DevAssert(x2ap_eNB_data->x2ap_eNB_instance != NULL);
+      x2ap_eNB_generate_x2_setup_failure (x2ap_eNB_data->x2ap_eNB_instance->instance,
+                                          assoc_id,
+                                          X2AP_Cause_PR_protocol,
+                                          X2AP_CauseProtocol_unspecified,
+                                          -1);
+      return -1;
+    }
+    /*
+     * TODO: call the reset procedure
+     */
+  }
+
+  return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data);
+}
+
+static
+int x2ap_eNB_handle_x2_setup_response(instance_t instance,
+                                      uint32_t assoc_id,
+                                      uint32_t stream,
+                                      X2AP_X2AP_PDU_t *pdu)
+{
+
+  X2AP_X2SetupResponse_t              *x2SetupResponse;
+  X2AP_X2SetupResponse_IEs_t          *ie;
+
+  x2ap_eNB_data_t                     *x2ap_eNB_data;
+  uint32_t                            eNB_id = 0;
+
+  DevAssert (pdu != NULL);
+  x2SetupResponse = &pdu->choice.successfulOutcome.value.choice.X2SetupResponse;
+
+  /*
+   * We received a new valid X2 Setup Response on a stream != 0.
+   * * * * This should not happen -> reject eNB x2 setup response.
+   */
+
+  if (stream != 0) {
+    X2AP_ERROR("Received new x2 setup response on stream != 0\n");
+  }
+
+  if ((x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0)) == NULL) {
+    X2AP_ERROR("[SCTP %d] Received X2 setup response for non existing "
+               "eNB context\n", assoc_id);
+    return -1;
+  }
+
+  X2AP_DEBUG("Received a new X2 setup response\n");
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
+                             X2AP_ProtocolIE_ID_id_GlobalENB_ID, true);
+
+  if (ie->value.choice.GlobalENB_ID.eNB_ID.present == X2AP_ENB_ID_PR_home_eNB_ID) {
+    // Home eNB ID = 28 bits
+    uint8_t  *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
+
+    if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
+      //TODO: handle case were size != 28 -> notify ? reject ?
+    }
+
+    eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
+    X2AP_DEBUG("Home eNB id: %07x\n", eNB_id);
+  } else {
+    // Macro eNB = 20 bits
+    uint8_t *eNB_id_buf = ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
+
+    if (ie->value.choice.GlobalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
+      //TODO: handle case were size != 20 -> notify ? reject ?
+    }
+
+    eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
+    X2AP_DEBUG("macro eNB id: %05x\n", eNB_id);
+  }
+
+  X2AP_DEBUG("Adding eNB to the list of associated eNBs\n");
+
+  if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
+      /*
+       * eNB has not been found in list of associated eNB,
+       * * * * Add it to the tail of list and initialize data
+       */
+    if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
+      /*
+       * ??: Send an overload cause...
+       */
+      return -1;
+    } else {
+      x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
+      x2ap_eNB_data->eNB_id = eNB_id;
+    }
+  } else {
+    x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
+    /*
+     * TODO: call the reset procedure
+     */
+  }
+
+  /* Optionaly set the target eNB name */
+
+  /* The association is now ready as source and target eNBs know parameters of each other.
+   * Mark the association as connected.
+   */
+  x2ap_eNB_data->state = X2AP_ENB_STATE_READY;
+  x2ap_eNB_data->x2ap_eNB_instance->x2_target_enb_associated_nb ++;
+  x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
+
+  return 0;
+}
+
+static
+int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
+                                     uint32_t assoc_id,
+                                     uint32_t stream,
+                                     X2AP_X2AP_PDU_t *pdu)
+{
+
+  X2AP_X2SetupFailure_t              *x2SetupFailure;
+  X2AP_X2SetupFailure_IEs_t          *ie;
+
+  x2ap_eNB_data_t                    *x2ap_eNB_data;
+
+  DevAssert(pdu != NULL);
+
+  x2SetupFailure = &pdu->choice.unsuccessfulOutcome.value.choice.X2SetupFailure;
+
+  /*
+   * We received a new valid X2 Setup Failure on a stream != 0.
+   * * * * This should not happen -> reject eNB x2 setup failure.
+  */
+
+  if (stream != 0) {
+    X2AP_WARN("[SCTP %d] Received x2 setup failure on stream != 0 (%d)\n",
+    assoc_id, stream);
+  }
+
+  if ((x2ap_eNB_data = x2ap_get_eNB (NULL, assoc_id, 0)) == NULL) {
+    X2AP_ERROR("[SCTP %d] Received X2 setup failure for non existing "
+    "eNB context\n", assoc_id);
+    return -1;
+  }
+
+  X2AP_DEBUG("Received a new X2 setup failure\n");
+
+  X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure,
+                             X2AP_ProtocolIE_ID_id_Cause, true);
+
+
+  // need a FSM to handle all cases
+  if ((ie->value.choice.Cause.present == X2AP_Cause_PR_misc) &&
+      (ie->value.choice.Cause.choice.misc == X2AP_CauseMisc_unspecified)) {
+    X2AP_WARN("Received X2 setup failure for eNB ... eNB is not ready\n");
+  } else {
+    X2AP_ERROR("Received x2 setup failure for eNB... please check your parameters\n");
+  }
+
+  x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;
+  x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
+
+  return 0;
+}
diff --git a/openair2/X2AP/x2ap_eNB_handler.h b/openair2/X2AP/x2ap_eNB_handler.h
index 6d65c25a0a01e73bf7b543831b918508237dfc5e..0f93859a84213e273c3a19eac0dd158d1616212e 100644
--- a/openair2/X2AP/x2ap_eNB_handler.h
+++ b/openair2/X2AP/x2ap_eNB_handler.h
@@ -24,10 +24,10 @@
 
 #include "x2ap_eNB_defs.h"
 
-void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *mme_desc_p, int sctp_shutdown);
+void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
 
-//int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
-  //                          const uint8_t * const data, const uint32_t data_length);
+int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
+                            const uint8_t * const data, const uint32_t data_length);
 
 #endif /* X2AP_ENB_HANDLERS_H_ */
 
diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.c b/openair2/X2AP/x2ap_eNB_itti_messaging.c
new file mode 100644
index 0000000000000000000000000000000000000000..d8e1e19afeeae608e1d44b18784ca1ec0aa293a6
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_itti_messaging.c
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "intertask_interface.h"
+
+#include "x2ap_eNB_itti_messaging.h"
+
+void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream)
+{
+  MessageDef      *message_p;
+  sctp_data_req_t *sctp_data_req;
+
+  message_p = itti_alloc_new_message(TASK_X2AP, SCTP_DATA_REQ);
+
+  sctp_data_req = &message_p->ittiMsg.sctp_data_req;
+
+  sctp_data_req->assoc_id      = assoc_id;
+  sctp_data_req->buffer        = buffer;
+  sctp_data_req->buffer_length = buffer_length;
+  sctp_data_req->stream        = stream;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
+
+void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
+{
+  MessageDef               *message_p = NULL;
+  sctp_close_association_t *sctp_close_association_p = NULL;
+
+  message_p = itti_alloc_new_message(TASK_X2AP, SCTP_CLOSE_ASSOCIATION);
+  sctp_close_association_p = &message_p->ittiMsg.sctp_close_association;
+  sctp_close_association_p->assoc_id      = assoc_id;
+
+  itti_send_msg_to_task(TASK_SCTP, instance, message_p);
+}
+
diff --git a/openair2/X2AP/x2ap_eNB_itti_messaging.h b/openair2/X2AP/x2ap_eNB_itti_messaging.h
new file mode 100644
index 0000000000000000000000000000000000000000..55bf58b6605260c85c70b4d5887f768c42f3e49f
--- /dev/null
+++ b/openair2/X2AP/x2ap_eNB_itti_messaging.h
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef X2AP_ENB_ITTI_MESSAGING_H_
+#define X2AP_ENB_ITTI_MESSAGING_H_
+
+void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
+                                      uint32_t buffer_length, uint16_t stream);
+
+
+void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id);
+
+
+#endif /* X2AP_ENB_ITTI_MESSAGING_H_ */